Android Source Notes--Activity Manager Service

Keywords: Android Java Windows xml

ActivityManagerService

Activity Manager Service (AMS) is one of the three core functions of the Android kernel, and the other two are Windows Manager Service and View. Activity Manager Service manages four components. Android wants to obscure the role of process and replace it with the concept of component. Activity Manger Service is the implementer of this concept. Secondly, memory management. For example, when Activity exits, its process will not be killed immediately, so the next time it starts the Acitivity, it will be able to improve the speed of start-up. These activities are automatically killed only when the system memory is tight, and the application does not care about this problem. And that's done in Ams. In addition, it also manages and schedules all user processes. It provides an API for querying process information that the system is running.

AMS is a Binder service. AMS derives from the Activity Manager Native class, which together with Iactivity Manager, Activity Manager Proxy and Active Manager implements the Binder framework of AMS. Their relationship is shown in the figure:

    

The Activity Manager Proxy class is implemented as an embedded class of Activity Manager Native. It is a proxy object and acts as an interface. Activity Manager is equivalent to encapsulating Activity Manager Proxy for easy application. Activity Manager obtains a reference to the Activity Manager Proxy object by calling the getDefault() method of Activity Manager Native.

# ActivityManagerNative.java

static public IActivityManager getDefault() {
        return gDefault.get();
    }

gDefault Definition
  private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
        protected IActivityManager create() {
            IBinder b = ServiceManager.getService("activity");
            if (false) {
                Log.v("ActivityManager", "default service binder = " + b);
            }
            IActivityManager am = asInterface(b);
            if (false) {
                Log.v("ActivityManager", "default service = " + am);
            }
            return am;
        }
    };	
	
	
public abstract class ActivityManagerNative extends Binder implements IActivityManager
{
    /**
     * Cast a Binder object into an activity manager interface, generating
     * a proxy if needed.
     */
    static public IActivityManager asInterface(IBinder obj) {
        if (obj == null) {
            return null;
        }
        IActivityManager in =
            (IActivityManager)obj.queryLocalInterface(descriptor);
        if (in != null) {
            return in;
        }

        return new ActivityManagerProxy(obj);
    }
	...
}	

Analysis: gDefault is a Singleton object that generates only one instance object. Object generation is accomplished by calling the asInterface() method of ActvivityManagerNative. This method returns the proxy object ActivityManagerProxy when the parameter is a Binder reference object.

AMS initialization:

AMS runs in the System Server (under the package com. android. server) process. The initialization of the object is done when the System Server class is initialized, as follows:

 # SystemServer.java
  
    private SystemServiceManager mSystemServiceManager;

    private ActivityManagerService mActivityManagerService;  
public static void main(String[] args) {
        new SystemServer().run();
    }  
   
  public SystemServer() {
        // Check for factory test mode.
        mFactoryTestMode = FactoryTest.getMode();
    }  
	
  private void run() {
  .....
   // Create the system service manager.
    mSystemServiceManager = new SystemServiceManager(mSystemContext);
     // Start services.
        try {
            Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartServices");
            startBootstrapServices();
            startCoreServices();
            startOtherServices();
        } catch (Throwable ex) {
            Slog.e("System", "******************************************");
            Slog.e("System", "************ Failure starting system services", ex);
            throw ex;
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
        }
  ......
  }	
 private void startBootstrapServices() {
        ...
        // Activity manager runs the show.
        mActivityManagerService = mSystemServiceManager.startService(
                ActivityManagerService.Lifecycle.class).getService();
        mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
        mActivityManagerService.setInstaller(installer);

        // Set up the Application instance for the system process and get started.
        mActivityManagerService.setSystemProcess();
        ....
    }	

Analysis: The startService() method of mSystemService Manager is invoked here, which creates instance objects of classes and registers them in Service Manager according to the incoming parameter: class of classes.

