AMS一个很重要的系统服务,安卓的四大组件都与之关联,这里便深入了解下它。

知识点

android 启动关联app 安卓应用关联启动_AMS

一、AMS关联类

Android 7.0和Android 8.0对于AMS相关部分处理有较大的区别,为了更好地理解AMS家族,这里将分别介绍Android 7.0和Android 8.0的AMS关联类。

1、Android 7.0的AMS关联类

简介
  • ActivityManager:主要对运行中的Activity进行管理。管理工作实际并不是由ActivityManager来处理的,而是交由AMS来处理的。
  • ActivityManagerNative :简称AMN。是一个抽象类,其功能由他的子类AMS处理。其getDefault方法可得到ActivityManagerProxy(简称AMP)。ActivityManager通过AMP与AMN通信。
  • ActivityManagerProxy:AMN的内部类、AMS的代理类。
  • ActivityManagerService:系统服务,运行在SystemSever进程。AMS作为系统服务,很多API是不会暴露给ActivityManager的。

接下来看下AMS在安卓7.0中Activity启动过程中的使用,这里就从Activity的startActivity看起,最终会调用Instrumentation的execStartActivity

public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {

...
  try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess(who);
            int result = ActivityManagerNative.getDefault()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, options);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;

}

可以看到,execStartActivity方法中会调用AMN的getDefault来获取AMS的代理类AMP。接着调用了AMP的startActivity方法,先来查看AMN的getDefault方法做了什么:

AMN 类中:

static public IActivityManager getDefault() {
 //1、在getDefault方法中调用了gDefault的get方法。
        return gDefault.get();
    }
    /*2、
    
gDefault是一个Singleton类


*/
     private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
        protected IActivityManager create() {
        //得到Ibind 类型的AMS引用
            IBinder b = ServiceManager.getService("activity");
            if (false) {
                Log.v("ActivityManager", "default service binder = " + b);
            }
            // 3、将它封装成AMP类型对象,并将它保存到gDefault中,
            //此后调用AMN的getDefault方法就会直接获得AMS的代理对象AMP
            IActivityManager am = asInterface(b);
            if (false) {
                Log.v("ActivityManager", "default service = " + am);
            }
            return am;
        }
    };

 static public IActivityManager asInterface(IBinder obj) {
        if (obj == null) {
            return null;
        }
        IActivityManager in =
        //4、descriptor值为android.app.IActivityManager类型
            (IActivityManager)obj.queryLocalInterface(descriptor);

//5、查询本地进程是否有IActivityManager接口的实现,
//如果有则返回,如果没有就使用ActivityManagerProxy将IBinder类型的AMS引用封装成AMP
        if (in != null) {
            return in;
        }

        return new ActivityManagerProxy(obj);
    }

//6、在AMP的构造方法中将AMS的引用赋值给变量mRemote,这样在AMP中就可以使用AMS了。
//其中IActivityManager是一个接口,AMN和AMP都实现了这个接口,
//用于实现代理模式和Binder通信
public ActivityManagerProxy(IBinder remote)
    {
        mRemote = remote;
    }

再回到Instrumentation的execStartActivity方法,来查看AMP的startActivity方法,AMP是AMN的内部类

public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
            String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {

...
//private IBinder mRemote;
 mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
        reply.readException();
        int result = reply.readInt();
        reply.recycle();
        data.recycle();
        return result;
}

首先将传入的参数写入到Parcel类型的data中。通过IBinder类型对象mRemote(AMS的引用)向服务器端的AMS发送一个START_ACTIVITY_TRANSACTION类型的进程间通信请求。那么服务器端AMS就会从Binder线程池中读取客户端发来的数据,最终会调用AMN的onTransact方法。

@Override
    public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
            throws RemoteException {
...
// 调用AMS的start 方法
 int result = startActivity(app, callingPackage, intent, resolvedType,
                    resultTo, resultWho, requestCode, startFlags, profilerInfo, options);
            reply.writeNoException();
            reply.writeInt(result);
            return true;
}

调用AMS的start 方法,AMS的startActivity方法最后会返回startActivityAsUser方法,等后续就是一系列无关AMS的调用了。。。

图解&小结

android 启动关联app 安卓应用关联启动_系统服务_02

android 启动关联app 安卓应用关联启动_AMP_03

