This article is a summary of the application process startup, and the application of the various Context those things, if there is an error, welcome to point out ~

First, create an application process

Zygote creates a new process

Android applications cannot actively start a process, only passively. When registering the four major components at Mainfest, you can specify which processes to run. When starting the component, AMS first determines whether the process already exists, and if not, asks the Zygote process first to create it.

        <service android:name=".ServiceName"
            android:process=":processName"/>
Copy the code

To start a service, for example, the startService() method in ActivityManagerService is called. Within that method, the bringUpServiceLocked method of ActiveService is called to start the service.

private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
            boolean whileRestarting, boolean permissionsReviewRequired)
            throws TransactionTooLargeException {
          ......
            app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
            if(app ! = null && app.thread ! = null) { app.addPackage(r.appInfo.packageName, r.appInfo.longVersionCode, mAm.mProcessStats); realStartServiceLocked(r, app,execInFg);
               return null;
            }

          if(app == null && ! permissionsReviewRequired) {if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                    hostingType, r.name, false, isolated, false)) == null) {
                bringDownServiceLocked(r);
                returnmsg; }}if(! mPendingServices.contains(r)) { mPendingServices.add(r); }return null;
    }
Copy the code

MAm. GetProcessRecordLocked () method is used to judge whether the current process exists, if does not exist, then call ActivityManagerService startProcessLocked method to create a process. The start method of Process is eventually called. The Zygote process is asked to create a process.

    public static final ProcessStartResult start(...) {
        return zygoteProcess.start(processClass, niceName, uid, gid, gids,
                    runtimeFlags, mountExternal, targetSdkVersion, seInfo,
                    abi, instructionSet, appDataDir, invokeWith, zygoteArgs);
    }
Copy the code

ZygoteProcess encapsulates the socket communication associated with the Zygote process. After the zygote process creates a new process, the PID of the new process is returned to the current system process.

    @GuardedBy("mLock")
    private static Process.ProcessStartResult zygoteSendArgsAndGetResult(
            ZygoteState zygoteState, ArrayList<String> args)
            throws ZygoteStartFailedEx {
        try {
            ......
            result.pid = inputStream.readInt();
            result.usingWrapper = inputStream.readBoolean();

            if (result.pid < 0) {
                throw new ZygoteStartFailedEx("fork() failed");
            }
            returnresult; } catch (IOException ex) { zygoteState.close(); throw new ZygoteStartFailedEx(ex); }}Copy the code

2. The new process publishes IBinder entity objects to AMS

After a new process is started, activityThread. main is executed, and attachApplication is invoked by the Binder in the Attach () method to inform AMS that the new process has been created. And publish your own IBinder to AMS.

public static void main(String[] args) {
        .....
        Looper.prepareMainLooper();

        ActivityThread thread = new ActivityThread();
        thread.attach(false, startSeq);

        Looper.loop();
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }
Copy the code
private void attach(boolean system, long startSeq) {
        sCurrentActivityThread = this;
        mSystemThread = system;
        if(! system) { ..... RuntimeInit.setApplicationObject(mAppThread.asBinder()); final IActivityManager mgr = ActivityManager.getService(); try { mgr.attachApplication(mAppThread, startSeq); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); }... }Copy the code

Create a new process Application object

After the Application process starts and releases its IBinder entity object to AMS, AMS invokes attachApplication() to create the Application object. Thread is the application process’s binder object in the AMS process.

@Override public final void attachApplication(IApplicationThread thread, long startSeq) { synchronized (this) { attachApplicationLocked(thread, callingPid, callingUid, startSeq); }}Copy the code
@GuardedBy("this") private final boolean attachApplicationLocked(IApplicationThread thread, int pid, int callingUid, long startSeq) { ..... thread.bindApplication(...) .return true;
    }
Copy the code

The bindApplication() method is executed in the Binder threads of the application process. The app data is first encapsulated into AppBindData, and then a Handler message is sent, executing the handleBindApplication() method in the main thread.

        public final void bindApplication(...) { AppBindData data = new AppBindData(); . sendMessage(H.BIND_APPLICATION, data); }Copy the code
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case BIND_APPLICATION:
                    AppBindData data = (AppBindData)msg.obj;
                    handleBindApplication(data);
                    break;
