Inicio del sistema Android (4): proceso de inicio del iniciador

1 Launcherresumen

El último paso en el inicio del sistema es iniciar una aplicación para mostrar las aplicaciones ya instaladas en el sistema, esta aplicación se llama Launcher. LauncherDurante el proceso de inicio, se solicitará PackageManagerServiceque se devuelva la información del programa de aplicación instalado en el sistema, y ​​la información se empaquetará en una lista de iconos de acceso directo y se mostrará en la pantalla del sistema, para que el usuario pueda iniciar el programa de aplicación correspondiente haciendo clic en estos iconos de acceso directo.

En términos sencillos, Launcheres Androidel escritorio del sistema, y ​​sus funciones incluyen principalmente los siguientes dos puntos:

  • Como Androidiniciador del sistema, se utiliza para iniciar el programa de aplicación;
  • Como Androidescritorio del sistema, se utiliza para mostrar y administrar íconos de acceso directo de aplicaciones u otros componentes del escritorio;

2 Launcherproceso de inicio

SystemServerEl proceso se iniciará durante el proceso de inicio PackageManagerService, y PackageManagerServicelos programas de aplicación en el sistema se instalarán después del inicio, y los que se iniciaron antes ActivityManagerServicese Launcheriniciarán.

LauncherLa puesta en marcha se divide en tres partes:

  • SystemServerComplete la configuración pertinente Launcherde la puesta en marcha Activity;
  • Zygoteproceso forkde proceso Launcher;
  • Ingrese ActivityThread.mainla función y finalmente complete la operación Launcherde Activity.onCreate;

LauncherLa configuración relevante completada en la primera etapa

Figura 1

SystemServer.startOtherServicesLlame al método en el método , ActivityManagerService.systemReadyel Launcherinicio del proceso comienza desde aquí, el siguiente es el código fuente relevante:

// /frameworks/base/services/java/com/android/server/SystemServer.java
private void startOtherServices() {
    
    
    ...
    mActivityManagerService.systemReady(() -> {
    
     // 1
        Slog.i(TAG, "Making services ready");
        traceBeginAndSlog("StartActivityManagerReadyPhase");
        mSystemServiceManager.startBootPhase(
            SystemService.PHASE_ACTIVITY_MANAGER_READY);
        traceEnd();
        }
       ...}                                                      

El siguiente es ActivityManagerService.systemReadyel código fuente del método:

// /frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public ActivityTaskManagerInternal mAtmInternal;
public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) {
    
    
    ...
    // 启动 Home Activity,即 Launcher 应用的入口 Activity,这里指的是,在所有屏幕上启动 Launcher。因为 Android 10 开始支持多屏幕,比如手机屏幕、虚拟投屏、外接屏幕
    mAtmInternal.startHomeOnAllDisplays(currentUserId, "systemReady"); // 1
    ...
}

Aquí mAtmInternalhay ActivityTaskManagerInternaluna instancia de , ActivityTaskManagerInternalque es una clase abstracta. ActivityManagerServiceLa clase interna en LocalServiceimplementos ActivityTaskManagerInternal:

// /frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
final class LocalService extends ActivityTaskManagerInternal {
    
    
    ...
    @Override
    public boolean startHomeOnAllDisplays(int userId, String reason) {
    
    
        synchronized (mGlobalLock) {
    
    
            return mRootActivityContainer.startHomeOnAllDisplays(userId, reason);
        }
    }
    ...
}

LocalService.startHomeOnAllDisplaysEl método fue llamado en el método RootActivityContainer.startHomeOnAllDisplays. RootActivityContainerLa función de es llamar PackageManagerServicepara consultar cuál de las aplicaciones instaladas en el sistema del teléfono móvil cumple con Launcherel estándar, devolver un Intentobjeto y dárselo aActivityStarter :

// /frameworks/base/services/core/java/com/android/server/wm/RootActivityContainer.java
boolean startHomeOnAllDisplays(int userId, String reason) {
    
    
    boolean homeStarted = false;
    for (int i = mActivityDisplays.size() - 1; i >= 0; i--) {
    
    
        final int displayId = mActivityDisplays.get(i).mDisplayId;
        homeStarted |= startHomeOnDisplay(userId, reason, displayId); // 1
    }
    return homeStarted;
}

boolean startHomeOnDisplay(int userId, String reason, int displayId) {
    
    
    return startHomeOnDisplay(userId, reason, displayId, false /* allowInstrumenting */,false /* fromHomeKey */);
}