# ActivityManagerService	
	
	 // Note: This method is invoked on the main thread but may need to attach various
    // handlers to other threads.  So take care to be explicit about the looper.
    public ActivityManagerService(Context systemContext) {
        mContext = systemContext;
        mFactoryTest = FactoryTest.getMode();
		//Gets the ActivityThread object running in System Server.
        mSystemThread = ActivityThread.currentActivityThread();

        Slog.i(TAG, "Memory class: " + ActivityManager.staticGetMemoryClass());
		//Create threads and Handler objects for processing messages
        mHandlerThread = new ServiceThread(TAG,
                android.os.Process.THREAD_PRIORITY_FOREGROUND, false /*allowIo*/);
        mHandlerThread.start();
        mHandler = new MainHandler(mHandlerThread.getLooper());
        mUiHandler = new UiHandler();

       ...
		//Create a data structure to manage broadcasting
        mFgBroadcastQueue = new BroadcastQueue(this, mHandler,
                "foreground", BROADCAST_FG_TIMEOUT, false);
        mBgBroadcastQueue = new BroadcastQueue(this, mHandler,
                "background", BROADCAST_BG_TIMEOUT, true);
        mBroadcastQueues[0] = mFgBroadcastQueue;
        mBroadcastQueues[1] = mBgBroadcastQueue;
		
		//Create an object for the management component Service.
        mServices = new ActiveServices(this);
		//Create an object to manage component provider
        mProviderMap = new ProviderMap(this);
        mAppErrors = new AppErrors(mContext, this);

        // Get the system data and system directories
        File dataDir = Environment.getDataDirectory();
        File systemDir = new File(dataDir, "system");
        systemDir.mkdirs();
		//Creating BatteryStatesService Service Service
        mBatteryStatsService = new BatteryStatsService(systemDir, mHandler);
        mBatteryStatsService.getActiveStatistics().readLocked();
        mBatteryStatsService.scheduleWriteToDisk();
        mOnBattery = DEBUG_POWER ? true
                : mBatteryStatsService.getActiveStatistics().getIsOnBattery();
        mBatteryStatsService.getActiveStatistics().setCallback(this);
		//Create ProcessStatsService Service Service
        mProcessStats = new ProcessStatsService(this, new File(systemDir, "procstats"));
		//Create AppOpsService Service Service
        mAppOpsService = new AppOpsService(new File(systemDir, "appops.xml"), mHandler);
		...
        mCompatModePackages = new CompatModePackages(this, systemDir, mHandler);
        //Create Intent Firewall
		mIntentFirewall = new IntentFirewall(new IntentFirewallInterface(), mHandler);
        mStackSupervisor = new ActivityStackSupervisor(this);
        //Create an active management object
		mActivityStarter = new ActivityStarter(this, mStackSupervisor);
        mRecentTasks = new RecentTasks(this, mStackSupervisor);
		//Create threads for CPU usage
        mProcessCpuThread = new Thread("CpuTracker") {
            @Override
            public void run() {
                while (true) {
                   ...
                }
            }
        };
		//Add services to Watchdog monitoring.
        Watchdog.getInstance().addMonitor(this);
        Watchdog.getInstance().addThread(mHandler);
    }

The function of AMS construction method is to create component management objects and some internal objects. After creating an AMS object in System Server, it calls its (AMS) setSystemProcess() method as follows:

#AMS
 public void setSystemProcess() {
        try {
		//Add Activity Manger Service to Service Manager
            ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
			//ProcessStates is a service for dump process information	
		   ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);
            //MemBinder is a service for memory usage of each process in dump system
			ServiceManager.addService("meminfo", new MemBinder(this));
            //Graphics Binder is a dump service that uses graphics acceleration card status for each process
			ServiceManager.addService("gfxinfo", new GraphicsBinder(this));
            //DbBinder is a service for db status of each process in dump system
			ServiceManager.addService("dbinfo", new DbBinder(this));
            if (MONITOR_CPU_USAGE) {
                ServiceManager.addService("cpuinfo", new CpuBinder(this));
            }
			//permissionController is a service that checks Binder invocation permissions.
            ServiceManager.addService("permission", new PermissionController(this));
            ServiceManager.addService("processinfo", new ProcessInfoService(this));

            ApplicationInfo info = mContext.getPackageManager().getApplicationInfo(
                    "android", STOCK_PM_FLAGS | MATCH_SYSTEM_ONLY);
            mSystemThread.installSystemApplicationInfo(info, getClass().getClassLoader());

            synchronized (this) {
				//Add the System Server process itself to process management
                ProcessRecord app = newProcessRecordLocked(info, info.processName, false, 0);
                app.persistent = true;
                app.pid = MY_PID;
                app.maxAdj = ProcessList.SYSTEM_ADJ;
                app.makeActive(mSystemThread.getApplicationThread(), mProcessStats);
                synchronized (mPidsSelfLocked) {
                    mPidsSelfLocked.put(app.pid, app);
                }
                updateLruProcessLocked(app, false, null);
                updateOomAdjLocked();
            }
        } catch (PackageManager.NameNotFoundException e) {
            throw new RuntimeException(
                    "Unable to find android system package", e);
        }
    }

Analysis: The purpose of this method is to register some services with Service Manager. Notice that the last piece of code represents the System Server ProcessRecord object and adds it to the AMS process management system. In other words, System Server can also be used as the application process of framework-res.apk, and add it to the process management system of AMS. For AMS, its management of the system process is not omitted.

SystemServer calls the AMS systemReady() method after starting all services.

# SystemServer
  private void startOtherServices() {
  ...
 	 // We now tell the activity manager it is okay to run third party
        // code.  It will call back into us once it has gotten to the state
        // where third party code can really run (but before it has actually
        // started launching the initial applications), for us to complete our
        // initialization.
        mActivityManagerService.systemReady(new Runnable() {
            @Override
            public void run() {
                Slog.i(TAG, "Making services ready");
                mSystemServiceManager.startBootPhase(
                        SystemService.PHASE_ACTIVITY_MANAGER_READY);
                Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "PhaseActivityManagerReady");

                Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartObservingNativeCrashes");
                try {
                    mActivityManagerService.startObservingNativeCrashes();
                } catch (Throwable e) {
                    reportWtf("observing native crashes", e);
                }
              ...
            }
        });
	...
	}
	