AMP是AMN的内部类,它们都实现了IActivityManager接口,这样它们就可以实现代理模式。具体来讲是远程代理。

AMP和AMN是运行在两个进程中的,AMP是Client端,AMN则是Server端,而Server端中具体的功能都是由AMN的子类AMS来实现的,因此,AMP就是AMS在Client端的代理类。

AMN又实现了Binder类,这样AMP和AMS就可以通过Binder来进行进程间通信

ActivityManager通过AMN的getDefault方法得到AMP,通过AMP就可以和AMS进行通信。除ActivityManager以外,有些想要与AMS进行通信的类也需要通过AMP,如上图解。

2、Android 8.0的AMS关联类

Instrumentation#execStartActivity方法
public ActivityResult execStartActivity(
        Context who, IBinder contextThread, IBinder token, String target,
        Intent intent, int requestCode, Bundle options) {

...
  try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess(who);
            int result = ActivityManager.getService()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target, requestCode, 0, null, options);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;
}
ActivityManager#getService
/**
     * @hide
     */
    public static IActivityManager getService() {
        return IActivityManagerSingleton.get();
    }

    private static final Singleton<IActivityManager> IActivityManagerSingleton =
            new Singleton<IActivityManager>() {
                @Override
                protected IActivityManager create() {
                //1、获得Binder类型的AMS引用
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                    //2、将Binder类型引用转换成IActivityManager类型的对象,
                    //这段代码采用的是AIDL
                    final IActivityManager am = IActivityManager.Stub.asInterface(b);
                    return am;
                }
            };

采用AIDL后就不需要使用AMS的代理类AMP了,因此Android8.0去掉了AMP,代替它的是IActivityManager,它是AMS在本地的代理。

图解&小结

ActivityManager的getService方法会得到IActivityManager,AMS只需要继承IActivityManager.Stub类,就可以和ActivityManager实现进程间通信了

android 启动关联app 安卓应用关联启动_系统服务_04

二、AMS的启动过程

AMS的启动是在SystemServer进程中启动的。也即AMS运行在SystemSever进程。SystemServer的main方法如下:

/**
     * The main entry point from zygote.
     */
    public static void main(String[] args) {
        new SystemServer().run();
    }
private void run() {
...         // 创建Looper
            Looper.prepareMainLooper();

            // 1、加载动态库android_servers(C,C++ 文件编译产物)
            System.loadLibrary("android_servers");

            // Check whether we failed to shut down last time we tried.
            // This call may not return.
            performPendingShutdown();

            // Initialize the system context.
            createSystemContext();

            // 2、创建system service manager。对系统的服务进行创建、启动、
            //生命周期管理
            mSystemServiceManager = new SystemServiceManager(mSystemContext);
            mSystemServiceManager.setRuntimeRestarted(mRuntimeRestart);
            LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
            // Prepare the thread pool for init tasks that can be parallelized
            SystemServerInitThreadPool.get();
            ...
            //3、分批启动系统服务
            //启动引导服务
            startBootstrapServices();
            //启动核心服务
            startCoreServices();
            //启动其他服务
            startOtherServices();
            ...
              // Loop forever.
        Looper.loop();
        throw new RuntimeException("Main thread loop unexpectedly exited");

}

AMS服务就是在启动系统服务时启动的。

系统服务有很多的有的需要立即启动,有的不需要立即启动,所以系统就分三批启动系统服务:

  • 引导服务(BootstrapServices):主要开启了ActivityManagerService、PowerManagerService、PackageManagerService等服
  • 核心服务(CoreServices):主要开启了DropBoxManagerService、BatteryService、UsageStatsService和WebViewUpdateService等服务
  • 其他服务(OtherServices):主要启动了CameraService、AlarmManagerService、VrManagerService等服务。

既然AMS的开启是SystemSever进程中调用引导服务时开启的,那么就看下startBootstrapServices方法:

private void startBootstrapServices() {
...
 // 开启AMS相关的代码
        traceBeginAndSlog("StartActivityManager");
        mActivityManagerService = mSystemServiceManager.startService(
                ActivityManagerService.Lifecycle.class).getService();
        mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
        mActivityManagerService.setInstaller(installer);
        traceEnd();
...
}

可以发现具体是通过SystemServiceManager#startService方法传参 ActivityManagerService.Lifecycle.class来开启的。具体细节如下:

SystemServiceManager.java

 public void startService(@NonNull final SystemService service) {
        // 注册AMS服务,方便系统管理
        mServices.add(service);
        //调用AMS的start方法开启AMS服务
        long time = System.currentTimeMillis();
        try {
            service.onStart();
        } catch (RuntimeException ex) {
            throw new RuntimeException("Failed to start service " + service.getClass().getName()
                    + ": onStart threw an exception", ex);
        }
        warnIfTooLong(System.currentTimeMillis() - time, service, "onStart");
    }

调用AMS的start方法开启AMS服务

这里需要注意:

  • 所有的系统服务父类都是SystemService
  • ActivityManagerService.Lifecycle.class 参数:可以看出Lifecycle是AMS的内部类。其实AMS对象创建、AMS的开启、AMS对象的获取都是这个内部类提供的功能。具体如下一看便知:
public static final class Lifecycle extends SystemService {
        //AMS
        private final ActivityManagerService mService; 
        
        // 1、构造方法中创建AMS对象
        public Lifecycle(Context context) {
            super(context);
            mService = new ActivityManagerService(context);
        }
       
       // 2、AMS start方法
        @Override
        public void onStart() {
            mService.start();
        }
       
       // 3、返回AMS对象
        public ActivityManagerService getService() {
            return mService;
        }
    }

三、AMS 与应用进程

Zygote的Java框架层中,会创建一个Server端的Socket,这个Socket用来等待AMS请求Zygote来创建新的应用程序进程。

要启动一个应用程序首先要保证应用程序的进程已经启动,否则就要先启动应用程序需要的进程,然后启动应用程序。

AMS管理着四大组件的开启以及组件信息的维护,AMS的职责是十分重要的。在启动应用程序时AMS会检查这个应用程序需要的应用程序进程是否存在,不存在就会请求Zygote进程创建需要的应用程序进程。

这里就以startService为例子展示下:

ActiveService#bringUpServiceLocked()

  private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
            boolean whileRestarting, boolean permissionsReviewRequired)
            throws TransactionTooLargeException {

...
  //1、processName描述service想要运行的进程,默认值为当前进程
  final String procName = r.processName;
        String hostingType = "service";
        ProcessRecord app;

        if (!isolated) {
        //2、mAm为AMS类型对象,这里调用AMS的getProcessRecordLocked表示去AMS中查询
        //是否存在一个与service对应的ProcessRecord类型对象。
            app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
            if (DEBUG_MU) Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid
                        + " app=" + app);
            if (app != null && app.thread != null) {//3、service应用进程存在
                try {
                    app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, mAm.mProcessStats);
                    //4、启动service
                    realStartServiceLocked(r, app, execInFg);
                    return null;
                } catch (TransactionTooLargeException e) {
                    throw e;
                } catch (RemoteException e) {
                    Slog.w(TAG, "Exception when starting service " + r.shortName, e);
                }
            }
        } else {       
            app = r.isolatedProc;
            if (WebViewZygote.isMultiprocessEnabled()
                    && r.serviceInfo.packageName.equals(WebViewZygote.getPackageName())) {
                hostingType = "webview_service";
            }
        }
        // 假如需要的应用进程不存在时,创建应用进程。
        if (app == null && !permissionsReviewRequired) {
            if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                    hostingType, r.name, false, isolated, false)) == null) {
                String msg = "Unable to launch app "
                        + r.appInfo.packageName + "/"
                        + r.appInfo.uid + " for service "
                        + r.intent.getIntent() + ": process is bad";
                Slog.w(TAG, msg);
                bringDownServiceLocked(r);
                return msg;
            }
            if (isolated) {
                r.isolatedProc = app;
            }
        }
...
return null;
}

伪代码表示

//app 对象为ProcessRecord类型,开启应用进程时AMS内部会维护记录这个进程。
    if(app!=null,app.thread!=null){ 
     开启组件
    }else{
     ams向zogote发socket请求创建应用进程
    }

四、AMS重要的数据结构

Activty是放入在Activity任务栈中的,有了任务栈,系统和开发者就能够更好地应用和管理Activity,来完成各种业务逻辑。

Activity任务栈模型是由多种数据结构共同组合而成的:

android 启动关联app 安卓应用关联启动_AMN_05

  • ActivityRecord:记录一个Activity的所有信息。
  • TaskRecord:包含一个或者多个ActivityRecord,用来管理栈中的ActivityRecord。
  • ActivityStack:包含一个或者多个TaskRecord,用来管理栈中的TaskRecord,也即用来管理系统所有Activity。

ActivityStack

ActivityStack是一个管理类,用来管理系统所有Activity。

1、ActivityStack何时被创建??

ActivityStack是由ActivityStackSupervisor来进行管理的,而ActivityStackSupervisor在AMS的构造方法中被创建。

ActivityStackSupervisor成员变量中维护了很多类型的ActivityStack如:

  • ActivityStack mHomeStack:用来存储Launcher App的所有Activity
  • ActivityStack mFocusedStack:表示当前正在接收输入或启动下一个Activity的所有Activity

通过ActivityStackSupervisor提供了获取上述ActivityStack 的方法,比如要获取mFocusedStack,只需要调用ActivityStackSupervisor的getFocusedStack方法就可以了

2、ActivityStack内部维护的数据

(1)枚举了Activity所有状态

enum ActivityState {
        INITIALIZING,
        RESUMED,
        PAUSING,
        PAUSED,
        STOPPING,
        STOPPED,
        FINISHING,
        DESTROYING,
        DESTROYED
    }

具体场景:Activity的切换动画系统源码

@Override
    public void overridePendingTransition(IBinder token, String packageName,
            int enterAnim, int exitAnim) {
        synchronized(this) {
            ActivityRecord self = ActivityRecord.isInStackLocked(token);
            if (self == null) {
                return;
            }

            final long origId = Binder.clearCallingIdentity();

            if (self.state == ActivityState.RESUMED
                    || self.state == ActivityState.PAUSING) {
                mWindowManager.overridePendingAppTransition(packageName,
                        enterAnim, exitAnim, null);
            }

            Binder.restoreCallingIdentity(origId);
        }
    }

可以看到只有ActivityState 为RESUMED状态或者PAUSING状态时才会调用WMS类型的mWindowManager对象的overridePendingAppTransition方法来切换动画

(2)重要字段

//所有没有被销毁的Activity任务栈
   private final ArrayList<TaskRecord> mTaskHistory = new ArrayList<>();
   
// 正在运行的activity,列表中第一个是最近最少使用的Activity
final ArrayList<ActivityRecord> mLRUActivities = new ArrayList<>();

//不考虑转化动画的activity
   final ArrayList<ActivityRecord> mNoAnimActivities = new ArrayList<>();

  //正在暂停的activity
   ActivityRecord mPausingActivity = null;
   //上一个已经暂停的activity
   ActivityRecord mLastPausedActivity = null;
   ...

TaskRecord相关重要字段

TaskRecord 用来描述一个Activity任务栈。TaskRecord的作用,其内部存储了任务栈的所有信息,包括任务栈的唯一标识符、任务栈的倾向性、任务栈中的Activity记录和AMS的引用等,需要注意的是其中含有ActivityStack,也就是当前Activity任务栈所归属的ActivityStack。

字段

说明

int taskId

任务栈唯一标识符

String affinity

任务倾向性

Intent intent

启动任务栈的intent

ArrayList<ActivityRecord> mActivities

按照历史顺序排列的activity记录

ActivityStack mStack

当前activity归属的任务栈

ActivityManagerService mService

AMS引用

ActivityRecord相关重要字段

用来描述一个Activity,记录了Activity的所有信息,包括AMS的引用、AndroidManifes节点信息、Activity状态、Activity资源信息和Activity进程相关信息等

需要注意的是其中含有该ActivityRecord所在的TaskRecord,这就将ActivityRecord和TaskRecord关联在一起。

具体是在启动Activity 时被创建的,具体是在ActivityStarter 的startActivity方法中被创建的。

字段

说明

ActivityManagerService service

AMS引用

ActivityInfo info

Activity中代码和AndroidManifes设置的节点,比如launchMode

String launchedFromPackage

启动activity的包名

String taskAffinity

Activity希望归属的栈

TaskRecord task

ActivityRecord所在的TaskRecord

ProcessRecord app

ActivityRecord所在的应用程序进程

ActivityState state

当前activity的状态

int icon

Activity的图标资源标识符

int theme

Activity的主题资源标识符

The end

参考:
安卓进阶解密:微信读书版