frameworks 之FallbackHome

frameworks 之FallbackHome

  • FallbackHome 启动
  • 启动 Activity 流程
  • 创建进程
  • ActivityThrad 与 AMS
  • 启动真正的 Launcher

mActivityManagerService 创建后会启动 FallbackHome 再启动桌面程序。因为此时还没解锁,桌面又涉及很多其他应用程序相关,所以要等待用户解锁后才能启动桌面程序,这就是为啥屏幕解锁后只有壁纸 等待一下才看到桌面。

涉及到的类如下

  • frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
  • frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
  • frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java
  • frameworks/base/services/core/java/com/android/server/wm/ActivityStartController.java
  • frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
  • frameworks/base/services/core/java/com/android/server/wm/Task.java
  • frameworks/base/services/core/java/com/android/server/wm/TaskFragment.java
  • frameworks/base/services/core/java/com/android/server/am/ProcessList.java
  • frameworks/base/core/java/android/os/Process.java
  • frameworks/base/core/java/android/os/ZygoteProcess.java
  • frameworks/base/core/java/android/app/ActivityThread.java
  • frameworks/base/services/core/java/com/android/server/wm/ClientLifecycleManager.java
  • packages/apps/Settings/src/com/android/settings/FallbackHome.java

FallbackHome 启动

systemService 启动 activityMangerService 后 会在 systemReady 方法中 启动对应的 fallbackHome , 其中mAtmInternal 为 ActivityTaskManagerService

public void systemReady(final Runnable goingCallback, @NonNull TimingsTraceAndSlog t) {...// Enable home activity for system user, so that the system can always boot. We don't// do this when the system user is not setup since the setup wizard should be the one// to handle home activity in this case.if (UserManager.isSplitSystemUser() &&Settings.Secure.getInt(mContext.getContentResolver(),Settings.Secure.USER_SETUP_COMPLETE, 0) != 0|| SystemProperties.getBoolean(SYSTEM_USER_HOME_NEEDED, false)) {t.traceBegin("enableHomeActivity");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();}t.traceEnd();}// 启动if (bootingSystemUser) {t.traceBegin("startHomeOnAllDisplays");mAtmInternal.startHomeOnAllDisplays(currentUserId, "systemReady");t.traceEnd();}
}

startHomeOnAllDisplays 里面又直接调用了 RootWindowContainer 遍历每个屏幕 启动对应的 startHomeOnDisplay 方法 ,接着又调用 startHomeOnDisplay 方法。观察该方法 我们可以发现里面的 startHomeOnTaskDisplayArea 方法 大概就是启动对应的 fallbackhome。

// frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.javaboolean startHomeOnAllDisplays(int userId, String reason) {boolean homeStarted = false;for (int i = getChildCount() - 1; i >= 0; i--) {final int displayId = getChildAt(i).mDisplayId;homeStarted |= startHomeOnDisplay(userId, reason, displayId);}return homeStarted;}// 启动boolean startHomeOnDisplay(int userId, String reason, int displayId, boolean allowInstrumenting,boolean fromHomeKey) {// Fallback to top focused display or default display if the displayId is invalid.if (displayId == INVALID_DISPLAY) {final Task rootTask = getTopDisplayFocusedRootTask();displayId = rootTask != null ? rootTask.getDisplayId() : DEFAULT_DISPLAY;}final DisplayContent display = getDisplayContent(displayId);// 其中的 startHomeOnTaskDisplayArea 启动对应的 fallbackHome  return display.reduceOnAllTaskDisplayAreas((taskDisplayArea, result) ->result | startHomeOnTaskDisplayArea(userId, reason, taskDisplayArea,allowInstrumenting, fromHomeKey),false /* initValue */);}

进入 startHomeOnTaskDisplayArea 可以看到 先获取对应的 homeIntent 因为还没解锁 所以获取不到 Launcher 要是解锁后 因为Launcher优先级比较高 就会变为获取到 Launcher 其中 intent 为 public static final String CATEGORY_HOME = “android.intent.category.HOME”;
找到 对应的 intent 后 进入 startHomeActivity

boolean startHomeOnTaskDisplayArea(int userId, String reason, TaskDisplayArea taskDisplayArea,boolean allowInstrumenting, boolean fromHomeKey) {...// 获取 intent ActivityInfo aInfo = null;if (taskDisplayArea == getDefaultTaskDisplayArea()) {homeIntent = mService.getHomeIntent();aInfo = resolveHomeActivity(userId, homeIntent);} else if (shouldPlaceSecondaryHomeOnDisplayArea(taskDisplayArea)) {Pair<ActivityInfo, Intent> info = resolveSecondaryHomeActivity(userId, taskDisplayArea);aInfo = info.first;homeIntent = info.second;}...// 启动 activity // Update the reason for ANR debugging to verify if the user activity is the one that// actually launched.final String myReason = reason + ":" + userId + ":" + UserHandle.getUserId(aInfo.applicationInfo.uid) + ":" + taskDisplayArea.getDisplayId();mService.getActivityStartController().startHomeActivity(homeIntent, aInfo, myReason,taskDisplayArea);
}

进入后 会看到 obtainStarter 进入对应的 设置对应的 参数后 ,执行 execute 启动actiity

// frameworks/base/services/core/java/com/android/server/wm/ActivityStartController.java
void startHomeActivity(Intent intent, ActivityInfo aInfo, String reason,TaskDisplayArea taskDisplayArea) {...// 进入启动的流程,设置对应的 参数后 ,执行 execute 启动actiity mLastHomeActivityStartResult = obtainStarter(intent, "startHomeActivity: " + reason).setOutActivity(tmpOutRecord).setCallingUid(0).setActivityInfo(aInfo).setActivityOptions(options.toBundle()).execute();
}