boolean startHomeOnDisplay(int userId, String reason, int displayId, 
                           boolean allowInstrumenting, boolean fromHomeKey) {
    
    
    ...
    Intent homeIntent = null;
    ActivityInfo aInfo = null;
    if (displayId == DEFAULT_DISPLAY) {
    
    
        // 构建一个 category 为 CATEGORY_HOME 的 Intent,表明是 HomeActivity
        homeIntent = mService.getHomeIntent(); // 2
        // 通过 PMS 从系统所有已安装的引用中找到一个符合 homeIntent 的 Activity
        aInfo = resolveHomeActivity(userId, homeIntent); // 3
    } else if (shouldPlaceSecondaryHomeOnDisplay(displayId)) {
    
    
        ...
    }
    ...
    // 启动 Launcher
    mService.getActivityStartController().startHomeActivity(homeIntent, aInfo, 
                                                            myReason, displayId); // 4
    return true;
}

2El método se llama en el comentario ActivityTaskManagerService.getHomeIntent()para construir un for category, lo que indica que es una aplicación conforme . Analice la información que debe iniciarse llamando al método en el comentario . Llame a Get en el comentario La función de esta clase es hacer varias comprobaciones antes del inicio, como si hay un archivo de lista registrado, si el archivo existe, etc., y luego iniciar .CATEGORY_HOMEIntentLauncherIntent3resolveHomeActivityActivity4ActivityTaskManagerService.getActivityStartController()ActivityStartControllerActivityClassActivity

El siguiente es el diagrama de tiempo relevante:

Figura 2

Primero, eche un vistazo al ActivityTaskManagerService.getHomeIntent()método, que es principalmente para construir una Launcheraplicación conforme Intent:

// frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
Intent getHomeIntent() {
    
    
    Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
    intent.setComponent(mTopComponent);
    intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING); 
    if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
    
    
        intent.addCategory(Intent.CATEGORY_HOME); // 1
    }
    return intent;
}     

El comentario 1representa Activityla intención de iniciar. En términos generales, solo hay una aplicación configurada en el archivo de manifiesto para todo el sistema CATEGORY_HOME. Si se configuran varias aplicaciones, el sistema requerirá que el usuario seleccione manualmente qué aplicación usar al iniciar. Inicie el Si está configurado en la aplicación de configuración del sistema, se seleccionará la aplicación configurada.

Luego mira RootActivityContainer.resolveIntentInternalel método:

// /frameworks/base/services/core/java/com/android/server/wm/RootActivityContainer.java
private ResolveInfo resolveIntentInternal(Intent intent, String resolvedType,
                                          int flags, int userId, 
                                          boolean resolveForStart, 
                                          int filterCallingUid) {
    
    
    try {
    
    
        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "resolveIntent");

        if (!sUserManager.exists(userId)) return null;
        final int callingUid = Binder.getCallingUid();
        flags = updateFlagsForResolve(flags, userId, intent, filterCallingUid, resolveForStart);
        mPermissionManager.enforceCrossUserPermission(callingUid, userId,
                                                      false /*requireFullPermission*/, false /*checkShell*/, "resolve intent");

        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "queryIntentActivities");
        final List<ResolveInfo> query = queryIntentActivitiesInternal(intent, resolvedType,
                                                                      flags, filterCallingUid, userId, resolveForStart, true /*allowDynamicSplits*/);
        Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);

        final ResolveInfo bestChoice =
            chooseBestActivity(intent, resolvedType, flags, query, userId);
        return bestChoice;
    } finally {
    
    
        Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
    }
}

Encuentre una aplicación coincidente entre todas las aplicaciones instaladas en el sistema a través de Binderla notificación de comunicación entre procesos .PackageManagerServicehomeInentActivity

Mira el código de nuevo ActivityStartController.startHomeActivity:

// /frameworks/base/services/core/java/com/android/server/wm/ActivityStartController.java
void startHomeActivity(Intent intent, ActivityInfo aInfo, String reason, 
                       int displayId) {
    
    
    final ActivityOptions options = ActivityOptions.makeBasic();
    options.setLaunchWindowingMode(WINDOWING_MODE_FULLSCREEN);
    if (!ActivityRecord.isResolverActivity(aInfo.name)) {
    
    
        options.setLaunchActivityType(ACTIVITY_TYPE_HOME);
    }
    options.setLaunchDisplayId(displayId);
    mLastHomeActivityStartResult = 
        obtainStarter(intent, "startHomeActivity: " + reason) // 1
        .setOutActivity(tmpOutRecord)
        .setCallingUid(0)
        .setActivityInfo(aInfo)
        .setActivityOptions(options.toBundle())
        .execute(); // 2
    mLastHomeActivityStartRecord = tmpOutRecord[0];
    final ActivityDisplay display =
        mService.mRootActivityContainer.getActivityDisplay(displayId);
    final ActivityStack homeStack = display != null ? display.getHomeStack() : null;
    if (homeStack != null && homeStack.mInResumeTopActivity) {
    
     
        mSupervisor.scheduleResumeTopActivities();
    }
}

ActivityStarter obtainStarter(Intent intent, String reason) {
    
     // 3
    return mFactory.obtain().setIntent(intent).setReason(reason);
}