Copy the code
Private void handleBindApplication(AppBindData data) {// Initializes basic application data...... Application app; / / create Appcalition object app = data. Info. MakeApplication (data restrictedBackupMode, null); . / / call Application. The onCreate () method mInstrumentation. CallApplicationOnCreate (app); . }Copy the code

Create an Application object through reflection by calling the newApplication() method in Instrumentation, and call the Application.Attach (Context) lifecycle callback method

    public Application newApplication(ClassLoader cl, String className, Context context)
            throws InstantiationException, IllegalAccessException, 
            ClassNotFoundException {
        Application app = getFactory(context.getPackageName())
                .instantiateApplication(cl, className);
        app.attach(context);
        return app;
    }
Copy the code

At this point, the creation of Application is completed. From this, it can also be concluded that Application does not correspond to the Application, but to the Application process.

4. Create a service instance

AMS eventually notifies the newly created process with the Binder mechanism to create service class instances and invoke service-related lifecycle functions.

 private void handleCreateService(CreateServiceData data) {
        LoadedApk packageInfo = getPackageInfoNoCheck(
                data.info.applicationInfo, data.compatInfo);
        Service service = null;

       java.lang.ClassLoader cl = packageInfo.getClassLoader();
       service = packageInfo.getAppFactory()
                    .instantiateService(cl, data.info.name, data.intent);
 
       ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
       context.setOuterContext(service);

       Application app = packageInfo.makeApplication(false, mInstrumentation);
       service.attach(context, this, data.info.name, data.token, app,
                    ActivityManager.getService());
       service.onCreate();          
    }
Copy the code

Two, various contexts

1, introduction,

Context is an abstract class that provides an application Context, which can be used to access system resources, system services, and so on.

public abstract class Context { public abstract Resources getResources(); public abstract Context getApplicationContext(); public abstract String getSystemServiceName(Class<? > serviceClass); public abstract void startActivity( Intent intent); public abstract ComponentName startService(Intent service); }Copy the code

ContextWrapper is the implementation class of the Context and receives a ContextImp object as a static proxy.

public class ContextWrapper extends Context {
    Context mBase;
    public ContextWrapper(Context base) {
        mBase = base;
    }
   
    protected void attachBaseContext(Context base) {
        if(mBase ! = null) { throw new IllegalStateException("Base context already set");
        }
        mBase = base;
    }

    public Context getBaseContext() {
        returnmBase; }... }Copy the code

ContextImpl Implements the Context

class ContextImpl extends Context {
 ....
}
Copy the code

2. Context in Application

Applicaiton inherits ContextWrapper to save global variables within the application process, initialize operations, and provide application context.

public class Application extends ContextWrapper implements ComponentCallbacks2 {
      ...
    public Application() {
        super(null);
    }
     final void attach(Context context) {
        attachBaseContext(context);
    }
    public void onCreate() {}}Copy the code

The Application creates the Application and creates a ContextImp object assigned to mBase via attch

public Application makeApplication(...) { ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this); app = mActivityThread.mInstrumentation.newApplication(cl, appClass, appContext); }Copy the code
    public Application newApplication(ClassLoader cl, String className, Context context) {
        Application app = getFactory(context.getPackageName())
                .instantiateApplication(cl, className);
        app.attach(context);
        return app;
    }
Copy the code

3. Context in the Activity

The Activity inherits the ContextThemeWrapper class, and the ContextThemeWrapper class inherits the ContextWrapper class, encapsulating only the theme-related content.

public class Activity extends ContextThemeWrapper{
    ......
    public final Application getApplication() {
        returnmApplication; } final void attach(...) { attachBaseContext(context); mApplication = application; }}Copy the code

The application creates the Activity

private Activity performLaunchActivity(...) { ContextImpl appContext = createBaseContextForActivity(r); Activity activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent); activity.attach(appContext, this, getInstrumentation(), r.token, r.ident, app, r.intent, r.activityInfo, title, r.parent, r.embeddedID, r.lastNonConfigurationInstances, config, r.referrer, r.voiceInteractor, window, r.configCallback); }Copy the code

4. Context in Service

Service inherits ContextWrapper.

public abstract class Service extends ContextWrapper {
   public final void attach(...) {
        attachBaseContext(context);
        mApplication = application;
    }
    public final Application getApplication() {
        returnmApplication; }}Copy the code

Create a Service

private void handleCreateService(CreateServiceData data) { service = packageInfo.getAppFactory() .instantiateService(cl,  data.info.name, data.intent); ContextImpl context = ContextImpl.createAppContext(this, packageInfo); service.attach(context, this, data.info.name, data.token, app, ActivityManager.getService()); service.onCreate(); }Copy the code

5. Compare various methods of obtaining Context

In an Activity or Service, you can use the following three methods to get the Context, but it is the baseContext ContextImp object that is used in any Application, Activity, or Service.

Context Context = this; // Get the current Activity or Service itself. ContextImpl Context baseContext = getBaseContext(); Context baseContext = getBaseContext(); Application = getApplication(); Application = getApplication(); Context applicationContext = getApplicationContext();Copy the code

The ~