#AMS	
 public void systemReady(final Runnable goingCallback) {
        synchronized(this) {
            if (mSystemReady) {//The value at the time of the call is false, and the following call will not be executed.
                // If we're done calling all the receivers, run the next "boot phase" passed in
                // by the SystemServer
                if (goingCallback != null) {
                    goingCallback.run();
                }
                return;
            }
            mLocalDeviceIdleController
                    = LocalServices.getService(DeviceIdleController.LocalService.class);
            // Make sure we have the current profile info, since it is needed for security checks.
            mUserController.onSystemReady();//User Manager Service reads the profile information saved by the system and loads the profile information of the existing users in the system.
            mRecentTasks.onSystemReadyLocked();//
            mAppOpsService.systemReady();
            mSystemReady = true;
        }
		//Clean up the processes, find the application processes that have been started, and kill them, in order to prepare a clean environment before starting Home.
        ArrayList<ProcessRecord> procsToKill = null;
        synchronized(mPidsSelfLocked) {
            for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
                ProcessRecord proc = mPidsSelfLocked.valueAt(i);
                if (!isAllowedWhileBooting(proc.info)){
                    if (procsToKill == null) {
                        procsToKill = new ArrayList<ProcessRecord>();
                    }
                    procsToKill.add(proc);
                }
            }
        }

        synchronized(this) {
            if (procsToKill != null) {
                for (int i=procsToKill.size()-1; i>=0; i--) {
                    ProcessRecord proc = procsToKill.get(i);
                    Slog.i(TAG, "Removing system update proc: " + proc);
                    removeProcessLocked(proc, true, false, "system update done");
                }
            }
            mProcessesReady = true;
        }

        Slog.i(TAG, "System now ready");
        EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
            SystemClock.uptimeMillis());
		//Start the application marked FLAG_PERSISTENT	
        synchronized(this) {
            // Make sure we have no pre-ready processes sitting around.

            if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL) {
                ResolveInfo ri = mContext.getPackageManager()
                        .resolveActivity(new Intent(Intent.ACTION_FACTORY_TEST),
                                STOCK_PM_FLAGS);
                CharSequence errorMsg = null;
                if (ri != null) {
                    ActivityInfo ai = ri.activityInfo;
                    ApplicationInfo app = ai.applicationInfo;
                    if ((app.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
                        mTopAction = Intent.ACTION_FACTORY_TEST;
                        mTopData = null;
                        mTopComponent = new ComponentName(app.packageName,
                                ai.name);
                    } else {
                        errorMsg = mContext.getResources().getText(
                                com.android.internal.R.string.factorytest_not_system);
                    }
                } else {
                    errorMsg = mContext.getResources().getText(
                            com.android.internal.R.string.factorytest_no_action);
         ...
		 //Read settings information
        retrieveSettings();
        final int currentUserId;
        synchronized (this) {
            currentUserId = mUserController.getCurrentUserIdLocked();
            readGrantedUriPermissionsLocked();
        }

        if (goingCallback != null) goingCallback.run();

        mBatteryStatsService.noteEvent(BatteryStats.HistoryItem.EVENT_USER_RUNNING_START,
                Integer.toString(currentUserId), currentUserId);
        mBatteryStatsService.noteEvent(BatteryStats.HistoryItem.EVENT_USER_FOREGROUND_START,
                Integer.toString(currentUserId), currentUserId);
        mSystemServiceManager.startUser(currentUserId);

        synchronized (this) {        
            startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_AWARE);
            // Start up initial activity.
            mBooting = true;//Startup End Logo
            // Enable home activity for system user, so that the system can always boot
            if (UserManager.isSplitSystemUser()) {
                ComponentName cName = new ComponentName(mContext, SystemUserHomeActivity.class);
                try {
                    AppGlobals.getPackageManager().setComponentEnabledSetting(cName,
                            PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0,
                            UserHandle.USER_SYSTEM);
                } catch (RemoteException e) {
                    throw e.rethrowAsRuntimeException();
                }
            }
			//Start Home Application
            startHomeActivityLocked(currentUserId, "systemReady");
           ...
            long ident = Binder.clearCallingIdentity();
            try {
                Intent intent = new Intent(Intent.ACTION_USER_STARTED);
                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
                        | Intent.FLAG_RECEIVER_FOREGROUND);
                intent.putExtra(Intent.EXTRA_USER_HANDLE, currentUserId);
                broadcastIntentLocked(null, null, intent,
                        null, null, 0, null, null, null, AppOpsManager.OP_NONE,
                        null, false, false, MY_PID, Process.SYSTEM_UID,
                        currentUserId);
                intent = new Intent(Intent.ACTION_USER_STARTING);
                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
                intent.putExtra(Intent.EXTRA_USER_HANDLE, currentUserId);
                broadcastIntentLocked(null, null, intent,
                        null, new IIntentReceiver.Stub() {
                            @Override
                            public void performReceive(Intent intent, int resultCode, String data,
                                    Bundle extras, boolean ordered, boolean sticky, int sendingUser)
                                    throws RemoteException {
                            }
                        }, 0, null, null,
                        new String[] {INTERACT_ACROSS_USERS}, AppOpsManager.OP_NONE,
                        null, true, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
            } catch (Throwable t) {
               ...
            } finally {
                Binder.restoreCallingIdentity(ident);
            }
            mStackSupervisor.resumeFocusedStackTopActivityLocked();
            mUserController.sendUserSwitchBroadcastsLocked(-1, currentUserId);
        }
    }	

Analysis: This method is the final preparation for Android to enter the user interaction phase.

Posted by Rik Peters on Sun, 12 May 2019 00:12:55 -0700