1Primero obtenga uno en el comentario ActivityStarter, que se usa principalmente para el inicio Activity, luego configure los parámetros requeridos y finalmente llame a su execute()método:

// /frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
int execute() {
    
    
    try {
    
    
        if (mRequest.mayWait) {
    
    
           ...
        } else {
    
    
            return startActivity(...);
        }
    } finally {
    
    
        onExecutionComplete();
    }
}

El siguiente es ActivityStarter.startActivityel código fuente relevante de , este método se utiliza principalmente para Activityla verificación de seguridad antes del inicio:

// /frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
private int startActivity(...) {
    
    
    mSupervisor.getActivityMetricsLogger().notifyActivityLaunching(intent);
    int err = ActivityManager.START_SUCCESS;
    // Pull the optional Ephemeral Installer-only bundle out of the options early.
    final Bundle verificationBundle
        = options != null ? options.popAppVerificationBundle() : null;
    WindowProcessController callerApp = null;
    if (caller != null) {
    
    
        callerApp = mService.getProcessController(caller);
        if (callerApp != null) {
    
    
            callingPid = callerApp.getPid();
            callingUid = callerApp.mInfo.uid;
        } else {
    
    
            Slog.w(TAG, "Unable to find app for caller " + caller
                   + " (pid=" + callingPid + ") when starting: "
                   + intent.toString());
            err = ActivityManager.START_PERMISSION_DENIED;
        }
    }
	...
    final int res = startActivity(r, sourceRecord, voiceSession, voiceInteractor, 
                                  startFlags, true /* doResume */, checkedOptions, 
                                  inTask, outActivity, restrictedBgActivity);
    ...
}

private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord, 
                          IVoiceInteractionSession voiceSession, 
                          IVoiceInteractor voiceInteractor, int startFlags, 
                          boolean doResume, ActivityOptions options, 
                          TaskRecord inTask, ActivityRecord[] outActivity,
                          boolean restrictedBgActivity) {
    
    
    ...
    result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor, 
                                    startFlags, doResume, options, inTask, 
                                    outActivity, restrictedBgActivity); // 1
    ...
}

Código 1llamado en el comentario :ActivityStarter.startActivityUnchecked

// /frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
private int startActivityUnchecked(final ActivityRecord r, 
                                   ActivityRecord sourceRecord, 
                                   IVoiceInteractionSession voiceSession, 
                                   IVoiceInteractor voiceInteractor, int startFlags, 
                                   boolean doResume, ActivityOptions options, 
                                   TaskRecord inTask, ActivityRecord[] outActivity, 
                                   boolean restrictedBgActivity) {
    
    
	...
    final int preferredWindowingMode = mLaunchParams.mWindowingMode;
    computeLaunchingTaskFlags(); // 1
    computeSourceStack(); // 2
    mIntent.setFlags(mLaunchFlags);
    ActivityRecord reusedActivity = getReusableIntentActivity();
	...
    mRootActivityContainer.resumeFocusedStacksTopActivities(); // 3
    ...
}

1El método en el comentario ActivityStarter.computeLaunchingTaskFlags()es el método de apilamiento calculado Activityen base a launcher modey de . El cálculo en el comentario comienza desde qué pila . El método se llama en el comentario :intent.flagActivity2ActivityStarter.computeSourceStack()Activity3RootActivityContainer.resumeFocusedStacksTopActivities

// /frameworks/base/services/core/java/com/android/server/wm/RootActivityContainer.java
boolean resumeFocusedStacksTopActivities() {
    
    
    return resumeFocusedStacksTopActivities(null, null, null);
}

boolean resumeFocusedStacksTopActivities(
    ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
    
    
	...
    if (targetStack != null && (targetStack.isTopStackOnDisplay()
                                || getTopDisplayFocusedStack() == targetStack)) {
    
    
        result = targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
    }

    for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
    
    
        ...
        if (!resumedOnDisplay) {
    
    
            final ActivityStack focusedStack = display.getFocusedStack(); 
            if (focusedStack != null) {
    
    
                focusedStack.resumeTopActivityUncheckedLocked(target, targetOptions); // 1
            }
        }
    }

    return result;
}

1Llame al método en el comentario ActivityStack.resumeTopActivityUncheckedLocked:

// /frameworks/base/services/core/java/com/android/server/wm/ActivityStack.java
@GuardedBy("mService")
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
    
    
    ...
    result = resumeTopActivityInnerLocked(prev, options);
    ...
}

@GuardedBy("mService")
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, 
                                             ActivityOptions options) {
    
    
    ...
    if (anim) {
    
    
        next.applyOptionsLocked();
    } else {
    
    
        next.clearOptionsLocked();
    }
    
    mStackSupervisor.mNoAnimActivities.clear();
    
    if (next.attachedToProcess()) {
    
     // 待启动的进程是否创建完成,如果没有就会到 else 中
        ...
    }  else {
    
    
         mStackSupervisor.startSpecificActivityLocked(next, true, true); // 1
    }
    ...
}

