1.2ActivityThread分析
目录介绍
- 01.ActivityThread介绍
- 02.启动Activity所属的应用进程
- 03.ActivityThread的main方法
01.ActivityThread介绍
- 整个Android应用进程的体系非常复杂,而ActivityThread是真正的核心类,它的main方法,是整个应用进程的入口。
- 接下来,就来了解一下,如何走到ActivityThread的main方法,然后在main方法中又做了什么……也就是从来里来,到哪里去?
02.启动Activity所属的应用进程
- 大概流程如下所示
ActivityManagerService.startProcessLocked() Process.start() ActivityThread.main() ActivityThread.attach() ActivityManagerNative.getDefault().attachApplication() ActivityManagerService.attachApplication()
- 首先看一下startProcessLocked()方法的具体实现:
private final void startProcessLocked(ProcessRecord app, String hostingType, String hostingNameStr) { startProcessLocked(app, hostingType, hostingNameStr, null /* abiOverride */, null /* entryPoint */, null /* entryPointArgs */); }
- 然后回调了其重载的startProcessLocked方法:
private final void startProcessLocked(ProcessRecord app, String hostingType, String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) { ... boolean isActivityProcess = (entryPoint == null); if (entryPoint == null) entryPoint = "android.app.ActivityThread"; Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " + app.processName); checkTime(startTime, "startProcess: asking zygote to start proc"); Process.ProcessStartResult startResult = Process.start(entryPoint, app.processName, uid, uid, gids, debugFlags, mountExternal, app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet, app.info.dataDir, entryPointArgs); checkTime(startTime, "startProcess: returned from zygote!"); ... }
- 可以发现其经过一系列的初始化操作之后调用了Process.start方法,并且传入了启动的类名“android.app.ActivityThread”:
public static final ProcessStartResult start(final String processClass, final String niceName, int uid, int gid, int[] gids, int debugFlags, int mountExternal, int targetSdkVersion, String seInfo, String abi, String instructionSet, String appDataDir, String[] zygoteArgs) { try { return startViaZygote(processClass, niceName, uid, gid, gids, debugFlags, mountExternal, targetSdkVersion, seInfo, abi, instructionSet, appDataDir, zygoteArgs); } catch (ZygoteStartFailedEx ex) { Log.e(LOG_TAG, "Starting VM process through Zygote failed"); throw new RuntimeException( "Starting VM process through Zygote failed", ex); } }
- 然后调用了startViaZygote方法:
private static ProcessStartResult startViaZygote(final String processClass, final String niceName, final int uid, final int gid, final int[] gids, int debugFlags, int mountExternal, int targetSdkVersion, String seInfo, String abi, String instructionSet, String appDataDir, String[] extraArgs) throws ZygoteStartFailedEx { synchronized(Process.class) { ... return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote); } }
- 继续查看一下zygoteSendArgsAndGetResult方法的实现:
private static ProcessStartResult zygoteSendArgsAndGetResult( ZygoteState zygoteState, ArrayList<String> args) throws ZygoteStartFailedEx { try { /** * See com.android.internal.os.ZygoteInit.readArgumentList() * Presently the wire format to the zygote process is: * a) a count of arguments (argc, in essence) * b) a number of newline-separated argument strings equal to count * * After the zygote process reads these it will write the pid of * the child or -1 on failure, followed by boolean to * indicate whether a wrapper process was used. */ final BufferedWriter writer = zygoteState.writer; final DataInputStream inputStream = zygoteState.inputStream; writer.write(Integer.toString(args.size())); writer.newLine(); int sz = args.size(); for (int i = 0; i < sz; i++) { String arg = args.get(i); if (arg.indexOf('\n') >= 0) { throw new ZygoteStartFailedEx( "embedded newlines not allowed"); } writer.write(arg); writer.newLine(); } writer.flush(); // Should there be a timeout on this? ProcessStartResult result = new ProcessStartResult(); result.pid = inputStream.readInt(); if (result.pid < 0) { throw new ZygoteStartFailedEx("fork() failed"); } result.usingWrapper = inputStream.readBoolean(); return result; } catch (IOException ex) { zygoteState.close(); throw new ZygoteStartFailedEx(ex); } }
- 可以发现其最终调用了Zygote并通过socket通信的方式让Zygote进程fork除了一个新的进程,并根据我们刚刚传递的"android.app.ActivityThread"字符串,反射出该对象并执行ActivityThread的main方法。这样我们所要启动的应用进程这时候其实已经启动了,但是还没有执行相应的初始化操作。
03.ActivityThread的main方法
- 为什么我们平时都将ActivityThread称之为ui线程或者是主线程
- 这里可以看出,应用进程被创建之后首先执行的是ActivityThread的main方法,所以我们将ActivityThread成为主线程。
- 这时候我们看一下ActivityThread的main方法的实现逻辑。
public static void main(String[] args) { ... Process.setArgV0("<pre-initialized>"); //初始化Looper Looper.prepareMainLooper(); //先创建ActivityThread对象 ActivityThread thread = new ActivityThread(); //attach thread.attach(false); if (sMainThreadHandler == null) { sMainThreadHandler = thread.getHandler(); } if (false) { Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG, "ActivityThread")); } // End of event ActivityThreadMain. Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); //开启loop循环 Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited"); }
- 在main方法中主要执行了一些初始化的逻辑,并且创建了一个UI线程消息队列,这也就是为什么我们可以在主线程中随意的创建Handler而不会报错的原因,这里提出一个问题,大家可以思考一下:子线程可以创建Handler么?可以的话应该怎么做?
- 然后执行了ActivityThread的attach方法,这里我们看一下attach方法执行了那些逻辑操作。
private void attach(boolean system) { ... final IActivityManager mgr = ActivityManagerNative.getDefault(); try { mgr.attachApplication(mAppThread); } catch (RemoteException ex) { // Ignore } ... }
- 刚刚已经分析过ActivityManagerNative是ActivityManagerService的Binder client,所以这里调用了attachApplication实际上就是通过Binder机制调用了ActivityManagerService的attachApplication,具体调用的过程,我们看一下ActivityManagerService是如何实现的:
@Override public final void attachApplication(IApplicationThread thread) { synchronized (this) { int callingPid = Binder.getCallingPid(); final long origId = Binder.clearCallingIdentity(); attachApplicationLocked(thread, callingPid); Binder.restoreCallingIdentity(origId); } }
- 可以发现其回调了attachApplicationLocked方法,我们看一下这个方法的实现逻辑。这个在ActivityManagerService类中。
@GuardedBy("this") private final boolean attachApplicationLocked(IApplicationThread thread, int pid, int callingUid, long startSeq) { ...... mStackSupervisor.getActivityMetricsLogger().notifyBindApplication(app); if (app.isolatedEntryPoint != null) { // This is an isolated process which should just call an entry point instead of // being bound to an application. thread.runIsolatedEntryPoint(app.isolatedEntryPoint, app.isolatedEntryPointArgs); } else if (app.instr != null) { thread.bindApplication(processName, appInfo, providers, app.instr.mClass, profilerInfo, app.instr.mArguments, app.instr.mWatcher, app.instr.mUiAutomationConnection, testMode, mBinderTransactionTrackingEnabled, enableTrackAllocation, isRestrictedBackupMode || !normalMode, app.persistent, new Configuration(getGlobalConfiguration()), app.compat, getCommonServicesLocked(app.isolated), mCoreSettingsObserver.getCoreSettingsLocked(), buildSerial, isAutofillCompatEnabled); } else { thread.bindApplication(processName, appInfo, providers, null, profilerInfo, null, null, null, testMode, mBinderTransactionTrackingEnabled, enableTrackAllocation, isRestrictedBackupMode || !normalMode, app.persistent, new Configuration(getGlobalConfiguration()), app.compat, getCommonServicesLocked(app.isolated), mCoreSettingsObserver.getCoreSettingsLocked(), buildSerial, isAutofillCompatEnabled); } ...... }
- 该方法执行了一系列的初始化操作,这样我们整个应用进程已经启动起来了。具体还是要看一下bindApplication这个方法。
- 进去上面的方法看一下
- thread.bindApplication()
- ActivityThread.ApplicationThread # bindApplication()
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, boolean autofillCompatibilityEnabled) { if (services != null) { if (false) { // Test code to make sure the app could see the passed-in services. for (Object oname : services.keySet()) { if (services.get(oname) == null) { continue; // AM just passed in a null service. } String name = (String) oname; // See b/79378449 about the following exemption. switch (name) { case "package": case Context.WINDOW_SERVICE: continue; } if (ServiceManager.getService(name) == null) { Log.wtf(TAG, "Service " + name + " should be accessible by this app"); } } } // Setup the service cache in the ServiceManager ServiceManager.initServiceCache(services); } setCoreSettings(coreSettings); AppBindData data = new AppBindData(); data.processName = processName; data.appInfo = appInfo; data.providers = providers; data.instrumentationName = instrumentationName; data.instrumentationArgs = instrumentationArgs; data.instrumentationWatcher = instrumentationWatcher; data.instrumentationUiAutomationConnection = instrumentationUiConnection; data.debugMode = debugMode; data.enableBinderTracking = enableBinderTracking; data.trackAllocation = trackAllocation; data.restrictedBackupMode = isRestrictedBackupMode; data.persistent = persistent; data.config = config; data.compatInfo = compatInfo; data.initProfilerInfo = profilerInfo; data.buildSerial = buildSerial; data.autofillCompatibilityEnabled = autofillCompatibilityEnabled; //主要看这里的代码 sendMessage(H.BIND_APPLICATION, data); }
- 然后看一下哪里处理消息。可以看到调用了handleBindApplication方法。
public void handleMessage(Message msg) { if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what)); switch (msg.what) { case BIND_APPLICATION: Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication"); AppBindData data = (AppBindData)msg.obj; handleBindApplication(data); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); break;
- 接着看一下handleBindApplication方法做了什么
- ActivityThread中的handleBindApplication
private void handleBindApplication(AppBindData data) { //设置进程名字 Process.setArgV0(data.processName); android.ddm.DdmHandleAppName.setAppName(data.processName, UserHandle.myUserId()); VMRuntime.setProcessPackageName(data.appInfo.packageName); if (data.appInfo.targetSdkVersion <= android.os.Build.VERSION_CODES.HONEYCOMB_MR1) { AsyncTask.setDefaultExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } // 创建ContextImpl final ContextImpl appContext = ContextImpl.createAppContext(this, data.info); Application app; final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites(); final StrictMode.ThreadPolicy writesAllowedPolicy = StrictMode.getThreadPolicy(); try { // data.info的对象是LoadedApk, 通过反射创建目标应用Application对象 app = data.info.makeApplication(data.restrictedBackupMode, null); app.setAutofillCompatibilityEnabled(data.autofillCompatibilityEnabled); mInitialApplication = app; mInstrumentation.onCreate(data.instrumentationArgs); mInstrumentation.callApplicationOnCreate(app); } catch (Exception e) { } } finally { } }
- 跟踪到mInstrumentation.callApplicationOnCreate(app);
- 可以看到Application进入onCreate()方法中,这就是从最开始main()方法开始到最后的Application的onCreate()的创建过程。
public void callApplicationOnCreate(Application app) { app.onCreate(); }
更多内容
- GitHub:https://github.com/yangchong211
- 博客:https://juejin.cn/user/1978776659695784
- 开源博客汇总:https://github.com/yangchong211/YCBlogs