进入 ActivityStarter , 执行对应的 execute 方法。 execute方法前面是拼接参数。最终执行启动是 executeRequest

// frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
int execute() {...res = executeRequest(mRequest);
}

启动 Activity 流程

进入 流程 IApplicationThread 作为 对应 应用的 ActivityThread 和应用通信的 Ibinder 还没创建 所以为空。 创建对应的 ActivityRecord 后执行 startActivityUnchecked注意传入该 onResume 参数为 true 调用该 方法后,又会调用 厘米的 startActivityInner

...
// frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
private int executeRequest(Request request) {final ActivityRecord r = new ActivityRecord.Builder(mService)... // 执行启动,注意传入该 onResume 参数为 truemLastStartActivityResult = startActivityUnchecked(r, sourceRecord, voiceSession,request.voiceInteractor, startFlags, true /* doResume */, checkedOptions,inTask, inTaskFragment, restrictedBgActivity, intentGrants);
}private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,int startFlags, boolean doResume, ActivityOptions options, Task inTask,TaskFragment inTaskFragment, boolean restrictedBgActivity,NeededUriGrants intentGrants) {mService.deferWindowLayout();Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "startActivityInner");// 启动result = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor,startFlags, doResume, options, inTask, inTaskFragment, restrictedBgActivity,intentGrants);startResultSuccessful = ActivityManager.isStartResultSuccessful(result);
}

因为 前面传入的 onResume 为 true ,所以进入该方法后,会执行 resumeFocusedTasksTopActivities

int startActivityInner(final ActivityRecord r, ActivityRecord sourceRecord,IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,int startFlags, boolean doResume, ActivityOptions options, Task inTask,TaskFragment inTaskFragment, boolean restrictedBgActivity,NeededUriGrants intentGrants) {...// 为 true 进入该方法 最终调用 resumeFocusedTasksTopActivitiesif (mDoResume) {...mRootWindowContainer.resumeFocusedTasksTopActivities(mTargetRootTask, mStartActivity, mOptions, mTransientLaunch);}}
}

接着里面调用 task 的 resumeTopActivityUncheckedLocked

// frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java
boolean resumeFocusedTasksTopActivities(Task targetRootTask, ActivityRecord target, ActivityOptions targetOptions,boolean deferPause) {...boolean result = false;if (targetRootTask != null && (targetRootTask.isTopRootTaskInDisplayArea()|| getTopDisplayFocusedRootTask() == targetRootTask)) {result = targetRootTask.resumeTopActivityUncheckedLocked(target, targetOptions,deferPause);}}

调用 resumeTopActivityInnerLocked, 调用后 里面又会继续调用 resumeTopActivity 方法。

// frameworks/base/services/core/java/com/android/server/wm/Task.java
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options,boolean deferPause) {... if (isLeafTask()) {if (isFocusableAndVisible()) {someActivityResumed = resumeTopActivityInnerLocked(prev, options, deferPause);}} 
}private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options,boolean deferPause) {... final TaskFragment topFragment = topActivity.getTaskFragment();resumed[0] = topFragment.resumeTopActivity(prev, options, deferPause);
}

resumeTop 因为 还没创建对应的进程 所以 next.attachedToProcess() 为 false , 进入 else 判断, 会执行 startSpecificActivity

// frameworks/base/services/core/java/com/android/server/wm/TaskFragment.java
final boolean resumeTopActivity(ActivityRecord prev, ActivityOptions options,boolean deferPause) {if (next.attachedToProcess()) {...} else {// 创建对应的进程mTaskSupervisor.startSpecificActivity(next, true, true);}
}

执行 ActivityTaskSupervisor 里面 判断是否进程存在,不存在 执行调用 startProcessAsync 创建进程,存在则调用 realStartActivityLocked

// frameworks/base/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
void startSpecificActivity(ActivityRecord r, boolean andResume, boolean checkConfig) {//1.如果wpc不为null且hasThread表示应用Activity所属进程存在,直接realStartActivityLocked启动Activityif (wpc != null && wpc.hasThread()) {try {realStartActivityLocked(r, wpc, andResume, checkConfig);return;} catch (RemoteException e) {Slog.w(TAG, "Exception when starting activity "+ r.intent.getComponent().flattenToShortString(), e);}// If a dead object exception was thrown -- fall through to// restart the application.knownToBeDead = true;}// 创建进程mService.startProcessAsync(r, knownToBeDead, isTop, isTop ? "top-activity" : "activity");
}

创建进程

PooledLambda.obtainMessage() 获取一个 Message,并为其指定 Callback,message 在判断到有 callback 参数时候 会执行 run 方法。 即执行 mService.mAmInternal 对象的 ActivityManagerInternal::startProcess 函数,函数入参为 r.processName、r.info.applicationInfo 等5个参数。由此可知,ActivityManagerInternal 的 startProcess() 方法是请求启动应用进程的起点.

// frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
void startProcessAsync(ActivityRecord activity, boolean knownToBeDead, boolean isTop,String hostingType) {final Message m = PooledLambda.obtainMessage(ActivityManagerInternal::startProcess,mAmInternal, activity.processName, activity.info.applicationInfo, knownToBeDead,isTop, hostingType, activity.intent.getComponent());mH.sendMessage(m);
}

在这里插入图片描述
我们之前说过 mAmInternal 的实现类为 ActivityManagerService, 查看 startProcess 方法。里面调用 startProcessLocked 方法。里面在调用 startProcessLocked

// frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public void startProcess(String processName, ApplicationInfo info, boolean knownToBeDead,boolean isTop, String hostingType, ComponentName hostingName) {...// 启动进程 isolated 传入参数为 false startProcessLocked(processName, info, knownToBeDead, 0 /* intentFlags */,new HostingRecord(hostingType, hostingName, isTop),ZYGOTE_POLICY_FLAG_LATENCY_SENSITIVE, false /* allowWhileBooting */,false /* isolated */);
}final ProcessRecord startProcessLocked(String processName,ApplicationInfo info, boolean knownToBeDead, int intentFlags,HostingRecord hostingRecord, int zygotePolicyFlags, boolean allowWhileBooting,boolean isolated) {return mProcessList.startProcessLocked(processName, info, knownToBeDead, intentFlags,hostingRecord, zygotePolicyFlags, allowWhileBooting, isolated, 0 /* isolatedUid */,null /* ABI override */, null /* entryPoint */,null /* entryPointArgs */, null /* crashHandler */);
}