1Llamado al comentario ActivityStackSupervisor.startSpecificActivityLocked:

// /frameworks/base/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
void startSpecificActivityLocked(ActivityRecord r, boolean andResume,
                                 boolean checkConfig) {
    
    
    ...
    try {
    
    
        ...
        final Message msg = PooledLambda.obtainMessage(
            ActivityManagerInternal::startProcess,  // 1
            mService.mAmInternal, r.processName, r.info.applicationInfo, 
            knownToBeDead, "activity", r.intent.getComponent());
        mService.mH.sendMessage(msg);
    } finally {
    
    
        Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
    }
}

Tenga en cuenta 1que la llamada es en realidad ActivityManagerService.startProcessel método, que comienza a crear un proceso:

// /frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public final class LocalService extends ActivityManagerInternal {
    
    
    @Override
    public void startProcess(String processName, ApplicationInfo info,
                             boolean knownToBeDead, String hostingType, 
                             ComponentName hostingName) {
    
    
        try {
    
    
            if (Trace.isTagEnabled(Trace.TRACE_TAG_ACTIVITY_MANAGER)) {
    
    
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "startProcess:"
                                 + processName);
            }
            synchronized (ActivityManagerService.this) {
    
    
                startProcessLocked(processName, info, knownToBeDead, 
                                   0 /* intentFlags */,
                                   new HostingRecord(hostingType, hostingName),
                                   false /* allowWhileBooting */, 
                                   false /* isolated */,
                                   true /* keepIfLarge */); // 1
            }
        } finally {
    
    
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        }
    }
    
    @GuardedBy("this")
    final ProcessRecord startProcessLocked(String processName,
                                           ApplicationInfo info, 
                                           boolean knownToBeDead, int intentFlags,
                                           HostingRecord hostingRecord, 
                                           boolean allowWhileBooting, 
                                           boolean isolated, boolean keepIfLarge) {
    
    
        return mProcessList.startProcessLocked(processName, info, knownToBeDead, 
                                               intentFlags,
                                               hostingRecord, allowWhileBooting, 
                                               isolated, 0 /* isolatedUid */, 
                                               keepIfLarge,
                                               null /* ABI override */, 
                                               null /* entryPoint */, 
                                               null /* entryPointArgs */,
                                               null /* crashHandler */); // 2
    }
}

1Llame al método en el comentario LocalService.startProcessLocked. En LocalService.startProcessLockedel método, el trabajo de creación de procesos se delega a ProcessList. Luego mira ProcessList.startProcessLockedel método:

// /frameworks/base/services/core/java/com/android/server/am/ProcessList.java
@GuardedBy("mService")
final void startProcessLocked(ProcessRecord app, HostingRecord hostingRecord) {
    
    
    startProcessLocked(app, hostingRecord, null /* abiOverride */);
}

@GuardedBy("mService")
final boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
                                 String abiOverride) {
    
    
    return startProcessLocked(app, hostingRecord, false /* disableHiddenApiChecks */,
                              false /* mountExtStorageFull */, abiOverride);
}

@GuardedBy("mService")
boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
                           boolean disableHiddenApiChecks, 
                           boolean mountExtStorageFull,
                           String abiOverride) {
    
    
    ...
    final String entryPoint = "android.app.ActivityThread"; // 1
    return startProcessLocked(hostingRecord, entryPoint, app, uid, gids,
                              runtimeFlags, mountExternal, seInfo, requiredAbi, 
                              instructionSet, invokeWith, startTime);
}

@GuardedBy("mService")
final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,
                                       boolean knownToBeDead, int intentFlags, 
                                       HostingRecord hostingRecord,
                                       boolean allowWhileBooting, boolean isolated, 
                                       int isolatedUid, boolean keepIfLarge,
                                       String abiOverride, String entryPoint, 
                                       String[] entryPointArgs, Runnable crashHandler) {
    
    
    if (!isolated) {
    
    
        app = getProcessRecordLocked(processName, info.uid, keepIfLarge);
        checkSlow(startTime, "startProcess: after getProcessRecord");
        ...
    }
    final String entryPoint = "android.app.ActivityThread";
    ...
}

La función de estos métodos es configurar algunos parámetros necesarios antes de crear el proceso, como el número de versión y otros parámetros. En el comentario 1hay un parámetro muy importante, entryPointque es el punto de entrada del nuevo proceso. Entonces, Androidla entrada del programa de la aplicación es ActivityThread.

Después de completar la configuración de los parámetros requeridos para crear un proceso, eventualmente irá a ZygoteProcessla clase:

private Process.ProcessStartResult startViaZygote(@NonNull final String processClass,
                                                  @Nullable final String niceName,
                                                  final int uid, final int gid,
                                                  @Nullable final int[] gids,
                                                  int runtimeFlags, int mountExternal,
                                                  int targetSdkVersion,
                                                  @Nullable String seInfo,
                                                  @NonNull String abi,
                                                  @Nullable String instructionSet,
                                                  @Nullable String appDataDir,
                                                  @Nullable String invokeWith,
                                                  boolean startChildZygote,
                                                  @Nullable String packageName,
                                                  boolean useUsapPool,
                                                  @Nullable String[] extraArgs)
   throws ZygoteStartFailedEx {
    
    
    synchronized (mLock) {
    
    
        return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi),
                                          useUsapPool, argsForZygote);
    }
}

En este momento, todavía está en system_serverproceso. El propósito de esta clase es crear un Socketobjeto de conexión local, conectarse al método Zygotedel proceso Sockety luego enviar los parámetros necesarios para crear el proceso a través del flujo de entrada de caracteres.

Fase 2: ZygoteEl proceso recibe la solicitud y crea Launcherun proceso

Consulte el proceso de inicio del proceso de solicitud

Fase tres: entrada , operaciones ActivityThread.mainde finalización finalLauncher.onCreate

Zygote forkSalga Launcherdel proceso y transfiera la siguiente Launchertarea de inicio ActivityThreada , y luego analice el proceso de creación desde ActivityThread.mainel método . LauncherEl siguiente es el diagrama de tiempo para ActivityThreadel inicio Activity:

ActivityThread comienza Diagrama de secuencia de actividades

ActivityThread.mainEl método es la entrada del programa, el siguiente es el código relevante:

// /frameworks/base/core/java/android/app/ActivityThread.java
public static void main(String[] args) {
    
    
    ...
    Looper.prepareMainLooper();
	...
    ActivityThread thread = new ActivityThread();
    thread.attach(false, startSeq); // 1

    if (sMainThreadHandler == null) {
    
    
        sMainThreadHandler = thread.getHandler();
    }
	...  
    Looper.loop();
    throw new RuntimeException("Main thread loop unexpectedly exited");
}

1Llame al método en el comentario ActivityThread.attach, el siguiente es el código fuente relevante:

// /frameworks/base/core/java/android/app/ActivityThread.java
@UnsupportedAppUsage
private void attach(boolean system, long startSeq) {
    
    
    sCurrentActivityThread = this;
    mSystemThread = system;
    if (!system) {
    
    
        ...
        final IActivityManager mgr = ActivityManager.getService(); // 1
        try {
    
    
            mgr.attachApplication(mAppThread, startSeq); // 2
        } catch (RemoteException ex) {
    
    
            throw ex.rethrowFromSystemServer();
        }
        ...
    } else {
    
    
        ...
    }
    ...
}

1Obtenga ActivityManagerServiceuna instancia de en la anotación y 2llame ActivityManagerService.attachApplicational método en la anotación:

// /frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
@Override
public final void attachApplication(IApplicationThread thread, long startSeq) {
    
    
    if (thread == null) {
    
    
        throw new SecurityException("Invalid application interface");
    }
    synchronized (this) {
    
    
        // 通过 Binder 获取传入的 pid 信息
        int callingPid = Binder.getCallingPid(); 
        final int callingUid = Binder.getCallingUid();
        final long origId = Binder.clearCallingIdentity();
        attachApplicationLocked(thread, callingPid, callingUid, startSeq); // 1
        Binder.restoreCallingIdentity(origId);
    }
}

public ActivityTaskManagerInternal mAtmInternal;
@GuardedBy("this")
private boolean attachApplicationLocked(@NonNull IApplicationThread thread,
                                        int pid, int callingUid, long startSeq) {
    
    
    ...
    didSomething = mAtmInternal.attachApplication(app.getWindowProcessController()); // 2
    ...
}

1El método se llama en la anotación ActivityManagerService.attachApplicationLocked. 2El comentario mAtmInternales ActivityTaskManagerInternaluna variable de tipo, ActivityTaskManagerServicela clase interna LocalServicehereda de ActivityTaskManagerInternal, el siguiente es el código fuente relevante:

// /frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
final class LocalService extends ActivityTaskManagerInternal {
    
    
    @HotPath(caller = HotPath.PROCESS_CHANGE)
    @Override
    public boolean attachApplication(WindowProcessController wpc) throws RemoteException {
    
    
        synchronized (mGlobalLockWithoutBoost) {
    
    
            return mRootActivityContainer.attachApplication(wpc); // 1
        }
    }
}

1El método se llama en el comentario RootActivityContainer.attachApplication:

// frameworks/base/services/core/java/com/android/server/wm/RootActivityContainer.java
boolean attachApplication(WindowProcessController app) throws RemoteException {
    
    
    final String processName = app.mName;
    boolean didSomething = false;
    for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
    
    
        final ActivityDisplay display = mActivityDisplays.get(displayNdx);
        final ActivityStack stack = display.getFocusedStack();
        if (stack != null) {
    
    
            stack.getAllRunningVisibleActivitiesLocked(mTmpActivityList);
            final ActivityRecord top = stack.topRunningActivityLocked();
            final int size = mTmpActivityList.size();
            for (int i = 0; i < size; i++) {
    
    
                final ActivityRecord activity = mTmpActivityList.get(i);
                if (activity.app == null && app.mUid == activity.info.applicationInfo.uid
                    && processName.equals(activity.processName)) {
    
    
                    try {
    
    
                        // 1
                        if (mStackSupervisor.realStartActivityLocked(activity, app,
                                                            top == activity /* andResume */, 
                                                                     true /* checkConfig */)) {
    
    
                            didSomething = true;
                        }
                    } catch (RemoteException e) {
    
    
                        Slog.w(TAG, "Exception in new application when starting activity "
                               + top.intent.getComponent().flattenToShortString(), e);
                        throw e;
                    }
                }
            }
        }
    }
    if (!didSomething) {
    
    
        ensureActivitiesVisible(null, 0, false /* preserve_windows */);
    }
    return didSomething;
}

1Llame al método en el comentario ActivityStackSupervisor.realStartActivityLocked:

// /frameworks/base/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,
                                boolean andResume, boolean checkConfig) throws RemoteException {
    
    
	...
    clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
                         System.identityHashCode(r), r.info,  
                         mergedConfiguration.getGlobalConfiguration(),
                         mergedConfiguration.getOverrideConfiguration(), r.compat,
                         r.launchedFromPackage, task.voiceInteractor,             
                         proc.getReportedProcState(), r.icicle, r.persistentState, results, 
                         newIntents, dc.isNextTransitionForward(),
                         proc.createProfilerInfoIfNeeded(), r.assistToken)); // 1

	...
    // Schedule transaction.
    mService.getLifecycleManager().scheduleTransaction(clientTransaction); // 2 
	...
}

2El método en el comentario ActivityTaskManagerService.getLifecycleManagerdevuelve ClientLifecycleManagerla instancia. El siguiente es ClientLifecycleManager.scheduleTransactionel código fuente relevante:

// /frameworks/base/services/core/java/com/android/server/wm/ClientLifecycleManager.java
void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
    
    
    final IApplicationThread client = transaction.getClient();
    transaction.schedule(); // 1
    if (!(client instanceof Binder)) {
    
    
        // If client is not an instance of Binder - it's a remote call and at this point it is
        // safe to recycle the object. All objects used for local calls will be recycled after
        // the transaction is executed on client in ActivityThread.
        transaction.recycle(); 
    }
}

1El método se llama en el comentario ClientTransaction.schedule:

// /frameworks/base/core/java/android/app/servertransaction/ClientTransaction.java
private IApplicationThread mClient; 
public void schedule() throws RemoteException {
    
    
    mClient.scheduleTransaction(this); // 1
}

1El comentario mClientes IApplicationThreaduna instancia, aquí está ApplicationThreadla clase interna de, el siguiente es el código fuente relevante ApplicationThread:ActivityThread

// /frameworks/base/core/java/android/app/ActivityThread.java
private class ApplicationThread extends IApplicationThread.Stub {
    
    
    @Override
    public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
    
    
        ActivityThread.this.scheduleTransaction(transaction); // 1
    }
}

1El método se llama en el comentario ActivityThread.this.scheduleTransaction, ActivityThreadque se hereda de ClientTransactionHandler, por lo que el método se llama aquí ClientTransactionHandler.scheduleTransactionEl siguiente es el código fuente relevante:

// /frameworks/base/core/java/android/app/ClientTransactionHandler.java
void scheduleTransaction(ClientTransaction transaction) {
    
    
    transaction.preExecute(this);
    sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction); // 1
}

1El en el comentario ActivityThread.Hes Handleruna subclase de, el siguiente es ActivityThread.sendMessageel código fuente del método y el ActivityThread.H.EXECUTE_TRANSACTIONprocesamiento relacionado sobre:

// /frameworks/base/core/java/android/app/ActivityThread.java
void sendMessage(int what, Object obj) {
    
    
    sendMessage(what, obj, 0, 0, false);
}

private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
    
    
    if (DEBUG_MESSAGES) {
    
    
        Slog.v(TAG,
               "SCHEDULE " + what + " " + mH.codeToString(what) + ": " + arg1 + " / " + obj);
    }
    Message msg = Message.obtain();
    msg.what = what;
    msg.obj = obj;
    msg.arg1 = arg1;
    msg.arg2 = arg2;
    if (async) {
    
    
        msg.setAsynchronous(true);
    }
    mH.sendMessage(msg);
}

