前言
Android中有四大组件:Activity、Service、BroadcastReceiver、ContentProvider。我们最常接触也是用户直接感受到的就是Activity了,今天来就说说Android启动的执行过程和工作原理。
Activity是一种 展示型组件,用于展示给用户一个可以交互的页面。Activity是Android中最重要的组件,对用户来说,所有的Activity就是一个App的全部,而其他组件用户是不能直接感知的;
今天我们就来分析总结下app启动流程的场景和知识点
一、启动中设计到关键类详解
1、启动流程设计到主要类
- ActivityManagerServices,简称AMS,服务端对象,负责系统中所有Activity的生命周期;
- ActivityThread,App的真正入口。当开启App之后,会调用main()开始运行,开启消息循环队列,这就是传说中的UI线程或者叫主线程。与ActivityManagerServices配合,一起完成Activity的管理工作;
- ApplicationThread,用来实现ActivityManagerService与ActivityThread之间的交互。在ActivityManagerService需要管理相关Application中的Activity的生命周期时,通过ApplicationThread的代理对象与ActivityThread通讯;
- ApplicationThreadProxy,是ApplicationThread在服务器端的代理,负责和客户端的ApplicationThread通讯。AMS就是通过该代理与ActivityThread进行通信的;
- Instrumentation,每一个应用程序只有一个Instrumentation对象,每个Activity内都有一个对该对象的引用。Instrumentation可以理解为应用进程的管家,ActivityThread要创建或暂停某个Activity时,都需要通过Instrumentation来进行具体的操作;
- ActivityStack,Activity在AMS的栈管理,用来记录已经启动的Activity的先后关系,状态信息等。通过ActivityStack决定是否需要启动新的进程;
- ActivityRecord,ActivityStack的管理对象,每个Activity在AMS对应一个ActivityRecord,来记录Activity的状态以及其他的管理信息。其实就是服务器端的Activity对象的映像;
- TaskRecord,AMS抽象出来的一个“任务”的概念,是记录ActivityRecord的栈,一个“Task”包含若干个ActivityRecord。AMS用TaskRecord确保Activity启动和退出的顺序。如果你清楚Activity的4种launchMode,那么对这个概念应该不陌生;
- 可以说,启动的流程就是通过这几个类之间不断通信的过程;
2、zygote
- zygote意为“受精卵“。Android是基于Linux系统的,而在Linux中,所有的进程都是由init进程直接或者是间接fork出来的,zygote进程也不例外。
- 在Android系统里面,zygote是一个进程的名字。Android是基于Linux System的,当你的手机开机的时候,Linux的内核加载完成之后就会启动一个叫“init“的进程。在Linux System里面,所有的进程都是由init进程fork出来的,我们的zygote进程也不例外。
- 我们都知道,每一个App其实都是:一个单独的dalvik虚拟机
- 一个单独的进程;
- 所以当系统里面的第一个zygote进程运行之后,在这之后再开启App,就相当于开启一个新的进程。而为了实现资源共用和更快的启动速度,Android系统开启新进程的方式,是通过fork第一个zygote进程实现的。所以说,除了第一个zygote进程,其他应用所在的进程都是zygote的子进程;
3、SystemServer
SystemServer也是一个进程,而且是由zygote进程fork出来的
在zygote开启的时候,会调用ZygoteInit.main()进行初始化
- public static void main(String argv[]) {
- ...ignore some code...
- //在加载首个zygote的时候,会传入初始化参数,使得startSystemServer = true
- boolean startSystemServer = false;
- for (int i = 1; i < argv.length; i++) {
- if ("start-system-server".equals(argv[i])) {
- startSystemServer = true;
- } else if (argv[i].startsWith(ABI_LIST_ARG)) {
- abiList = argv[i].substring(ABI_LIST_ARG.length());
- } else if (argv[i].startsWith(SOCKET_NAME_ARG)) {
- socketName = argv[i].substring(SOCKET_NAME_ARG.length());
- } else {
- throw new RuntimeException("Unknown command line argument: " + argv[i]);
- }
- }
- ...ignore some code...
- //开始fork我们的SystemServer进程
- if (startSystemServer) {
- startSystemServer(abiList, socketName);
- }
- ...ignore some code...
- }
startSystemServer()做了些什么
- /**留着这个注释,就是为了说明SystemServer确实是被fork出来的
- * Prepare the arguments and fork for the system server process.
- */
- private static boolean startSystemServer(String abiList, String socketName)
- throws MethodAndArgsCaller, RuntimeException {
- ...ignore some code...
- //留着这段注释,就是为了说明上面ZygoteInit.main(String argv[])里面的argv就是通过这种方式传递进来的
- /* Hardcoded command line to start the system server */
- String args[] = {
- "--setuid=1000",
- "--setgid=1000",
- "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1032,3001,3002,3003,3006,3007",
- "--capabilities=" + capabilities + "," + capabilities,
- "--runtime-init",
- "--nice-name=system_server",
- "com.android.server.SystemServer",
- };
- int pid;
- try {
- parsedArgs = new ZygoteConnection.Arguments(args);
- ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
- ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);
- //fork出来的 -_-|||
- /* Request to fork the system server process */
- pid = Zygote.forkSystemServer(
- parsedArgs.uid, parsedArgs.gid,
- parsedArgs.gids,
- parsedArgs.debugFlags,
- null,
- parsedArgs.permittedCapabilities,
- parsedArgs.effectiveCapabilities);
- } catch (IllegalArgumentException ex) {
- throw new RuntimeException(ex);
- }
- /* For child process */
- if (pid == 0) {
- if (hasSecondZygote(abiList)) {
- waitForSecondaryZygote(socketName);
- }
- handleSystemServerProcess(parsedArgs);
- }
- return true;
- }
4、ActivityManagerService
- ActivityManagerService,简称AMS,服务端对象,负责系统中所有Activity的生命周期。
- ActivityManagerService进行初始化的时机很明确,就是在SystemServer进程开启的时候,就会初始化ActivityManagerService。
- public final class SystemServer {
- //zygote的主入口
- public static void main(String[] args) {
- new SystemServer().run();
- }
- public SystemServer() {
- // Check for factory test mode.
- mFactoryTestMode = FactoryTest.getMode();
- }
- private void run() {
- ...ignore some code...
- //加载本地系统服务库,并进行初始化
- System.loadLibrary("android_servers");
- nativeInit();
- // 创建系统上下文
- createSystemContext();
- //初始化SystemServiceManager对象,下面的系统服务开启都需要调用SystemServiceManager.startService(Class<T>),这个方法通过反射来启动对应的服务
- mSystemServiceManager = new SystemServiceManager(mSystemContext);
- //开启服务
- try {
- startBootstrapServices();
- startCoreServices();
- startOtherServices();
- } catch (Throwable ex) {
- Slog.e("System", "******************************************");
- Slog.e("System", "************ Failure starting system services", ex);
- throw ex;
- }
- ...ignore some code...
- }
初始化系统上下文对象mSystemContext,并设置默认的主题,mSystemContext实际上是一个ContextImpl对象。调用ActivityThread.systemMain()的时候,会调用ActivityThread.attach(true),而在attach()里面,则创建了Application对象,并调用了Application.onCreate()。
- private void createSystemContext() {
- ActivityThread activityThread = ActivityThread.systemMain();
- mSystemContext = activityThread.getSystemContext();
- mSystemContext.setTheme(android.R.style.Theme_DeviceDefault_Light_DarkActionBar);
- }
- //在这里开启了几个核心的服务,因为这些服务之间相互依赖,所以都放在了这个方法里面。
- private void startBootstrapServices() {
- ...ignore some code...
- //初始化ActivityManagerService
- mActivityManagerService = mSystemServiceManager.startService(
- ActivityManagerService.Lifecycle.class).getService();
- mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
- //初始化PowerManagerService,因为其他服务需要依赖这个Service,因此需要尽快的初始化
- mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
- // 现在电源管理已经开启,ActivityManagerService负责电源管理功能
- mActivityManagerService.initPowerManagement();
- // 初始化DisplayManagerService
- mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);
- //初始化PackageManagerService
- mPackageManagerService = PackageManagerService.main(mSystemContext, mInstaller,
- mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
- ...ignore some code...
- }
- }
二、app启动流程图步骤介绍
1、activity中的startActivity方法最终都会通过拿到ATSM的代理IActivityTaskManager调用的startActivity;
2、之后进入system server进程中的ATMS startActivity,ATMS 经过收集Intent信息,然后使用ActivityStackSupervisor.startSpecificActivityLocked,如果进程已经存在,则直接使用realStartActivityLocked,通过App的binder客户端的代理ApplicationThread调用回到bindApplication,走入Activity的启动流程;如果进程不存在则通过socket链接Zygote,请求fork新的进程;
3、App进程创建完成后,进程启动会调用ActivityThread.main方法,初始化主线程Handler,接着走入attach方法,然后通过AMS的代理调用AMS的attachApplication方法,并将App进程的通信代理ApplicationThread传入AMS;
4、AMS获取到ATMS调用ApplicationThread的bindApplication回到App进程的ActivityThread.ApplicationThread.bindApplication方法中,然后使用Handler切换到主线程执行handleBindApplication,这里初始化了App的进程名字、时间,用户的硬件配置,包括App的文件系统,创建了App的Context实例,Instrumentation实例,调用App的onCreate回调方法,同时告诉AMS APP初始化工作完毕;
5、AMS接着会调用ATMS的attachApplication,最后调用ClientLifecycleManager的scheduleTransaction方法,通过App的Binder代理ApplicationThread回到ActivityThread;
6、进入ActivityThread.ApplicationThread.scheduleTransaction方法之后就进入了Activity的onStart、onResume回调
创建进程之前的过程主要是AMS的内部信息收集的判断的过程,下面主要看一下App进程启动的源码流程;
三、启动源码流程解析
1、APP进程起点
一个App的程序入口到底是什么?是ActivityThread.main()
从应用进程被创建开始,ActivityThread.main被执行
- public static void main(String[] args) {
- ActivityThread thread = new ActivityThread();
- thread.attach(false, startSeq);
- 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);
- Looper.loop();
- throw new RuntimeException("Main thread loop unexpectedly exited");
- }
调用ActivityThread的attach方法,然后将activity和AMS通信的Binder代理IApplicationThread实例传入AMS
- @UnsupportedAppUsage
- private void attach(boolean system, long startSeq) {
- sCurrentActivityThread = this;
- mSystemThread = system;
- if (!system) {
- android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
- UserHandle.myUserId());
- RuntimeInit.setApplicationObject(mAppThread.asBinder());
- final IActivityManager mgr = ActivityManager.getService();
- try {
- mgr.attachApplication(mAppThread, startSeq);
- } catch (RemoteException ex) {
- throw ex.rethrowFromSystemServer();
- }
- // Watch for getting close to heap limit.
- BinderInternal.addGcWatcher(new Runnable() {
- @Override public void run() {
- if (!mSomeActivitiesChanged) {
- return;
- }
- Runtime runtime = Runtime.getRuntime();
- long dalvikMax = runtime.maxMemory();
- long dalvikUsed = runtime.totalMemory() - runtime.freeMemory();
- if (dalvikUsed > ((3*dalvikMax)/4)) {
- if (DEBUG_MEMORY_TRIM) Slog.d(TAG, "Dalvik max=" + (dalvikMax/1024)
- + " total=" + (runtime.totalMemory()/1024)
- + " used=" + (dalvikUsed/1024));
- mSomeActivitiesChanged = false;
- try {
- ActivityTaskManager.getService().releaseSomeActivities(mAppThread);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
- }
- });
- }
- }
2、AMS的attachApplication
接着进入AMS进程,ActivityManagerService.attachApplicationLocked
- private final boolean attachApplicationLocked(IApplicationThread thread,
- int pid, int callingUid, long startSeq) {
- 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 (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);
- } else {
- 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);
- }
- } catch (Exception e) {
- }
- // See if the top visible activity is waiting to run in this process...
- if (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;
- }
- }
- return true;
- }
- thread.bindApplication:该方法主要讲App进程的配置信息通过IApplicationThread Binder通信回传到ActivityThread中;
- mAtmInternal.attachApplication:mAtmInternal实际就是ActivityTaskManager的实例,通过LocalServices加载;
- mAtmInternal = LocalServices.getService(ActivityTaskManagerInternal.class);
那么这里相当于走到了ActivityTaskManagerServer的attachApplication中;
3、APP的bindApplication
先看第一条:
注意:ActivityThread中存在于Binder通信的代理--》ApplicationThread extends IApplicationThread.Stub
ActivityThread--》ApplicationThread--》bindApplication
- @Override
- public final void bindApplication(String processName, ApplicationInfo appInfo,
- ProviderInfoList providerList, 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) {
- setCoreSettings(coreSettings);
- AppBindData data = new AppBindData();
- data.processName = processName;
- .....
- sendMessage(H.BIND_APPLICATION, data);
- }
这里的bindApplication主要初始化了AppBindData,然后发送BIND_APPLICATION给APP的主线程BIND_APPLICATION,最后执行了handleBindApplication
handleBindApplication如下:
- ActivityThread--》class H extends Handler
- 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;
- Application的onCreate方法
- private void handleBindApplication(AppBindData data) {
- mBoundApplication = data;
- mConfiguration = new Configuration(data.config);
- mCompatConfiguration = new Configuration(data.config);
- if (data.initProfilerInfo != null) {
- mProfiler.profileFile = data.initProfilerInfo.profileFile;
- mProfiler.profileFd = data.initProfilerInfo.profileFd;
- mProfiler.samplingInterval = data.initProfilerInfo.samplingInterval;
- mProfiler.autoStopProfiler = data.initProfilerInfo.autoStopProfiler;
- mProfiler.streamingOutput = data.initProfilerInfo.streamingOutput;
- if (data.initProfilerInfo.attachAgentDuringBind) {
- agent = data.initProfilerInfo.agent;
- }
- }
- mInstrumentationPackageName = ii.packageName;
- mInstrumentationAppDir = ii.sourceDir;
- mInstrumentationSplitAppDirs = ii.splitSourceDirs;
- mInstrumentationLibDir = getInstrumentationLibrary(data.appInfo, ii);
- mInstrumentedAppDir = data.info.getAppDir();
- mInstrumentedSplitAppDirs = data.info.getSplitAppDirs();
- mInstrumentedLibDir = data.info.getLibDir();
- mInstrumentation.callApplicationOnCreate(app);
- }
该方法主要在App进程中对App的一些硬件资源配置申请的属性、App的文件夹等完成App基本信息的初始化
4、ATMS的attachApplication
接着看第二条:mAtmInternal.attachApplication
- mAtmInternal.attachApplication最终会调用mRootActivityContainer.attachApplication(wpc)
- @HotPath(caller = HotPath.PROCESS_CHANGE)
- @Override
- public boolean attachApplication(WindowProcessController wpc) throws RemoteException {
- synchronized (mGlobalLockWithoutBoost) {
- return mRootActivityContainer.attachApplication(wpc);
- }
- }
- RootActivityContainer.attachApplication
- 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);
- //获取前台栈顶第一个非finishing的Activity
- 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 {
- //真正启动Activity
- 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;
- }
接着调用ActivityStackSupervisor.realStartActivityLocked开始创建Activity
5、ASS的realStartActivityLocked
- ActivityStackSupervisor.realStartActivityLocked
- final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
- boolean andResume, boolean checkConfig) throws RemoteException {
- try {
- r.startFreezingScreenLocked(app, 0);
- //启动tick,收集应用启动慢的信息
- // schedule launch ticks to collect information about slow apps.
- r.startLaunchTickingLocked();
- r.setProcess(app);
- try {
- //创建Activity启动事务
- // Create activity launch transaction.
- final ClientTransaction clientTransaction = ClientTransaction.obtain(app.thread,
- r.appToken);
- clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
- System.identityHashCode(r), r.info,
- // TODO: Have this take the merged configuration instead of separate global
- // and override configs.
- mergedConfiguration.getGlobalConfiguration(),
- mergedConfiguration.getOverrideConfiguration(), r.compat,
- r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
- r.persistentState, results, newIntents, mService.isNextTransitionForward(),
- profilerInfo));
- //设置目标事务的状态为onResume
- // Set desired final state.
- final ActivityLifecycleItem lifecycleItem;
- if (andResume) {
- lifecycleItem = ResumeActivityItem.obtain(mService.isNextTransitionForward());
- } else {
- lifecycleItem = PauseActivityItem.obtain();
- }
- clientTransaction.setLifecycleStateRequest(lifecycleItem);
- //通过transaciton方式开始activity生命周期,onCreate,onStart,onResume
- // Schedule transaction.
- mService.getLifecycleManager().scheduleTransaction(clientTransaction);
- } catch (RemoteException e) {
- }
- } finally {
- endDeferResume();
- }
- return true;
- }
- ClientLifecycleManager
创建ClientLifecycleManager和ClientTransactionHandler来辅助管理Activity的生命周期,注意
clientTransaction.addCallback是LaunchActivityItem
lifecycleItem是ResumeActivityItem
ClientLifecycleManager.scheduleTransaction最终会调用ClientTransaction的schedule方法
- public void schedule() throws RemoteException {
- mClient.scheduleTransaction(this);
- }
那么这个mClient是IApplicationThread的实例,那么此时也就回到了ActivityThread的ApplicationThread中
- IApplicationThread getClient() {
- return mClient;
- }
6、Activity的onCreate方法
APP的scheduleTransaction
- ActivityThread的ApplicationThread中
- @Override
- public void scheduleTransaction(ClientTransaction transaction) throws RemoteException {
- ActivityThread.this.scheduleTransaction(transaction);
- }
因为ActivityThread继承ClientTransactionHandler,所以到了ClientTransactionHandler中
- void scheduleTransaction(ClientTransaction transaction) {
- transaction.preExecute(this);
- sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);
- }
通过Handler发送消息EXECUTE_TRANSACTION到H中
- case EXECUTE_TRANSACTION:
- final ClientTransaction transaction = (ClientTransaction) msg.obj;
- mTransactionExecutor.execute(transaction);
- 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;
接着TransactionExecutor的execute方法
- public void execute(ClientTransaction transaction) {
- final IBinder token = transaction.getActivityToken();
- log("Start resolving transaction for client: " + mTransactionHandler + ", token: " + token);
- executeCallbacks(transaction);
- executeLifecycleState(transaction);
- mPendingActions.clear();
- log("End resolving transaction");
- }
- LaunchActivityItem.execute方法
- @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);
- client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
- Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
- }
- client其实是在ActivityThread的实例,那么就回到了ActivityThread的handleLaunchActivity
- @Override
- public Activity handleLaunchActivity(ActivityClientRecord r,
- PendingTransactionActions pendingActions, Intent customIntent) {
- final Activity a = performLaunchActivity(r, customIntent);
- }
7、接着调用performLaunchActivity
- private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
- ActivityInfo aInfo = r.activityInfo;
- if (r.packageInfo == null) {
- r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
- Context.CONTEXT_INCLUDE_CODE);
- }
- ComponentName component = r.intent.getComponent();
- if (component == null) {
- component = r.intent.resolveActivity(
- mInitialApplication.getPackageManager());
- r.intent.setComponent(component);
- }
- if (r.activityInfo.targetActivity != null) {
- component = new ComponentName(r.activityInfo.packageName,
- r.activityInfo.targetActivity);
- }
- //创建Activity的context实例
- ContextImpl appContext = createBaseContextForActivity(r);
- Activity activity = null;
- try {
- java.lang.ClassLoader cl = appContext.getClassLoader();
- //创建Activity的实例
- activity = mInstrumentation.newActivity(
- cl, component.getClassName(), r.intent);
- StrictMode.incrementExpectedActivityCount(activity.getClass());
- r.intent.setExtrasClassLoader(cl);
- r.intent.prepareToEnterProcess();
- if (r.state != null) {
- r.state.setClassLoader(cl);
- }
- } catch (Exception e) {
- }
- try {
- Application app = r.packageInfo.makeApplication(false, mInstrumentation);
- if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
- if (localLOGV) Slog.v(
- TAG, r + ": app=" + app
- + ", appName=" + app.getPackageName()
- + ", pkg=" + r.packageInfo.getPackageName()
- + ", comp=" + r.intent.getComponent().toShortString()
- + ", dir=" + r.packageInfo.getAppDir());
- if (activity != null) {
- //获取Resources资源
- appContext.getResources().addLoaders(
- app.getResources().getLoaders().toArray(new ResourcesLoader[0]));
- appContext.setOuterContext(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()) {
- //回调Activity的onCreat
- mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
- } else {
- mInstrumentation.callActivityOnCreate(activity, r.state);
- }
- }
- } catch (SuperNotCalledException e) {
- throw e;
- } catch (Exception e) {
- }
- return activity;
- }
在performLaunchActivity中,主要是加载App的资源包,然后创建了Activity的context实例,并创建了Activity的实例,接着调用activity.attach方法,attach执行完之后调用了onCreate方法。
8、APP的activity.attach
- activity.attach
- final void attach(Context context, ActivityThread aThread,
- Instrumentation instr, IBinder token, int ident,
- Application application, Intent intent, ActivityInfo info,
- CharSequence title, Activity parent, String id,
- NonConfigurationInstances lastNonConfigurationInstances,
- Configuration config, String referrer, IVoiceInteractor voiceInteractor,
- Window window, ActivityConfigCallback activityConfigCallback, IBinder assistToken) {
- attachBaseContext(context);
- mFragments.attachHost(null /*parent*/);
- //创建了PhoneWindow实例
- mWindow = new PhoneWindow(this, window, activityConfigCallback);
- //设置了WindowControllerCallback监听
- mWindow.setWindowControllerCallback(this);
- //设置了WindowCallback监听
- mWindow.setCallback(this);
- mWindow.setOnWindowDismissedCallback(this);
- mWindow.getLayoutInflater().setPrivateFactory(this);
- if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
- mWindow.setSoftInputMode(info.softInputMode);
- }
- if (info.uiOptions != 0) {
- mWindow.setUiOptions(info.uiOptions);
- }
- //线程对象赋值,即ActivityThread main方法所在的线程
- mUiThread = Thread.currentThread();
- //初始化Activity的成员变量,包括windowmanager
- mMainThread = aThread;
- mInstrumentation = instr;
- mToken = token;
- mAssistToken = assistToken;
- mIdent = ident;
- mApplication = application;
- mIntent = intent;
- mReferrer = referrer;
- mComponent = intent.getComponent();
- mActivityInfo = info;
- mTitle = title;
- mParent = parent;
- mEmbeddedID = id;
- mLastNonConfigurationInstances = lastNonConfigurationInstances;
- if (voiceInteractor != null) {
- if (lastNonConfigurationInstances != null) {
- mVoiceInteractor = lastNonConfigurationInstances.voiceInteractor;
- } else {
- mVoiceInteractor = new VoiceInteractor(voiceInteractor, this, this,
- Looper.myLooper());
- }
- }
- mWindow.setWindowManager(
- (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
- mToken, mComponent.flattenToString(),
- (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
- if (mParent != null) {
- mWindow.setContainer(mParent.getWindow());
- }
- mWindowManager = mWindow.getWindowManager();
- mCurrentConfig = config;
- mWindow.setColorMode(info.colorMode);
- setAutofillOptions(application.getAutofillOptions());
- setContentCaptureOptions(application.getContentCaptureOptions());
- }
activity.attach中主要
1.创建了PhoneWindow实例
2.设置了Window接口的监听
3.初始化了成员变量,包括线程和WindowManager
三、点击桌面图标启动
当我们点击手机桌面上的图标的时候,App就由Launcher开始启动了。但是,你有没有思考过Launcher到底是一个什么东西?
Launcher本质上也是一个应用程序,和我们的App一样,也是继承自Activity
- packages/apps/Launcher2/src/com/android/launcher2/Launcher.java
- public final class Launcher extends Activity
- implements View.OnClickListener, OnLongClickListener, LauncherModel.Callbacks,
- View.OnTouchListener {
- }
auncher实现了点击、长按等回调接口,来接收用户的输入。既然是普通的App,那么我们的开发经验在这里就仍然适用,比如,我们点击图标的时候,是怎么开启的应用呢?如果让你,你怎么做这个功能呢?捕捉图标点击事件,然后startActivity()发送对应的Intent请求呗!是的,Launcher也是这么做的,就是这么easy!
那么到底是处理的哪个对象的点击事件呢?既然Launcher是App,并且有界面,那么肯定有布局文件呀,是的,我找到了布局文件launcher.xml
- <FrameLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:launcher="http://schemas.android.com/apk/res/com.android.launcher"
- android:id="@+id/launcher">
- <com.android.launcher2.DragLayer
- android:id="@+id/drag_layer"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:fitsSystemWindows="true">
- <!-- Keep these behind the workspace so that they are not visible when
- we go into AllApps -->
- <include
- android:id="@+id/dock_divider"
- layout="@layout/workspace_divider"
- android:layout_marginBottom="@dimen/button_bar_height"
- android:layout_gravity="bottom" />
- <include
- android:id="@+id/paged_view_indicator"
- layout="@layout/scroll_indicator"
- android:layout_gravity="bottom"
- android:layout_marginBottom="@dimen/button_bar_height" />
- <!-- The workspace contains 5 screens of cells -->
- <com.android.launcher2.Workspace
- android:id="@+id/workspace"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:paddingStart="@dimen/workspace_left_padding"
- android:paddingEnd="@dimen/workspace_right_padding"
- android:paddingTop="@dimen/workspace_top_padding"
- android:paddingBottom="@dimen/workspace_bottom_padding"
- launcher:defaultScreen="2"
- launcher:cellCountX="@integer/cell_count_x"
- launcher:cellCountY="@integer/cell_count_y"
- launcher:pageSpacing="@dimen/workspace_page_spacing"
- launcher:scrollIndicatorPaddingLeft="@dimen/workspace_divider_padding_left"
- launcher:scrollIndicatorPaddingRight="@dimen/workspace_divider_padding_right">
- <include android:id="@+id/cell1" layout="@layout/workspace_screen" />
- <include android:id="@+id/cell2" layout="@layout/workspace_screen" />
- <include android:id="@+id/cell3" layout="@layout/workspace_screen" />
- <include android:id="@+id/cell4" layout="@layout/workspace_screen" />
- <include android:id="@+id/cell5" layout="@layout/workspace_screen" />
- </com.android.launcher2.Workspace>
- ...ignore some code...
- </com.android.launcher2.DragLayer>
- </FrameLayout>
程序列表界面,点击图标的时候会发生什么呢?实际上,程序列表界面使用的是AppsCustomizePagedView对象,所以我在这个类里面找到了onClick(View v)。
- com.android.launcher2.AppsCustomizePagedView.java
- /**
- * The Apps/Customize page that displays all the applications, widgets, and shortcuts.
- */
- public class AppsCustomizePagedView extends PagedViewWithDraggableItems implements
- View.OnClickListener, View.OnKeyListener, DragSource,
- PagedViewIcon.PressedCallback, PagedViewWidget.ShortPressListener,
- LauncherTransitionable {
- @Override
- public void onClick(View v) {
- ...ignore some code...
- if (v instanceof PagedViewIcon) {
- mLauncher.updateWallpaperVisibility(true);
- mLauncher.startActivitySafely(v, appInfo.intent, appInfo);
- } else if (v instanceof PagedViewWidget) {
- ...ignore some code..
- }
- }
- }
可以看到,调用的是
- mLauncher.startActivitySafely(v, appInfo.intent, appInfo);
和上面一样!这叫什么?这叫殊途同归!
所以咱们现在又明白了一件事情:不管从哪里点击图标,调用的都是Launcher.startActivitySafely()。
下面我们就可以一步步的来看一下Launcher.startActivitySafely()到底做了什么事情。
- boolean startActivitySafely(View v, Intent intent, Object tag) {
- boolean success = false;
- try {
- success = startActivity(v, intent, tag);
- } catch (ActivityNotFoundException e) {
- Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
- Log.e(TAG, "Unable to launch. tag=" + tag + " intent=" + intent, e);
- }
- return success;
- }
- 调用了startActivity(v, intent, tag)
- boolean startActivity(View v, Intent intent, Object tag) {
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- try {
- boolean useLaunchAnimation = (v != null) &&
- !intent.hasExtra(INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION);
- if (useLaunchAnimation) {
- if (user == null || user.equals(android.os.Process.myUserHandle())) {
- startActivity(intent, opts.toBundle());
- } else {
- launcherApps.startMainActivity(intent.getComponent(), user,
- intent.getSourceBounds(),
- opts.toBundle());
- }
- } else {
- if (user == null || user.equals(android.os.Process.myUserHandle())) {
- startActivity(intent);
- } else {
- launcherApps.startMainActivity(intent.getComponent(), user,
- intent.getSourceBounds(), null);
- }
- }
- return true;
- } catch (SecurityException e) {
- ...
- }
- return false;
- }
这里会调用Activity.startActivity(intent, opts.toBundle()),这个方法熟悉吗?这就是我们经常用到的Activity.startActivity(Intent)的重载函数。而且由于设置了
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
所以这个Activity会添加到一个新的Task栈中,而且,startActivity()调用的其实是startActivityForResult()这个方法。
- @Override
- public void startActivity(Intent intent, @Nullable Bundle options) {
- if (options != null) {
- startActivityForResult(intent, -1, options);
- } else {
- // Note we want to go through this call for compatibility with
- // applications that may have overridden the method.
- startActivityForResult(intent, -1);
- }
- }
所以我们现在明确了,Launcher中开启一个App,其实和我们在Activity中直接startActivity()基本一样,都是调用了Activity.startActivityForResult()。
下次我们详细介绍下startActivity之后的流程
总结:
- 点击桌面App图标,Launcher进程采用Binder IPC向system_server进程发起startActivity请求;
- system_server进程接收到请求后,向zygote进程发送创建进程的请求;
- Zygote进程fork出新的子进程,即App进程;
- App进程,通过Binder IPC向sytem_server进程发起attachApplication请求;
- system_server进程在收到请求后,进行一系列准备工作后,再通过binder IPC向App进程发送scheduleLaunchActivity请求;
- App进程的binder线程(ApplicationThread)在收到请求后,通过handler向主线程发送LAUNCH_ACTIVITY消息;
- 主线程在收到Message后,通过发射机制创建目标Activity,并回调Activity.onCreate()等方法
原文链接:https://mp.weixin.qq.com/s/V14dtw1Nkd0sK7wKT9ktiA