接着调用 ProcessList 里面的 他会先判断 app 即 ProcessRecord 是否为空。如果为空 创建对应的对象,然后调用 startProcessLocked 接着创建,, 里面又会接着调用 startProcessLocked

// frameworks/base/services/core/java/com/android/server/am/ProcessList.java
ProcessRecord startProcessLocked(String processName, ApplicationInfo info,boolean knownToBeDead, int intentFlags, HostingRecord hostingRecord,int zygotePolicyFlags, boolean allowWhileBooting, boolean isolated, int isolatedUid,String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) {if (app == null) {checkSlow(startTime, "startProcess: creating new process record");app = newProcessRecordLocked(info, processName, isolated, isolatedUid, hostingRecord);...} else {...}// 创建进程final boolean success =startProcessLocked(app, hostingRecord, zygotePolicyFlags, abiOverride);
}boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,int zygotePolicyFlags, String abiOverride) {return startProcessLocked(app, hostingRecord, zygotePolicyFlags,false /* disableHiddenApiChecks */, false /* disableTestApiChecks */,abiOverride);}

startProcessLocked 里面又对 app 属性进行赋值,最终在调用 startProcessLocked, 里面接着调用 startProcess 方法 , 其中 entryPoint 为 android.app.ActivityThread。 这就是 应用程序 启动会 走 ActivityThread 入口

boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,int zygotePolicyFlags, boolean disableHiddenApiChecks, boolean disableTestApiChecks,String abiOverride) {// Start the process.  It will either succeed and return a result containing// the PID of the new process, or else throw a RuntimeException.// 创建进程时候,入口final String entryPoint = "android.app.ActivityThread";return startProcessLocked(hostingRecord, entryPoint, app, uid, gids,runtimeFlags, zygotePolicyFlags, mountExternal, seInfo, requiredAbi,instructionSet, invokeWith, startTime);
}boolean startProcessLocked(HostingRecord hostingRecord, String entryPoint, ProcessRecord app,int uid, int[] gids, int runtimeFlags, int zygotePolicyFlags, int mountExternal,String seInfo, String requiredAbi, String instructionSet, String invokeWith,long startTime) {// 创建进程final Process.ProcessStartResult startResult = startProcess(hostingRecord,entryPoint, app,uid, gids, runtimeFlags, zygotePolicyFlags, mountExternal, seInfo,requiredAbi, instructionSet, invokeWith, startTime);handleProcessStartedLocked(app, startResult.pid, startResult.usingWrapper,startSeq, false);
}

startProcess 方法 会对各种情况做判断,启动 fallbackHome 是走 Process.start

private Process.ProcessStartResult startProcess(HostingRecord hostingRecord, String entryPoint,ProcessRecord app, int uid, int[] gids, int runtimeFlags, int zygotePolicyFlags,int mountExternal, String seInfo, String requiredAbi, String instructionSet,String invokeWith, long startTime) {// 启动webview的if (hostingRecord.usesWebviewZygote()) {startResult = startWebView(entryPoint,app.processName, uid, uid, gids, runtimeFlags, mountExternal,app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,app.info.dataDir, null, app.info.packageName,app.getDisabledCompatChanges(),new String[]{PROC_START_SEQ_IDENT + app.getStartSeq()});} else if (hostingRecord.usesAppZygote()) {final AppZygote appZygote = createAppZygoteForProcessIfNeeded(app);// We can't isolate app data and storage data as parent zygote already did that.startResult = appZygote.getProcess().start(entryPoint,app.processName, uid, uid, gids, runtimeFlags, mountExternal,app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,app.info.dataDir, null, app.info.packageName,/*zygotePolicyFlags=*/ ZYGOTE_POLICY_FLAG_EMPTY, isTopApp,app.getDisabledCompatChanges(), pkgDataInfoMap, allowlistedAppDataInfoMap,false, false,new String[]{PROC_START_SEQ_IDENT + app.getStartSeq()});} else {// 应用启动regularZygote = true;startResult = Process.start(entryPoint,app.processName, uid, uid, gids, runtimeFlags, mountExternal,app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,app.info.dataDir, invokeWith, app.info.packageName, zygotePolicyFlags,isTopApp, app.getDisabledCompatChanges(), pkgDataInfoMap,allowlistedAppDataInfoMap, bindMountAppsData, bindMountAppStorageDirs,new String[]{PROC_START_SEQ_IDENT + app.getStartSeq()});}
}

而progress start方法 里面实际又是调用 ZygoteProcess 的 start 方法 。 zygoteProcess 里面又调用 startViaZygote 方法。 该方法里面会对 创建的一些参数 进行初始化。其中 之前传入的 entryPoint 作为参数 放到最后。根据之前的文章 知道会解析 – 的参数,把没有的参数 放到remaind 参数里面 反射调用 启动main 方法