class H extends Handler {
    
    
    ...
    public static final int EXECUTE_TRANSACTION = 159;
	...
    public void handleMessage(Message msg) {
    
    
        if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
        switch (msg.what) {
    
    
            ...
            case EXECUTE_TRANSACTION:
                final ClientTransaction transaction = (ClientTransaction) msg.obj;
                mTransactionExecutor.execute(transaction); // 1
                if (isSystem()) {
    
    
                    // Client transactions inside system process are recycled on the client side
                    // instead of ClientLifecycleManager to avoid being cleared before this
                    // message is handled.
                    transaction.recycle();
                }
                // TODO(lifecycler): Recycle locally scheduled transactions.
                break;
				...
        }
    }
}

método 1llamado en la anotaciónTransactionExecutor.execute

// /frameworks/base/core/java/android/app/servertransaction/TransactionExecutor.java
public void execute(ClientTransaction transaction) {
    
    
    ...
    executeCallbacks(transaction); // 1

    executeLifecycleState(transaction);
    mPendingActions.clear();
    if (DEBUG_RESOLVER) Slog.d(TAG, tId(transaction) + "End resolving transaction");
}

@VisibleForTesting
public void executeCallbacks(ClientTransaction transaction) {
    
    
    ...
    final int size = callbacks.size();
    for (int i = 0; i < size; ++i) {
    
    
        final ClientTransactionItem item = callbacks.get(i);
        ...
        item.execute(mTransactionHandler, token, mPendingActions); // 2
        ..
    }
}

2El método se llama en el comentario , que se implementa ClientTransactionItem.executeen su subclase , el siguiente es el método:LaunchActivityItemLaunchActivityItem.execute

// /frameworks/base/core/java/android/app/servertransaction/LaunchActivityItem.java) 
@Override
public void execute(ClientTransactionHandler client, IBinder token,
                    PendingTransactionActions pendingActions) {
    
    
    Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
    ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
                                                      mOverrideConfig, mCompatInfo, mReferrer, 
                                                      mVoiceInteractor, mState, 
                                                      mPersistentState,
                                                      mPendingResults, mPendingNewIntents, 
                                                      mIsForward,
                                                      mProfilerInfo, client, mAssistToken);
    client.handleLaunchActivity(r, pendingActions, null /* customIntent */); // 1
    Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}

1El en el comentario clientes ClientTransactionHandleruna subclase de ActivityThread, vea ActivityThread.handleLauncherActivityel código fuente de , principalmente llamando ActivityThread.performLaunchActivityal método:

// /frameworks/base/core/java/android/app/ActivityThread.java
@Override
public Activity handleLaunchActivity(ActivityClientRecord r,
                                     PendingTransactionActions pendingActions, 
                                     Intent customIntent) {
    
    
    ...
    WindowManagerGlobal.initialize();
    
	// 1 启动 Activity
    final Activity a = performLaunchActivity(r, customIntent);

    if (a != null) {
    
    
        r.createdConfig = new Configuration(mConfiguration);
        reportSizeConfigurations(r);
        if (!r.activity.mFinished && pendingActions != null) {
    
    
            pendingActions.setOldState(r.state);
            pendingActions.setRestoreInstanceState(true);
            pendingActions.setCallOnPostCreate(true);
        }
    } else {
    
    
        // If there was an error, for any reason, tell the activity manager to stop us.
        try {
    
    
            // 停止 Activity 的启动
            ActivityTaskManager.getService()
                .finishActivity(r.token, Activity.RESULT_CANCELED, null,
                                Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
        } catch (RemoteException ex) {
    
    
            throw ex.rethrowFromSystemServer();
        }
    }

    return a;
}

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    
    
    ActivityInfo aInfo = r.activityInfo; // 2 获取 ActivityInfo 类
    if (r.packageInfo == null) {
    
    
        // 3 获取 APK 文件描述类 LoadApk
        r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                                       Context.CONTEXT_INCLUDE_CODE); 
    }

    ComponentName component = r.intent.getComponent(); // 4
    ...
    // 5 创建要启动的 Activity 的上下文环境
    ContextImpl appContext = createBaseContextForActivity(r); 
    Activity activity = null;
    try {
    
    
        java.lang.ClassLoader cl = appContext.getClassLoader();
        // 6 用类加载器创建该 Activity 的实例
        activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
        ...
    } catch (Exception e) {
    
    
        ...
    }

    try {
    
    
        // 7 创建 Application
        Application app = r.packageInfo.makeApplication(false, mInstrumentation);
        ...
        if (activity != null) {
    
    
            ...
            // 8 初始化 Activity
            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,
                            r.assistToken);
            ...
            if (r.isPersistable()) {
    
    
                mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState); // 9
            } else {
    
    
                mInstrumentation.callActivityOnCreate(activity, r.state);
            }
            ...
        }
        ...
    } catch (SuperNotCalledException e) {
    
    
        throw e;

    } catch (Exception e) {
    
    
        ....
    }
    return activity;
}

