1 Launcher
resumen
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
. Launcher
Durante el proceso de inicio, se solicitará PackageManagerService
que 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, Launcher
es Android
el escritorio del sistema, y sus funciones incluyen principalmente los siguientes dos puntos:
- Como
Android
iniciador del sistema, se utiliza para iniciar el programa de aplicación; - Como
Android
escritorio del sistema, se utiliza para mostrar y administrar íconos de acceso directo de aplicaciones u otros componentes del escritorio;
2 Launcher
proceso de inicio
SystemServer
El proceso se iniciará durante el proceso de inicio PackageManagerService
, y PackageManagerService
los programas de aplicación en el sistema se instalarán después del inicio, y los que se iniciaron antes ActivityManagerService
se Launcher
iniciarán.
Launcher
La puesta en marcha se divide en tres partes:
SystemServer
Complete la configuración pertinenteLauncher
de la puesta en marchaActivity
;Zygote
procesofork
de procesoLauncher
;- Ingrese
ActivityThread.main
la función y finalmente complete la operaciónLauncher
deActivity.onCreate
;
Launcher
La configuración relevante completada en la primera etapa
SystemServer.startOtherServices
Llame al método en el método , ActivityManagerService.systemReady
el Launcher
inicio 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.systemReady
el 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í mAtmInternal
hay ActivityTaskManagerInternal
una instancia de , ActivityTaskManagerInternal
que es una clase abstracta. ActivityManagerService
La clase interna en LocalService
implementos 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.startHomeOnAllDisplays
El método fue llamado en el método RootActivityContainer.startHomeOnAllDisplays
. RootActivityContainer
La función de es llamar PackageManagerService
para consultar cuál de las aplicaciones instaladas en el sistema del teléfono móvil cumple con Launcher
el estándar, devolver un Intent
objeto 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;
}
2
El 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_HOME
Intent
Launcher
Intent
3
resolveHomeActivity
Activity
4
ActivityTaskManagerService.getActivityStartController()
ActivityStartController
Activity
Class
Activity
El siguiente es el diagrama de tiempo relevante:
Primero, eche un vistazo al ActivityTaskManagerService.getHomeIntent()
método, que es principalmente para construir una Launcher
aplicació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 1
representa Activity
la 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.resolveIntentInternal
el 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 Binder
la notificación de comunicación entre procesos .PackageManagerService
homeInent
Activity
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);
}
1
Primero 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.startActivity
el código fuente relevante de , este método se utiliza principalmente para Activity
la 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 1
llamado 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
...
}
1
El método en el comentario ActivityStarter.computeLaunchingTaskFlags()
es el método de apilamiento calculado Activity
en base a launcher mode
y de . El cálculo en el comentario comienza desde qué pila . El método se llama en el comentario :intent.flag
Activity
2
ActivityStarter.computeSourceStack()
Activity
3
RootActivityContainer.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;
}
1
Llame 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
}
...
}
1
Llamado 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 1
que la llamada es en realidad ActivityManagerService.startProcess
el 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
}
}
1
Llame al método en el comentario LocalService.startProcessLocked
. En LocalService.startProcessLocked
el método, el trabajo de creación de procesos se delega a ProcessList
. Luego mira ProcessList.startProcessLocked
el 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 1
hay un parámetro muy importante, entryPoint
que es el punto de entrada del nuevo proceso. Entonces, Android
la 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 ZygoteProcess
la 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_server
proceso. El propósito de esta clase es crear un Socket
objeto de conexión local, conectarse al método Zygote
del proceso Socket
y luego enviar los parámetros necesarios para crear el proceso a través del flujo de entrada de caracteres.
Fase 2: Zygote
El proceso recibe la solicitud y crea Launcher
un proceso
Consulte el proceso de inicio del proceso de solicitud
Fase tres: entrada , operaciones ActivityThread.main
de finalización finalLauncher.onCreate
Zygote
fork
Salga Launcher
del proceso y transfiera la siguiente Launcher
tarea de inicio ActivityThread
a , y luego analice el proceso de creación desde ActivityThread.main
el método . Launcher
El siguiente es el diagrama de tiempo para ActivityThread
el inicio Activity
:
ActivityThread.main
El 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");
}
1
Llame 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 {
...
}
...
}
1
Obtenga ActivityManagerService
una instancia de en la anotación y 2
llame ActivityManagerService.attachApplication
al 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
...
}
1
El método se llama en la anotación ActivityManagerService.attachApplicationLocked
. 2
El comentario mAtmInternal
es ActivityTaskManagerInternal
una variable de tipo, ActivityTaskManagerService
la clase interna LocalService
hereda 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
}
}
}
1
El 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;
}
1
Llame 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
...
}
2
El método en el comentario ActivityTaskManagerService.getLifecycleManager
devuelve ClientLifecycleManager
la instancia. El siguiente es ClientLifecycleManager.scheduleTransaction
el 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();
}
}
1
El 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
}
1
El comentario mClient
es IApplicationThread
una instancia, aquí está ApplicationThread
la 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
}
}
1
El método se llama en el comentario ActivityThread.this.scheduleTransaction
, ActivityThread
que se hereda de ClientTransactionHandler
, por lo que el método se llama aquí ClientTransactionHandler.scheduleTransaction
El 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
}
1
El en el comentario ActivityThread.H
es Handler
una subclase de, el siguiente es ActivityThread.sendMessage
el código fuente del método y el ActivityThread.H.EXECUTE_TRANSACTION
procesamiento 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 1
llamado 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
..
}
}
2
El método se llama en el comentario , que se implementa ClientTransactionItem.execute
en su subclase , el siguiente es el método:LaunchActivityItem
LaunchActivityItem.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);
}
1
El en el comentario client
es ClientTransactionHandler
una subclase de ActivityThread
, vea ActivityThread.handleLauncherActivity
el código fuente de , principalmente llamando ActivityThread.performLaunchActivity
al 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 1
llama ActivityThread.performLaunchActivity
al método para iniciar Activity
. Los comentarios se utilizan para 2
obtener ActivityInfo
y almacenar código e información AndroidManifest
de conjuntos Activity
y Receiver
nodos, por ejemplo, Activity
y . 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 :theme
launchMode
3
APK
LoadedApk
4
Activity
ComponentName
ComponentName
Activity
5
Activity
6
ComponentName
Activity
Activity
7
Application
LoadedApk.makeApplication
Application.onCreate
8
Activity.attach
Activity
Activity.attach
Window
PhoneWindow
Activity
9
Instrumentation.callActivityOnCreate
Activity
// /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);
}
1
El método se llama en el comentario Activity.performCreate
, y el método Activity.performCreate
se llama en el método . En este punto, se inicia la raíz. El siguiente es el código fuente relevante:Activity.onCreate
Activity
// /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