// frameworks/base/core/java/android/os/ZygoteProcess.javapublic final Process.ProcessStartResult start(@NonNull final String processClass,....{....return startViaZygote(processClass, niceName, uid, gid, gids,runtimeFlags, mountExternal, targetSdkVersion, seInfo,abi, instructionSet, appDataDir, invokeWith, /*startChildZygote=*/ false,packageName, zygotePolicyFlags, isTopApp, disabledCompatChanges,pkgDataInfoMap, allowlistedDataInfoList, bindMountAppsData,bindMountAppStorageDirs, zygoteArgs);
}private Process.ProcessStartResult startViaZygote(@NonNull final String processClass ...){..// 初始化参数ArrayList<String> argsForZygote = new ArrayList<>();// --runtime-args, --setuid=, --setgid=,// and --setgroups= must go firstargsForZygote.add("--runtime-args");argsForZygote.add("--setuid=" + uid);argsForZygote.add("--setgid=" + gid);...// 最后要反射的参数argsForZygote.add(processClass);if (extraArgs != null) {Collections.addAll(argsForZygote, extraArgs);}synchronized(mLock) {// The USAP pool can not be used if the application will not use the systems graphics// driver.  If that driver is requested use the Zygote application start path.return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi),zygotePolicyFlags,argsForZygote);}
}

zygoteSendArgsAndGetResult 接着调用 attemptZygoteSendArgsAndGetResult ,将参数拼接为 string 字符串, 该方法通过 socket 将消息 发送给 zygote 创建进程。