El comentario 1llama ActivityThread.performLaunchActivityal método para iniciar Activity. Los comentarios se utilizan para 2obtener ActivityInfoy almacenar código e información AndroidManifestde conjuntos Activityy Receivernodos, por ejemplo, Activityy . Obtenga la clase de descripción del archivo en el comentario . Obtenga la clase de la que se iniciará en el comentario y guarde el nombre del paquete y el nombre de la clase en la clase. Se utiliza en los comentarios para crear el contexto en el que empezar . De acuerdo con el nombre de clase almacenado en el comentario , utilice el cargador de clases para crear la instancia de . La anotación se usa para crear y el método se llamará dentro del método. Llame a la inicialización del método en la anotación y el objeto ( ) se creará en el método y se asociará consigo mismo. Llame al método en el comentario para comenzar :themelaunchMode3APKLoadedApk4ActivityComponentNameComponentNameActivity5Activity6ComponentNameActivityActivity7ApplicationLoadedApk.makeApplicationApplication.onCreate8Activity.attachActivityActivity.attachWindowPhoneWindowActivity9Instrumentation.callActivityOnCreateActivity

// /frameworks/base/core/java/android/app/Instrumentation.java
public void callActivityOnCreate(Activity activity, Bundle icicle,
                                 PersistableBundle persistentState) {
    
    
    prePerformCreate(activity);
    activity.performCreate(icicle, persistentState); // 1
    postPerformCreate(activity);
}

1El método se llama en el comentario Activity.performCreate, y el método Activity.performCreatese llama en el método . En este punto, se inicia la raíz. El siguiente es el código fuente relevante:Activity.onCreateActivity

// /frameworks/base/core/java/android/app/Activity.java
@UnsupportedAppUsage
final void performCreate(Bundle icicle, PersistableBundle persistentState) {
    
    
    dispatchActivityPreCreated(icicle);
    mCanEnterPictureInPicture = true;
    restoreHasCurrentPermissionRequest(icicle);
    // 1
    if (persistentState != null) {
    
    
        onCreate(icicle, persistentState);
    } else {
    
    
        onCreate(icicle);
    }
    writeEventLog(LOG_AM_ON_CREATE_CALLED, "performCreate");
    mActivityTransitionState.readState(icicle);

    mVisibleFromClient = !mWindow.getWindowStyle().getBoolean(
        com.android.internal.R.styleable.Window_windowNoDisplay, false);
    mFragments.dispatchActivityCreated();
    mActivityTransitionState.setEnterActivityOptions(this, getActivityOptions());
    dispatchActivityPostCreated(icicle);
}

@MainThread
@CallSuper
protected void onCreate(@Nullable Bundle savedInstanceState) {
    
    
    if (DEBUG_LIFECYCLE) Slog.v(TAG, "onCreate " + this + ": " + savedInstanceState);

    if (mLastNonConfigurationInstances != null) {
    
    
        mFragments.restoreLoaderNonConfig(mLastNonConfigurationInstances.loaders);
    }
    if (mActivityInfo.parentActivityName != null) {
    
    
        if (mActionBar == null) {
    
    
            mEnableDefaultActionBarUp = true;
        } else {
    
    
            mActionBar.setDefaultDisplayHomeAsUpEnabled(true);
        }
    }
    if (savedInstanceState != null) {
    
    
        mAutoFillResetNeeded = savedInstanceState.getBoolean(AUTOFILL_RESET_NEEDED, false);
        mLastAutofillId = savedInstanceState.getInt(LAST_AUTOFILL_ID,
                                                    View.LAST_APP_AUTOFILL_ID);

        if (mAutoFillResetNeeded) {
    
    
            getAutofillManager().onCreate(savedInstanceState);
        }

        Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG);
        mFragments.restoreAllState(p, mLastNonConfigurationInstances != null
                                   ? mLastNonConfigurationInstances.fragments : null);
    }
    mFragments.dispatchCreate();
    dispatchActivityCreated(savedInstanceState);
    if (mVoiceInteractor != null) {
    
    
        mVoiceInteractor.attachActivity(this);
    }
    mRestoredFromBundle = savedInstanceState != null;
    mCalled = true;

}

public void onCreate(@Nullable Bundle savedInstanceState,
                     @Nullable PersistableBundle persistentState) {
    
    
    onCreate(savedInstanceState);
}

referencia

Inicio del sistema Android para el análisis del proceso de inicio del Lanzador

Supongo que te gusta

Origin blog.csdn.net/xingyu19911016/article/details/128697566
Recomendado
Clasificación