Android 7.0 and Android 8.0 have great differences in the processing of AMS related parts
AMS family for Android 7.0
There are three main categories
-
ActivityManager
Activity manager is a class associated with AMS. It mainly manages running activities. These management tasks are not handled by ActivityManager, but by AMs
-
ActivityManagerNative(AMN)
AMN is an abstract class that delegates functions to its subclass AMS, which is a Binder communication class
-
ActivityManagerProxy(AMP)
The method in the ActivityManager will get the ActivityManagerProxy through the getDefault method of ActivityManagerNative (AMN)
AMP is the internal class of AMN. They all implement the IActivityManager interface, so they can implement the agent mode. Specifically, they are remote agents: AMP and amn run in two processes, AMP is the Client side, amn is the Server side, and the specific functions in the Server side are implemented by AMS, a subclass of AMN. Therefore, AMP is the proxy class of AMS on the Client side
Take the Activity startup process of Android 7.0 as an example. During the Activity startup process, the execStartActivity method of Instrumentation will be called
/*frameworks/base/core/java/android/app/Instrumentation.java*/ public ActivityResult execStartActivity(Context who, IBinder contextThread, IBinder token, Activity target, Intent intent, int requestCode, Bundle options){ ... //Call getDefault of AMN to get the proxy class amp of AMS, and then call the startActivity method of AMP int result = ActivityManagerNative.getDefault().startActivity(...); ... } /*ActivityManagerNative.java*/ static public IActivityManager getDefault(){ return gDefault.get(); } private static final Singleton<IActivityManager> getDefault = new Singleton<IActivityManager>(){ protected IActivityManager create(){ //Get the Service reference named "activity", that is, the reference of AMS of IBinder type IBinder b = ServiceManager.getService("activity"); ... //The Service reference is encapsulated into a AMP type object and saved to gDefault. After that, the AMS's proxy object AMP is directly invoked by calling AMN's getDefault method. IActivityManager am = asInterface(b); } } static public IActivityManager asInterface(IBinder obj){ if(obj == null){ return null; } //The descriptor value is android.app.IActivityManager; This code is mainly used to query whether the local process has the IActivityManager interface implementation. If so, it returns IActivityManager in = (IActivityManager) obj.queryLocalInterface(descriptor); if(in != null){ return in; } //If not, encapsulate the AMS reference of IBinder type into AMP return new ActivityManagerProxy(obj); } class ActivityManagerProxy implements IActivityManager{ //Assign the reference of AMS to the variable mRemote in the construction method, so that AMS can be used in AMP public ActivityManagerProxy(IBinder remote){ mReomte = remote; } } //Go back to the execStartActivity method of Instrumentation to see the startActivity method of AMP. Amp is an internal class of AMN /*ActivityManagerNative.java*/ public int startActivity(...) throws RemoteException{ ... //Write the passed in parameters to the data of Parcel type data.writeInt(requestCode); data.writeInt(startFlags); ... //Send a start to the server-side AMS through the IBinder type object mremote (a reference to AMS)_ ACTIVITY_ An interprocess communication request of type transaction. Then the server AMS will read the data sent by the client from the Binder thread pool, and finally call the onTransact method of AMN mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0); } @Override public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException{ switch(code){ case START_ACTIVITY_TRANSACTION: ... int result = startActivity(aap, callingPackage, intetn, resolvedType, resultTo, resultWho, requestCode, startFlags, profilerInfo, options); reply.writeNoException(); reply.writeInt(result); return true; } } //The startActivity method of AMS is called in the onTransact method /*ActivityManagerService.java*/ public final int startActivity(IApplicationThread caller, ....){ return startActivityAsUser(...); } //In this method, the startActivityMayWait method of ActivityStarter will be called finally public final int startActivityAsUser(...,int userId){ ... return mActivityStarter.startActivityMayWait(...); }
AMS family for Android 8.0
Similarly, take the Activity startup process as an example. For Android 8.0, the execStartActivity method of Instrumentation will be called during the Activity startup process
/*frameworks/base/core/java/android/app/Instrumentation.java*/ public ActivityResult execStartActivity(Context who, ...){ ... int result = ActivityManager.getService().startActivity(...); ... } /* ActivityManager getService method for * ActivityManager.java */ public static IActivityManager getService(){ return IActivityManagerSingleton.get(); } private static final Singleton<IActivityManager> IActivityManagerSingleton = new Singleton<IActivityManager>(){ @Override protected IActivityManager create(){ //Get the Service reference named "activity" (the value of Context.ACTIVITY_SERVICE is "activity"), that is, the reference of AMS of IBinder type final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE); // Convert it to an object of type IActivityManager, final IActivityManager am = IActivityManager.Stub.asInterface(b); } }
IActivityManager.java class is automatically generated by AIDL tool during compilation. The file path of IActivityManager.aidl is framework/base/core/java/android/app/IActivityManager.aidl. To realize inter process communication, the server side, that is, AMS, only needs to inherit the IActivityManager.Stub class and implement the corresponding methods. After AIDL is adopted, the proxy class AMP of AMS is not required
AMS startup process
AMS is started in the SystemServer process. We start from the main method of SystemServer
/*framworks/base/services/java/com/android/server/SystemServer.java*/ public static void main(String[] args){ new SystemServer().run(); } private void run(){ try{ ... //Create message Looper Looper.prepareMainLooper(); //Load dynamic library libandroid_servers.so System.loadLibrary("android_servers"); //Create a system service manager, which will create, start and manage the service life cycle of the system mSystemServiceManager = new SystemServiceManager(mSystemContext); ... //Start the boot service. Start AMS, PowerManagerService, PackageManagerService and other services with SystemServiceManager startBootstrapServices(); //Start the core service. Start DropBoxManagerService, BatteryService, UsageStatusService and WebViewUpdateService startCoreServices(); //Start other services. Start CameraService, AlarmManagerService, VrManagerService and other services startOtherServices(); } } //Next, we mainly look at the boot service and how AMS is started. That is, the startBootstrapServices() method private void startBootstrapServices(){ ... traceBeginAndSlog("StartActivityManager"); //Call the startService method of SystemServiceManager mActivityManagerService = mSystemServiceManager.startService(ActivityManagerService.Lifecycle.class).getService(); mActivityManagerService.setSystemServiceManager(mSystemServiceManager); mActivityManagerService.setInstaller(installer); traceEnd(); ... } /*SystemServiceManager.java*/ public void startService(final SystemService service){ //Add the service object to the mServices of ArrayList type to complete the registration mServices.add(service); //Call the onStart method of the service to start the service object service.onStart(); } /** What does this service object specifically refer to? * ActivityManagerService.Lifecycle.class Is an internal class of AMS * ActivityManagerService.java */ public static final class Lifecycle extends SystemService{ private final ActivityManagerService mService; public Lifecycle(Context context){ super(context); //Create an AMS instance in the construction method of Lifecycle mService = new ActivityManagerService(context); } @Override public void onStart(){ //When you call the onStart method of a service of SystemService type, you actually call the start method of AMS there mService.start() } //Return the AMS instance, and call this method to get the AMS instance public ActivityManagerService getService(){ return mService; } }
AMS and application process
In Chapter 2, the system startup will go to the java framework layer of Zygote, and a Server-side Socket will be created to wait for AMS to request Zygote to create a new application process.
To start an application, first ensure that the program process required by the application already exists. When starting an application, AMS will check whether the process required by the application exists. If it does not exist, AMS will request the Zygote process to create the required application process
Here, take the service startup process as an example to analyze the relationship between AMS and application process. Service will call the bringUpServiceLocked method of ActiveServices during startup
/*frameworks/base/services/core/java/com/android/server/am/ActiveServices.java*/ private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg, boolean whileRestarting, boolean permissionsReviewRequired) throws TransactionTooLargeException{ ... //Get the value of processName of ServiceRecord and assign it to procName. processName is used to describe which process the Service wants to run in. By default, it is the current process. We can set the android:process attribute in the AndroidManifest file to start a new process to run the Service final String procName = r.processName; ... //Query whether there is an object app of ProcessRecord type corresponding to the Service ProcessRecord app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false); //Determine whether the application process used to run the Service exists if(app != null && app.thread != null){ //Start Service realStartServiceLocked(r, app, execInFg); } //If the application process used to run the Service does not exist if(app == null && !permissionReviewRequired){ //Use the startProcessLocked() method to create the corresponding application process if((app = mAm.startProcessLocked(procName, r.appInfo, true, intentFlags, hostingType, r.name, false, isolated, false)) == null) } }
The relationship between AMS and application process mainly includes the following two points:
-
When starting an application, AMS will check whether the application process required by the application exists
-
If the required application does not exist, AMS will request the Zygote process to create the required application process
AMS important data structure
ActivityRecord
ActivityRecord internally records all the information of an Activity, so it is used to describe an Activity. It is created when the Activity is started, specifically in the startActivity method of ActivityStarter
Some important member variables of ActivityRecord are shown in the following table
name | type | explain |
---|---|---|
service | ActivityManagerService | References to AMS |
info | ActivityInfo | Code in Activity and node information set by AndroidManifest, such as launchMode |
launchedFromPackage | String | The package name of the startup Activity |
taskAffinity | String | The stack to which the Activity wants to belong |
task | TaskRecord | TaskRecord where ActivityRecord is located |
app | ProcessRecord | The application process in which the ActivityRecord resides |
state | ActivityState | Current Activity status |
icon | int | Icon resource identifier for Activity |
theme | int | Subject resource identifier for Activity |
TaskRecord
TaskRecord is used to describe an Activity task stack, which internally stores all the information of the task stack, including the ActivityStack, that is, the ActivityStack to which the current Activity task stack belongs
name | type | explain |
---|---|---|
taskId | int | Unique identifier of the task stack |
affinity | String | Tendency of task stack |
intent | Intent | Start the Intent of this task stack |
mActivities | ArrayList<ActivityRecord> | Activity records in historical order |
mStack | ActivityStack | ActivityStack to which you currently belong |
mService | ActivityManagerService | References to AMS |
Activity stack is a management class used to manage all activities in the system. It internally maintains data such as all States of activities, activities in special states and lists related to activities. The ActivityStack is managed by the ActivityStack supervisor
taskAffinity
We can set android:taskAffinity in AndroidManifest.xml to specify the stack where the Activity wants to belong. By default, all activities of the same application have the same taskAffinity
taskAffinity works in the following two cases:
-
TaskAffinity and FLAG_ACTIVITY_NEW_TASK or singleTask. If the taskAffinity of the newly started Activity is the same as that of the stack, it will be added to the stack; If different, a new stack is created
-
taskAffinity works with allowtaskreparating. If allowtaskreparating is true, the Activity has the ability to transfer