private Process.ProcessStartResult zygoteSendArgsAndGetResult(ZygoteState zygoteState, int zygotePolicyFlags, @NonNull ArrayList<String> args)throws ZygoteStartFailedEx {...if (shouldAttemptUsapLaunch(zygotePolicyFlags, args)) {try {return attemptUsapSendArgsAndGetResult(zygoteState, msgStr);} catch (IOException ex) {// If there was an IOException using the USAP pool we will log the error and// attempt to start the process through the Zygote.Log.e(LOG_TAG, "IO Exception while communicating with USAP pool - "+ ex.getMessage());}}return attemptZygoteSendArgsAndGetResult(zygoteState, msgStr);
}
// 发送对应 socket
private Process.ProcessStartResult attemptZygoteSendArgsAndGetResult(ZygoteState zygoteState, String msgStr) throws ZygoteStartFailedEx {try {final BufferedWriter zygoteWriter = zygoteState.mZygoteOutputWriter;final DataInputStream zygoteInputStream = zygoteState.mZygoteInputStream;zygoteWriter.write(msgStr);zygoteWriter.flush();// Always read the entire result from the input stream to avoid leaving// bytes in the stream for future process starts to accidentally stumble// upon.Process.ProcessStartResult result = new Process.ProcessStartResult();// 读取返回创建的pidresult.pid = zygoteInputStream.readInt();result.usingWrapper = zygoteInputStream.readBoolean();if (result.pid < 0) {throw new ZygoteStartFailedEx("fork() failed");}return result;} catch (IOException ex) {zygoteState.close();Log.e(LOG_TAG, "IO Exception while communicating with Zygote - "+ ex.toString());throw new ZygoteStartFailedEx(ex);}}

发送 socket 对应的 参数 zygoteWriter 是在 ZygoteState 初始化的时候, 传入 。
在这里插入图片描述
而该参数又是通过 connect 方法的时候 。创建 LocalSocket。 创建socket。并建立连接。 创建该 socket 传入的地址 为 LocalSocketAddress zygoteSocketAddress 参数。该参数又是在 ZygoteProcess 初始化的时候 创建 对应字符串 为 zygote
在这里插入图片描述

	// frameworks/base/core/java/com/android/internal/os/Zygote.java/*** @hide for internal use only.*/public static final String PRIMARY_SOCKET_NAME = "zygote";/*** @hide for internal use only.*/public static final String SECONDARY_SOCKET_NAME = "zygote_secondary";// frameworks/base/core/java/android/os/ZygoteProcess.java
public ZygoteProcess() {mZygoteSocketAddress =new LocalSocketAddress(Zygote.PRIMARY_SOCKET_NAME,LocalSocketAddress.Namespace.RESERVED);mZygoteSecondarySocketAddress =new LocalSocketAddress(Zygote.SECONDARY_SOCKET_NAME,LocalSocketAddress.Namespace.RESERVED);mUsapPoolSocketAddress =new LocalSocketAddress(Zygote.USAP_POOL_PRIMARY_SOCKET_NAME,LocalSocketAddress.Namespace.RESERVED);mUsapPoolSecondarySocketAddress =new LocalSocketAddress(Zygote.USAP_POOL_SECONDARY_SOCKET_NAME,LocalSocketAddress.Namespace.RESERVED);// This constructor is used to create the primary and secondary Zygotes, which can support// Unspecialized App Process Pools.mUsapPoolSupported = true;}

这样就把消息 发给了 zygote 那边。之前的文章 ZygoteInit 执行 main 函数后,会执行 zygoteServer.runSelectLoop(abiList); 方法 里面为 死循环 一直等待新消息 唤醒。收到消息后 执行 processCommand

					if (pollIndex == 0) {// Zygote server socketZygoteConnection newPeer = acceptCommandPeer(abiList);peers.add(newPeer);socketFDs.add(newPeer.getFileDescriptor());} else if (pollIndex < usapPoolEventFDIndex) {// Session socket accepted from the Zygote server sockettry {ZygoteConnection connection = peers.get(pollIndex);boolean multipleForksOK = !isUsapPoolEnabled()&& ZygoteHooks.isIndefiniteThreadSuspensionSafe();final Runnable command =connection.processCommand(this, multipleForksOK);}

processCommand 方法方法里面 又是我们熟悉的 fork 进程 Zygote.forkAndSpecialize
fork 出进程后 调用 handleChildProc 方法处理进程 。处理应用程序进程:将 ActivityThread 的 main() 方法封装到 Runnable 中
在这里插入图片描述
因为 非zygote 进程,所以 执行 ZygoteInit.zygoteInit 。 说明:ZygoteInit.nativeZygoteInit() 启动了 Binder 线程池,应用程序进程此后可以通过 Binder 实现跨进程通讯。RuntimeInit.applicationInit 里面通过调用 findStaticMain 基于反射创建 ActivityThread并返回 runable。 最终会返回给 ZygoteInit 的 main() 方法执行其 run() 方法

private Runnable handleChildProc(ZygoteArguments parsedArgs,FileDescriptor pipeFd, boolean isZygote) {...if (!isZygote) {return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,parsedArgs.mDisabledCompatChanges,parsedArgs.mRemainingArgs, null /* classLoader */);} else {return ZygoteInit.childZygoteInit(parsedArgs.mRemainingArgs  /* classLoader */);}
}public static Runnable zygoteInit(int targetSdkVersion, long[] disabledCompatChanges,String[] argv, ClassLoader classLoader) {if (RuntimeInit.DEBUG) {Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");}Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");RuntimeInit.redirectLogStreams();RuntimeInit.commonInit();// //启动 Binder 线程池ZygoteInit.nativeZygoteInit();return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv,classLoader);}

在这里插入图片描述

在这里插入图片描述
这样就调用到 ActivityThrad main 方法。

ActivityThrad 与 AMS

进入 ActivityThrad 方法,里面包含对 Looper 的创建。创建 ActivityThread 因为非系统进程 所以 attach 传入为 false 。 loop 开启 循环

public static void main(String[] args) {// looper跟当前线程创建Looper.prepareMainLooper();// 创建 ActivityThread ActivityThread thread = new ActivityThread();... thread.attach(false, startSeq);if (sMainThreadHandler == null) {//创建主线程 H 类:return mH, mH 在定义时就被初始化:final H mH = new H()sMainThreadHandler = thread.getHandler();}...//开启消息循环Looper.loop();
}

查看 attach 方法 因为传入为 false 。所以第一个分支。其中 mgr 为 AMS 的binder对象。这样调用 attachApplication 将当前 app 进程的 ibinder对象传给AMS 这样 AMS 就可以调用我们进程的方法

// frameworks/base/core/java/android/app/ActivityThread.java
private void attach(boolean system, long startSeq) {sCurrentActivityThread = this;mSystemThread = system;if (!system) { //system  = false...//mAppThread 为 ApplicationThread 类型,在定义时就被初始化RuntimeInit.setApplicationObject(mAppThread.asBinder());//获取 AMSfinal IActivityManager mgr = ActivityManager.getService();try {mgr.attachApplication(mAppThread, startSeq);}...}...
}

IActivityManger 也是通过 ServiceManger 获取, IActivityManger 的实现 为 ActivityManagerService

// frameworks/base/core/java/android/app/ActivityManager.java
// 获取单例
private static IActivityTaskManager getTaskService() {return ActivityTaskManager.getService();}@UnsupportedAppUsageprivate static final Singleton<IActivityManager> IActivityManagerSingleton =new Singleton<IActivityManager>() {@Overrideprotected IActivityManager create() {final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);final IActivityManager am = IActivityManager.Stub.asInterface(b);return am;}};

查看 ActivityManagerService 里面的 attachApplication 方法,获取了调用的pid 后,接着又调用了 attachApplicationLocked 方法。里面通过 bindApplication 调用 Applicaiton的 onCreate 方法。getCommonServicesLocked() 方法中将 WMS、DMS、IMS、PMS 等服务的 name 和 binder 添加到 mAppBindArgs(类型:ArrayMap<String, IBinder>)中,并将其返回。这样我们在Activity 中就可以通过context 获取。 最后在调用 mAtmInternal.attachApplication 该方法会调用获取对应 入口activity。

	@Overridepublic final void attachApplication(IApplicationThread thread, long startSeq) {if (thread == null) {throw new SecurityException("Invalid application interface");}synchronized (this) {int callingPid = Binder.getCallingPid();final int callingUid = Binder.getCallingUid();final long origId = Binder.clearCallingIdentity();attachApplicationLocked(thread, callingPid, callingUid, startSeq);Binder.restoreCallingIdentity(origId);}}private boolean attachApplicationLocked(@NonNull IApplicationThread thread,int pid, int callingUid, long startSeq) {// 绑定AIDL监听try {AppDeathRecipient adr = new AppDeathRecipient(app, pid, thread);thread.asBinder().linkToDeath(adr, 0);app.setDeathRecipient(adr);} catch (RemoteException e) {app.resetPackageList(mProcessStats);mProcessList.startProcessLocked(app,new HostingRecord("link fail", processName),ZYGOTE_POLICY_FLAG_EMPTY);return false;}...// 走else 的 bindApplication 调用 Applicaiton的 onCreate 方法。if (app.isolatedEntryPoint != null) {...} else if (instr2 != null) {thread.bindApplication(processName, appInfo, providers, instr2.mClass, profilerInfo, instr2.mArguments,instr2.mWatcher, instr2.mUiAutomationConnection, testMode, mBinderTransactionTrackingEnabled, enableTrackAllocation, isRestrictedBackupMode || !normalMode, app.isPersistent(),new Configuration(app.getWindowProcessController().getConfiguration()), app.compat, getCommonServicesLocked(app.isolated), mCoreSettingsObserver.getCoreSettingsLocked(),buildSerial, autofillOptions, contentCaptureOptions, app.mDisabledCompatChanges);} else {//第 4 个参数为 ComponentName 类型,影响 Instrumentation 的创建方式thread.bindApplication(processName, appInfo, providers, null, profilerInfo, null, null, null, testMode,mBinderTransactionTrackingEnabled, enableTrackAllocation, isRestrictedBackupMode || !normalMode, app.isPersistent(), new Configuration(app.getWindowProcessController().getConfiguration()),app.compat, getCommonServicesLocked(app.isolated), mCoreSettingsObserver.getCoreSettingsLocked(),buildSerial, autofillOptions, contentCaptureOptions, app.mDisabledCompatChanges);}...app.makeActive(thread, mProcessStats);// See if the top visible activity is waiting to run in this process...// 启动对应的launch Activityif (normalMode) {try {didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());} catch (Exception e) {Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);badApp = true;}}...// Find any services that should be running in this process...if (!badApp) {try {didSomething |= mServices.attachApplicationLocked(app, processName);checkTime(startTime, "attachApplicationLocked: after mServices.attachApplicationLocked");} catch (Exception e) {Slog.wtf(TAG, "Exception thrown starting services in " + app, e);badApp = true;}}}

在这里插入图片描述

查看 ActivityThrad 里面的 BindApplication 方法。通过将传回来的服务,放到 ServiceManger 里面。 在发送 消息 到 BIND_APPLICATION


public final void bindApplication(String processName, ApplicationInfo appInfo, List<ProviderInfo> providers, ComponentName instrumentationName, ProfilerInfo profilerInfo, Bundle instrumentationArgs,IInstrumentationWatcher instrumentationWatcher, IUiAutomationConnection instrumentationUiConnection, int debugMode, boolean enableBinderTracking, boolean trackAllocation, boolean isRestrictedBackupMode, boolean persistent, Configuration config, CompatibilityInfo compatInfo, Map services, Bundle coreSettings,String buildSerial, AutofillOptions autofillOptions, ContentCaptureOptions contentCaptureOptions, long[] disabledCompatChanges) {if (services != null) {...// sCache.putAll(services), sCache 为 Map<String, IBinder> 类型ServiceManager.initServiceCache(services);}//relaunchAllActivities(false)setCoreSettings(coreSettings);AppBindData data = new AppBindData();...data.instrumentationName = instrumentationName;...//ActivityThread 的内部类 H 类处理消息,将业务从 Binder 线程切换至主线程sendMessage(H.BIND_APPLICATION, data);

收到消息后 执行了 handleBindApplication 方法。对JVM和堆栈进行设置。设置 UI线程为重要线程。对时间 语言 等进行设置。 **创建 Instrumentation (控制activity的生命周期)**并 通过 createAppContext 创建上下文。最后调用 mInstrumentation.callApplicationOnCreate(app); 执行 Application 的 onCreate 。

private void handleBindApplication(AppBindData data) {// 将当前UI线程设置为最重要进程// Register the UI Thread as a sensitive thread to the runtime.VMRuntime.registerSensitiveThread();// In the case the stack depth property exists, pass it down to the runtime.// 设置当前调试的跟踪栈深度String property = SystemProperties.get("debug.allocTracker.stackDepth");if (property.length() != 0) {VMDebug.setAllocTrackerStackDepth(Integer.parseInt(property));}if (data.trackAllocation) {DdmVmInternal.setRecentAllocationsTrackingEnabled(true);}...final InstrumentationInfo ii;...//创建 Application 的 Contextfinal ContextImpl appContext = ContextImpl.createAppContext(this, data.info);...//ii 是否为 null,取决于 data.instrumentationName 是否为 nullif (ii != null) {...//创建 Instrumentation 的 Context, final ContextImpl instrContext = ContextImpl.createAppContext(this, pi, appContext.getOpPackageName());try {final ClassLoader cl = instrContext.getClassLoader();mInstrumentation = (Instrumentation) cl.loadClass(data.instrumentationName.getClassName()).newInstance();}...//注入 ActivityThread、Context、ComponentName 等mInstrumentation.init(this, instrContext, appContext, component, data.instrumentationWatcher, data.instrumentationUiAutomationConnection);...} else {mInstrumentation = new Instrumentation();//注入 ActivityThreadmInstrumentation.basicInit(this);}...Application app;...try {//创建 Application 对象app = data.info.makeApplication(data.restrictedBackupMode, null);...mInitialApplication = app;...try {mInstrumentation.onCreate(data.instrumentationArgs);}...try {//调用 Application 的 onCreate() 方法mInstrumentation.callApplicationOnCreate(app);}...}...
}

回到之前的 mAtmInternal.attachApplication 方法。该方法会启动对应的 activity,该方法具体实现为 ActivityTaskManagerService 。执行

		// frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java@HotPath(caller = HotPath.PROCESS_CHANGE)@Overridepublic boolean attachApplication(WindowProcessController wpc) throws RemoteException {synchronized (mGlobalLockWithoutBoost) {if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) {Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "attachApplication:" + wpc.mName);}try {return mRootWindowContainer.attachApplication(wpc);} finally {Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);}}}

attachApplication 方法又会调用 RootWindowContainerstartActivityForAttachedApplicationIfNeeded方法。继而调用 realStartActivityLocked

// frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java
boolean attachApplication(WindowProcessController app) throws RemoteException {final PooledFunction c = PooledLambda.obtainFunction(RootWindowContainer::startActivityForAttachedApplicationIfNeeded, this,PooledLambda.__(ActivityRecord.class), app,rootTask.topRunningActivity());rootTask.forAllActivities(c);
}private boolean startActivityForAttachedApplicationIfNeeded(ActivityRecord r,WindowProcessController app, ActivityRecord top) {if (r.finishing || !r.showToCurrentUser() || !r.visibleIgnoringKeyguard || r.app != null|| app.mUid != r.info.applicationInfo.uid || !app.mName.equals(r.processName)) {return false;}try {if (mTaskSupervisor.realStartActivityLocked(r, app,top == r && r.getTask().canBeResumed(r) /*andResume*/,true /*checkConfig*/)) {mTmpBoolean = true;}} catch (RemoteException e) {Slog.w(TAG, "Exception in new application when starting activity "+ top.intent.getComponent().flattenToShortString(), e);mTmpRemoteException = e;return true;}return false;}

realStartActivityLocked 里面又会执行 scheduleTransaction 该方法会通过调用 AIDL scheduleTransaction 在 ActivityThread 执行。

boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,boolean andResume, boolean checkConfig) throws RemoteException {...mService.getLifecycleManager().scheduleTransaction(clientTransaction);
}

在这里插入图片描述
在这里插入图片描述
在ActivityThread 那边会发送 Handler 消息 ActivityThread.H.EXECUTE_TRANSACTION。该方法会执行 execute 方法,最终执行到 handleRelaunchActivity 方法启动l auncher 方法。这里有小技巧因为里面堆栈较多实现类。所以这里在 handleLaunchActivity 添加堆栈打印。然后启动模拟器 查看堆栈。可以看到 最终是通过 TransactionExecutor.execute -> TransactionExecutor.executeCallbacks -> ActivityTransactionItem.execute -> ActivityRelaunchItem.execute -> ActivityThread.handleRelaunchActivity 启动 FallbackHome 的 主Activity。

public Activity handleLaunchActivity(ActivityClientRecord r,PendingTransactionActions pendingActions, Intent customIntent) {Slog.v(TAG, "handleLaunchActivity", new NullPointerException());
}

在这里插入图片描述

启动真正的 Launcher

拉起 FallbackHome 界面后,该Activity 位于 packages/apps/Settings/src/com/android/settings/FallbackHome.java,可以通过 过滤 android.intent.category.HOME 查找
activity 的 onCreate 方法 ,注册了解锁的广播监听。收到即调用 maybeFinish 方法。

protected void onCreate(Bundle savedInstanceState) {// 设置壁纸mWallManager = getSystemService(WallpaperManager.class);if (mWallManager == null) {Log.w(TAG, "Wallpaper manager isn't ready, can't listen to color changes!");} else {loadWallpaperColors(flags);}// 注册解锁监听广播registerReceiver(mReceiver, new IntentFilter(Intent.ACTION_USER_UNLOCKED));// 开始判断maybeFinish();
}

该方法会 每隔 500毫秒 去获取 Intent.CATEGORY_HOME 的 activity 。并判断是否和当前包名一样,如果不一样则代表 已经检测到了 Launch 。结束自己并启动真正的 launch 。(因为解锁后就可以检测到 Launcher 而且优先级比 FallbackHome 高

	private void maybeFinish() {if (getSystemService(UserManager.class).isUserUnlocked()) {// 获取对应的 intent final Intent homeIntent = new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME);final ResolveInfo homeInfo = getPackageManager().resolveActivity(homeIntent, 0);// 判断包名是否一致 ,一致延时500 毫秒 在检测if (Objects.equals(getPackageName(), homeInfo.activityInfo.packageName)) {Log.d(TAG, "User unlocked but no home; let's hope someone enables one soon?");mHandler.sendEmptyMessageDelayed(0, 500);} else {Log.d(TAG, "User unlocked and real home found; let's go!");getSystemService(PowerManager.class).userActivity(SystemClock.uptimeMillis(), false);finish();}}}// 延时任务检测private Handler mHandler = new Handler() {@Overridepublic void handleMessage(Message msg) {maybeFinish();}};

通过 PowerManger 的 userActivity 启动, 可以看到 最终 是调用了 IPowerManager , 查找 Context.POWER_SERVICE 看其注册地方。注册了 power ,对应的实现类为 PowerManagerService 。frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/46345.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Python】数据处理(mongodb、布隆过滤器、索引)

数据 数据预处理 df pd.read_csv(file_path, encodingANSI) csv的编码方式一定要用 ANSI。要不然会出现各种报错 import pandas as pd from datetime import datetime# 读取CSV文件 file_path book_douban.csv df pd.read_csv(file_path, encodingANSI)# 定义一个函数来…

基于SpringBoot协同过滤算法商品推荐系统(源码+lw+部署文档+讲解等)

前言&#xff1a; 博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行前辈交流✌ 技术范围&#xff1a;SpringBo…

【C++】入门基础(引用、inline、nullptr)

目录 一.引用 1.引用的定义 2.引用的特性 3.引用的使用场景 4.const引用 5.引用和指针的区别 二.inline 三.nullptr 一.引用 1.引用的定义 引用不是新定义一个变量&#xff0c;而是给已经存在的变量取一个别名&#xff0c;编译器不会给引用变量开辟内存空间&#xff0c…

SpringSecurity6 | 获取登录用户的认证信息

✅作者简介:大家好,我是Leo,热爱Java后端开发者,一个想要与大家共同进步的男人😉😉 🍎个人主页:Leo的博客 💞当前专栏: 循序渐进学SpringSecurity6 ✨特色专栏: MySQL学习 🥭本文内容: SpringSecurity6 | 获取登录用户的认证信息 📚个人知识库: Leo知识库…

【C++初阶】类和对象(下)

【C初阶】类和对象下 &#x1f955;个人主页&#xff1a;开敲&#x1f349; &#x1f525;所属专栏&#xff1a;C&#x1f96d; &#x1f33c;文章目录&#x1f33c; 1. 再谈构造函数 2. 类型转换 3. static成员 4. 友元 5. 内部类 1. 再谈构造函数 ① 之前我们实现构造函…

关于Qt Creator 使用Qt Quick的Design模式设置

关于使用Qt Quick的Design模式设置&#xff1a; 如描述所言&#xff1a; 如果使用Design模式打开qml文件失败显示如下&#xff1a; 首先确认自己是否安装了Qt Design Studio 如果安装了仍然不显示&#xff0c;则需要勾选下面三个地方才能用Design模式打开.ui.qml文件&#…

gradle设置优先使用maven本地仓库

1. gradle优先使用maven本地库的逻辑 Created with Raphal 2.3.0 开始 maven本地库 是否存在依赖&#xff1f; 使用maven 本地库的依赖 结束 下载依赖到 gradle本地库 yes no 2. 配置 在app/build.gradle.kts中添加mavenLocal() mavenLocal()9. 参考文章 https://www.cnblog…

24_YOLOV3-SPP网络详解

1.1 简介 YOLOv3-SPP是对YOLOv3&#xff08;You Only Look Once version 3&#xff09;目标检测模型的一种改进版本&#xff0c;其中"SPP"代表空间金字塔池化&#xff08;Spatial Pyramid Pooling&#xff09;。这个改进主要是为了增强网络对不同尺度物体的检测能力…

Qt5离线安装包无法下载问题解决办法

Qt5离线安装包无法下载问题解决办法 文章目录 Qt5离线安装包无法下载问题解决办法1、前言2、Qt5安装包下载办法 更多精彩内容&#x1f449;个人内容分类汇总 &#x1f448;&#x1f449;Qt开发经验 &#x1f448; 1、前言 Qt安装包官方下载地址 Qt5离线安装包目前在国内已经被墙…

Golang | Leetcode Golang题解之第233题数字1的个数

题目&#xff1a; 题解&#xff1a; func countDigitOne(n int) (ans int) {// mulk 表示 10^k// 在下面的代码中&#xff0c;可以发现 k 并没有被直接使用到&#xff08;都是使用 10^k&#xff09;// 但为了让代码看起来更加直观&#xff0c;这里保留了 kfor k, mulk : 0, 1;…

大模型系列3--pytorch dataloader的原理

pytorch dataloader运行原理 1. 背景2. 环境搭建2.1. 安装WSL & vscode2.2. 安装conda & pytorch_gpu环境 & pytorch 2.112.3 命令行验证python环境2.4. vscode启用pytorch_cpu虚拟环境 3. 调试工具3.1. vscode 断点调试3.2. py-spy代码栈探测3.3. gdb attach3.4. …

IDEA社区版使用Maven archetype 创建Spring boot 项目

1.新建new project 2.选择Maven Archetype 3.命名name 4.选择存储地址 5.选择jdk版本 6.Archetype使用webapp 7.create创建项目 创建好长这样。 检查一下自己的Maven是否是自己的。 没问题的话就开始增添java包。 [有的人连resources包也没有&#xff0c;那就需要自己添…

每日一题~ cf div3 957 D+E(若只dp,暴力枚举)

D题 简单的dp&#xff0c;我当时没反应过来 这是 dp&#xff0c;好吧&#xff0c;其实是很久没做题了。&#xff08;脑袋木了&#xff09; 题意&#xff1a;n m k n 长的字符 &#xff0c;m k 可以跳跃的最大距离&#xff08;每次跳跃的距离1< <m) k 在水里游泳的最大值 …

IP 地址与 CDN 性能优化

内容分发网络&#xff08;CDN&#xff09;就是通过内容分配到离用户最优的服务器来提高访问速度。而IP地址如何分配与管理就是CND技术的基础。本文将来探讨介绍CDN中的IP地址分配与管理&#xff0c;以及如何通过CDN优化网络性能。 首先我们来了解CDN的基本原理 CDN是一种分布式…

Java核心篇之JVM探秘:内存模型与管理初探

系列文章目录 第一章 Java核心篇之JVM探秘&#xff1a;内存模型与管理初探 第二章 Java核心篇之JVM探秘&#xff1a;对象创建与内存分配机制 第三章 Java核心篇之JVM探秘&#xff1a;垃圾回收算法与垃圾收集器 第四章 Java核心篇之JVM调优实战&#xff1a;Arthas工具使用及…

基于Java中的SSM框架实现暖心家装平台系统项目【项目源码+论文说明】

基于Java中的SSM框架实现暖心家装平台系统演示 摘要 自从互联网技术得到大规模的应用以后&#xff0c;传统家装企业面临全新的竞争激烈的市场环境。要想占得当前家装营销与管理的先机&#xff0c;除了要加强内部管理&#xff0c;提高企业内部运营效率&#xff0c;更要积极推进…

google 浏览器插件开发简单学习案例:计算器

1、首先&#xff0c;我们需要创建扩展的文件结构 2、创建 manifest.json 文件 是Chrome插件的配置文件&#xff0c;定义了插件的基本信息和资源。 {"manifest_version": 3,"name": "Simple Calculator","version": "1.0"…

[K8S]一、Flink on K8S

Kubernetes | Apache Flink 先编辑好这5个配置文件&#xff0c;然后再直接执行 kubectl create -f ./ kubectl get all kubectl get nodes kubectl get pods kubectl get pod -o wide kubectl get cm -- 获取所有的configmap 配置文件 kubectl logs pod_name -- 查看…

链接追踪系列-00.es设置日志保存7天-番外篇

索引生命周期策略 ELK日志我们一般都是按天存储&#xff0c;例如索引名为"zipkin-span-2023-03-24"&#xff0c;因为日志量所占的存储是非常大的&#xff0c;我们不能一直保存&#xff0c;而是要定期清理旧的&#xff0c;这里就以保留7天日志为例。 自动清理7天以前…

Java二十三种设计模式-工厂方法模式(2/23)

工厂方法模式&#xff1a;设计模式中的瑞士军刀 引言 在软件开发中&#xff0c;工厂方法模式是一种常用的创建型设计模式&#xff0c;它用于处理对象的创建&#xff0c;将对象的实例化推迟到子类中进行。这种模式不仅简化了对象的创建过程&#xff0c;还提高了代码的可维护性…