Android 7.0 ActivityManagerService(3) 启动Activity的过程:二
来源:互联网 发布:win10设置java环境变量 编辑:程序博客网 时间:2024/06/03 22:42
这一篇博客,我们将继续学习Activity的启动流程。
在启动Activity的过程:一中,我们的流程最终分析到AMS通过zygote启动Activity对应的进程,现在我们看看后续的过程如何进行。
关于zygote启动进程的流程,可以参考Android6.0 SystemServer进程。这篇文章中,分析了zygote如何启动SystemServer进程和普通进程。虽然分析的是Android M的代码,但与android N的思路基本一致。
一、ActivityThread的main函数
通过zygote启动进程时,传入的className为android.app.ActivityThread。
因此,当zygote通过反射调用进程的main函数时,ActivityThread的main函数将被启动:
public static void main(String[] args) { .................. //开始信息采样 SamplingProfilerIntegration.start(); // CloseGuard defaults to true and can be quite spammy. We // disable it here, but selectively enable it later (via // StrictMode) on debug builds, but using DropBox, not logs. //和调试有关 CloseGuard.setEnabled(false); //得到当前进程的UserEnvironment Environment.initForCurrentUser(); ............... // Make sure TrustedCertificateStore looks in the right place for CA certificates // 确保进程能够得到CA证书的路径 final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId()); TrustedCertificateStore.setDefaultUserDirectory(configDir); Process.setArgV0("<pre-initialized>"); //准备主线程的Looper Looper.prepareMainLooper(); //创建当前进程的ActivityThread ActivityThread thread = new ActivityThread(); //调用attach函数 thread.attach(false); if (sMainThreadHandler == null) { //保存进程对应的主线程Handler sMainThreadHandler = thread.getHandler(); } ......... //进入主线程的消息循环 Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited");}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
从上述代码可以看出,ActivityThread的main函数最主要工作是:
1、创建出一个Looper,并将主线程加入到消息循环中。
2、创建出ActivityThread,并调用其attach函数。
在介绍AMS的启动过程时,我们就提到了ActivityThread。
当时从代码中,我们知道SystemServer进程,为了融入Android体系,调用createSystemContext函数。
在createSystemContext函数中,SystemServer进程创建了自己的ActivityThread,并调用了attach函数。
通过比对代码容易看出,SystemServer进程作为系统进程,attach参数为true,而普通进程传入的参数为false。
现在,我们重新看看ActivityThread的attach函数,这次侧重于普通进程的部分:
private void attach(boolean system) { sCurrentActivityThread = this; mSystemThread = system; if (!system) { ViewRootImpl.addFirstDrawHandler(new Runnable() { @Override public void run() { //JIT-Just in time //JIT技术主要是对多次运行的代码进行编译,当再次调用时使用编译之后的机器码,而不是每次都解释,以节约时间 //JIT原理: //每启动一个应用程序,都会相应地启动一个dalvik虚拟机,启动时会建立JIT线程,一直在后台运行。 //当某段代码被调用时,虚拟机会判断它是否需要编译成机器码,如果需要,就做一个标记。 //JIT线程在后台检测该标记,如果发现标记被设定,就把对应代码编译成机器码,并将其机器码地址及相关信息保存起来 //当进程下次执行到此段代码时,就会直接跳到机器码执行,而不再解释执行,从而提高运行速度 //这里开启JIT,应该是为了提高android绘制的速度 ensureJitEnabled(); } }); //设置在DDMS中看到的进程名为"<pre-initialized>" android.ddm.DdmHandleAppName.setAppName("<pre-initialized>", UserHandle.myUserId()); //设置RuntimeInit的mApplicationObject参数 RuntimeInit.setApplicationObject(mAppThread.asBinder()); final IActivityManager mgr = ActivityManagerNative.getDefault(); try { //与AMS通信,调用其attachApplication接口 mgr.attachApplication(mAppThread); } catch (RemoteException ex) { throw ex.rethrowFromSystemServer(); } // Watch for getting close to heap limit. // 监控GC操作; 当进程内的一些Activity发生变化,同时内存占用量较大时 // 通知AMS释放一些Activity BinderInternal.addGcWatcher(new Runnable() { 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)) { ........... mSomeActivitiesChanged = false; try { //通知AMS释放一些Activity,以缓解内存紧张 mgr.releaseSomeActivities(mAppThread); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } } }); } else { ............. } ........}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
在分析Activity启动过程的第一部分时,我们提到过AMS创建一个应用进程后,会设置一个超时时间。
如果超过这个时间,应用进程还没有和AMS交互,AMS就认为该进程创建失败。
因此,应用进程启动后,需要尽快和AMS交互。
上述代码中,attachApplication就是应用进程与AMS交互的接口。
二、AMS的attachApplication函数
我们进入AMS看看attachApplication相关的流程。
public final void attachApplication(IApplicationThread thread) { synchronized (this) { int callingPid = Binder.getCallingPid(); final long origId = Binder.clearCallingIdentity(); //进一步调用attachApplicationLocked函数 attachApplicationLocked(thread, callingPid); Binder.restoreCallingIdentity(origId); }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
attachApplicationLocked函数比较长,分段来看一下。
1 Part-I
private final boolean attachApplicationLocked(IApplicationThread thread, int pid) { ProcessRecord app; //根据pid查找对应的ProcessRecord对象 if (pid != MY_PID && pid >= 0) { synchronized (mPidsSelfLocked) { app = mPidsSelfLocked.get(pid); } } else { app = null; } //如果进程由AMS启动,则它在AMS中一定有对应的ProcessRecord //此处app为null,则表示AMS没有该进程的记录,故需要kill掉此异常进程 if (app == null) { ................ if (pid > 0 && pid != MY_PID) { //pid大于0且不是系统进程,则直接kill掉 //将调用android_util_Process.cpp中的android_os_Process_sendSignalQuiet函数 //最终通过kill函数杀死进程,kill函数要求pid > 0 Process.killProcessQuiet(pid); } else { try { //pid < 0时,fork进程失败,因此仅上层完成清理工作即可 //调用ApplicationThread的scheduleExit函数 //应用进程将进行一些扫尾工作,例如结束消息循环,然后退出运行 thread.scheduleExit(); } catch (Exception e) { // Ignore exceptions. } } return false; } // If this application record is still attached to a previous // process, clean it up now. // 判断pid对应processRecord的IApplicationThread是否为null // AMS创建ProcessRecord后,在attach之前,正常情况下IApplicationThread应该为null // 特殊情况下:如果旧应用进程被杀死,底层对应的pid被释放,在通知到达AMS之前(AMS在下面的代码里注册了“讣告”接收对象), // 用户又启动了一个新的进程,新进程刚好分配到旧进程的pid时 // 此处得到的processRecord可能就是旧进程的,于是app.thread可能不为null,因此需要作判断和处理 if (app.thread != null) { handleAppDiedLocked(app, true, true); } ................... final String processName = app.processName; try { //创建一个“讣告”接收对象,注册到应用进程的ApplicationThread中 //当应用进程退出时,该对象的binderDied将被调用,这样AMS就能做相应的处理 //binderDied函数将在另一个线程中被调用,其内部也会调用handleAppDiedLocked函数 AppDeathRecipient adr = new AppDeathRecipient( app, pid, thread); thread.asBinder().linkToDeath(adr, 0); app.deathRecipient = adr; } catch (RemoteException e) { app.resetPackageList(mProcessStats); startProcessLocked(app, "link fail", processName); return false; } 设置app的一些变量,例如调度优先级和oom_adj相关的成员 ................. //启动成功,从消息队列中移除PROC_START_TIMEOUT_MSG mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app); .................
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
至此,attachApplicationLocked的第一部分介绍完毕。
这部分代码的核心功能比较简单,其实就是:
1、判断进程的有效性,同时注册观察者监听进程的死亡信号。
2、设置pid对应的ProcessRecord对象的一些成员变量,例如和应用进程交互的IApplicationThread对象、进程调度的优先级等。
3、进程注册成功,AMS从消息队列中移除PROC_START_TIMEOUT_MSG。
2 Part-II
现在,我们看看attachApplicationLocked第二部分的代码:
..............//AMS正常启动后,mProcessesReady就已经变为true了boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);//generateApplicationProvidersLocked将通过PKMS查询定义在进程中的ContentProvider,并将其保存在AMS的数据结构中List<ProviderInfo> providers = normalMode ? generateApplicationProvidersLocked(app) : null;//这里应该是处理:加载ContentProvider时,启动进程的场景//checkAppInLaunchingProvidersLocked主要将当前启动进程的ProcessRecord,和AMS中mLaunchingProviders的ProcessRecord进行比较//当判断出该进程是由于启动ContentProvider而被加载的,那么就发送一个延迟消息(10s)//通过这里可以看出,当由于加载ContentProvider启动进程时,在进程启动后,ContentProvider在10s内要完成发布if (providers != null && checkAppInLaunchingProvidersLocked(app)) { Message msg = mHandler.obtainMessage(CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG); msg.obj = app; mHandler.sendMessageDelayed(msg, CONTENT_PROVIDER_PUBLISH_TIMEOUT);}...........try { ........... //回调进程ApplicationThread的bindApplication接口 thread.bindApplication(..........); //更新进程调度策略 updateLruProcessLocked(app, false, null); ..............} catch () { ............ app.resetPackageList(mProcessStats); app.unlinkDeathRecipient(); //这里的策略比较激进,当bindApplicaiton失败后,将直接重新启动这个进程 startProcessLocked(app, "bind fail", processName); return false;}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
从代码来看,第二阶段最核心工作就是:
调用进程ApplicationThread的bindApplication函数,接下来我们分析一下该函数。
2.1 ApplicationThread的bindApplication函数
从之前的代码,我们知道应用进程由zygote fork得到,然后调用ActivityThread的main函数,进入到Java世界。
但是截至目前,该进程并没有融入到Android的体系中,因此仅能被称为一个Java进程,甚至连进程名也只是“敷衍”地定义为“pre-initialized”。
我们之前分析AMS启动过程时,介绍了SystemServer的createSystemContext函数。
在该函数中,SystemServer在自己的进程中,创建出Android运行环境,才摇身一变成为了Android进程。
同样,此处的bindApplication函数,就是在新进程中创建并初始化对应的Android运行环境。
现在,我们看看bindApplication函数的主要流程:
//参数较多,无需深究,重要的从代码流程中就能知道含义public final void bindApplication(.......) { //按照string-IBinder的方式,保存AMS传递过来的系统service的Binder接口 //这样进程与系统服务通信时,就不需要先通过SystemServer查询了 if (services != null) { // Setup the service cache in the ServiceManager ServiceManager.initServiceCache(services); } //内部发送H.SET_CORE_SETTINGS消息 //由handleSetCoreSettings进行处理,主要用于保存新的信息 setCoreSettings(coreSettings); //用AppBindData对象保存参数对应的信息 AppBindData data = new AppBindData(); data.processName = processName; data.appInfo = appInfo; data.providers = providers; .................. //发送消息 sendMessage(H.BIND_APPLICATION, data);}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
由以上代码可知,ApplicationThread的接口被AMS调用后,会将参数保存到AppBindData对象中,然后发送消息让ActivityThread的主线程处理。
由此可以看出,对应用进程而言,ApplicationThread只是与AMS通信的接口,实际的工作一般还是会交给ActivityThread来完成。
ActivityThread中处理该消息的实际函数为handleBindApplication,我们看看这个函数的内容。
2.2 handleBindApplication函数
private void handleBindApplication(AppBindData data) { // Register the UI Thread as a sensitive thread to the runtime. VMRuntime.registerSensitiveThread(); ................. //初始化性能统计对象 mProfiler = new Profiler(); if (data.initProfilerInfo != null) { mProfiler.profileFile = data.initProfilerInfo.profileFile; mProfiler.profileFd = data.initProfilerInfo.profileFd; mProfiler.samplingInterval = data.initProfilerInfo.samplingInterval; mProfiler.autoStopProfiler = data.initProfilerInfo.autoStopProfiler; } // send up app name; do this *before* waiting for debugger //重新设置进程名,并修改DDMS中的名称 Process.setArgV0(data.processName); android.ddm.DdmHandleAppName.setAppName(data.processName, UserHandle.myUserId()); if (data.persistent) { // Persistent processes on low-memory devices do not get to // use hardware accelerated drawing, since this can add too much // overhead to the process. //在低内存设备上,禁止常驻进程使用硬件加速 if (!ActivityManager.isHighEndGfx()) { ThreadedRenderer.disable(false); } } //启动性能统计 if (mProfiler.profileFd != null) { mProfiler.startProfiling(); } // If the app is Honeycomb MR1 or earlier, switch its AsyncTask // implementation to use the pool executor. Normally, we use the // serialized executor as the default. This has to happen in the // main thread so the main looper is set right. //Java并发使用的ThreadExecutor,没有太深入的去了解 //比较浅显的来讲,serialized executor应该是保证一个任务执行完毕后,才去执行下一个任务 //pool executor根据配置的corePoolSize决定初始时,可以并行的数量; //当同时提交的任务数量,超过corePoolSize时,任务就会加入到队列中 if (data.appInfo.targetSdkVersion <= android.os.Build.VERSION_CODES.HONEYCOMB_MR1) { AsyncTask.setDefaultExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } /* * Before spawning a new process, reset the time zone to be the system time zone. * This needs to be done because the system time zone could have changed after the * the spawning of this process. Without doing this this process would have the incorrect * system time zone. */ TimeZone.setDefault(null); /* * Set the LocaleList. This may change once we create the App Context. */ LocaleList.setDefault(data.config.getLocales()); //更新资源和兼容性相关的配置 synchronized (mResourcesManager) { /* * Update the system configuration since its preloaded and might not * reflect configuration changes. The configuration object passed * in AppBindData can be safely assumed to be up to date */ mResourcesManager.applyConfigurationToResourcesLocked(data.config, data.compatInfo); mCurDefaultDisplayDpi = data.config.densityDpi; // This calls mResourcesManager so keep it within the synchronized block. applyCompatConfiguration(mCurDefaultDisplayDpi); } //根据传递过来的ApplicationInfo创建一个对应的LoadedApk对象 data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo); /** * Switch this process to density compatibility mode if needed. */ //如果没有设置屏幕密度,则为Bitmap设置默认的屏幕密度 if ((data.appInfo.flags&ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) == 0) { mDensityCompatMode = true; Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT); } updateDefaultDensity(); final boolean is24Hr = "24".equals(mCoreSettings.getString(Settings.System.TIME_12_24)); DateFormat.set24HourTimePref(is24Hr); .................... /** * For apps targetting Honeycomb or later, we don't allow network usage * on the main event loop / UI thread. This is what ultimately throws * {@link NetworkOnMainThreadException}. */ //禁止在主线程使用网络操作 if (data.appInfo.targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB) { StrictMode.enableDeathOnNetwork(); } /** * For apps targetting N or later, we don't allow file:// Uri exposure. * This is what ultimately throws {@link FileUriExposedException}. */ //禁止主线程操作文件 if (data.appInfo.targetSdkVersion >= Build.VERSION_CODES.N) { StrictMode.enableDeathOnFileUriExposure(); } ............... /** * Initialize the default http proxy in this process for the reasons we set the time zone. */ final IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE); if (b != null) { final IConnectivityManager service = IConnectivityManager.Stub.asInterface(b); try { //设置默认的Http proxy final ProxyInfo proxyInfo = service.getProxyForNetwork(null); Proxy.setHttpProxySystemProperty(proxyInfo); } catch (RemoteException e) { ............. } } ......................... //创建出进程读应的Android运行环境 final ContextImpl appContext = ContextImpl.createAppContext(this, data.info); ......................... // Install the Network Security Config Provider. This must happen before the application // code is loaded to prevent issues with instances of TLS objects being created before // the provider is installed. ................. NetworkSecurityConfigProvider.install(appContext); ................. if ((data.appInfo.flags&ApplicationInfo.FLAG_LARGE_HEAP) != 0) { //如果package中声明了FLAG_LARGE_HEAP,则可跳出虚拟机对内存限制 dalvik.system.VMRuntime.getRuntime().clearGrowthLimit(); } else { // Small heap, clamp to the current growth limit and let the heap release // pages after the growth limit to the non growth limit capacity. b/18387825 dalvik.system.VMRuntime.getRuntime().clampGrowthLimit(); } // Allow disk access during application and provider setup. This could // block processing ordered broadcasts, but later processing would // probably end up doing the same disk access. final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites(); try { // If the app is being launched for full backup or restore, bring it up in // a restricted environment with the base application class. // 利用LoadedApk的makeApplication函数,通过反射创建出Application Application app = data.info.makeApplication(data.restrictedBackupMode, null); mInitialApplication = app; // don't bring up providers in restricted mode; they may depend on the // app's custom Application class if (!data.restrictedBackupMode) { if (!ArrayUtils.isEmpty(data.providers)) { //加载进程对应Package中携带的ContentProvider installContentProviders(app, data.providers); // For process that contains content providers, we want to // ensure that the JIT is enabled "at some point". // 通过JIT技术加速 mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000); } } ................... try { //调用Application的onCreate函数,完成一些初始化工作 mInstrumentation.callApplicationOnCreate(app); } catch (Exception e) { ................. } } finally { StrictMode.setThreadPolicy(savedPolicy); }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
如上文所述,handleBindApplication的目的是让一个Java进程融入到Android体系中。
因此,该函数中的代码主要进行以下工作:
1、按照Android的要求,完成对进程基本参数的设置置,包括设置进程名、时区、资源及兼容性配置;
同时也添加了一些限制,例如主线程不能访问网络等。
2、创建进程对应的ContextImpl、LoadedApk、Application等对象,同时加载Application中的ContentProvider,并初始化Application。
当完成上述工作后,新建的进程终于加入到了Android体系。
3 Part-III
接下来,我们看看AMS中attachApplicationLocked函数的最后一部分内容:
.....................// Remove this record from the list of starting applications.// 进程已经启动,从一些列表中移除对应的记录mPersistentStartingProcesses.remove(app);...................mProcessesOnHold.remove(app);boolean badApp = false;boolean didSomething = false;// See if the top visible activity is waiting to run in this process...if (normalMode) { try { //启动Activity if (mStackSupervisor.attachApplicationLocked(app)) { didSomething = true; } } 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 { //启动因目标进程还未启动,而处于等待状态的service didSomething |= mServices.attachApplicationLocked(app, processName); } catch (Exception e) { Slog.wtf(TAG, "Exception thrown starting services in " + app, e); badApp = true; }}// Check if a next-broadcast receiver is in this process...if (!badApp && isPendingBroadcastProcessLocked(pid)) { try { //发送因目标进程还未启动,而处于等待状态的Broadcast didSomething |= sendPendingBroadcastsLocked(app); } catch (Exception e) { // If the app died trying to launch the receiver we declare it 'bad' Slog.wtf(TAG, "Exception thrown dispatching broadcasts in " + app, e); badApp = true; }}// Check whether the next backup agent is in this process...if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.uid) { ............... try { //启动backup Agent thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, compatibilityInfoForPackageLocked(mBackupTarget.appInfo), mBackupTarget.backupMode); } catch (Exception e) { Slog.wtf(TAG, "Exception thrown creating backup agent in " + app, e); badApp = true; } }}if (badApp) { //如果以上组件启动出错,则需要杀死进程并移除记录 app.kill("error during init", true); handleAppDiedLocked(app, false, true); return false;}//如果以上没有启动任何组件,那么didSomething为falseif (!didSomething) { //调整进程的oom_adj值, oom_adj相当于一种优先级 //如果应用进程没有运行任何组件,那么当内存出现不足时,该进程是最先被系统“杀死” //反之,进程中运行的组件越多,则越不容易被“杀死” updateOomAdjLocked();}return true;......
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
这段代码比较好理解,主要功能就是启动新建进程中运行的Activity、Service等组件。
这里我们主要关注一下Activity的启动过程,即下面这段代码:
.............if (normalMode) { try { if (mStackSupervisor.attachApplicationLocked(app)) { didSomething = true; } } catch (Exception e) { .......... badApp = true; }}...............
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
我们跟进定义于ActivityStackSupervisor中的attachApplicationLocked函数:
boolean attachApplicationLocked(ProcessRecord app) throws RemoteException { final String processName = app.processName; boolean didSomething = false; //ActivityStackSupervisor维护着终端中所有Activity和Task之间的关系 //此处通过轮寻,找出前台栈顶端的待启动Activity for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks; for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { final ActivityStack stack = stacks.get(stackNdx); if (!isFocusedStack(stack)) { continue; } ActivityRecord hr = stack.topRunningActivityLocked(); if (hr != null) { //前台待启动的Activity与当前新建的进程一致时,启动这个Activity if (hr.app == null && app.uid == hr.info.applicationInfo.uid && processName.equals(hr.processName)) { try { //realStartActivityLocked进行实际的启动工作 if (realStartActivityLocked(hr, app, true, true)) { didSomething = true; } } catch (RemoteException e) { ............. } } } } } ................. return didSomething;}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
通过这段代码,我们终于明白了启动Activity的过程:一中的流程,为什么要花大力气先将待启动的Activity的Task移动到前台,并且要将该Activity移动到栈顶。
毕竟,在创建新进程时,无法将待启动Activity的信息一并传递给新进程(进程刚创建时,并没有加入到Android体系),因此新进程被创建后,无法知道需要创建的Activity。
于是,上面的代码就规定:如果前台栈顶Activity对应的进程信息,与新启动的进程相互吻合时,该进程就需要启动该Activity。
三、realStartActivityLocked函数
接下来,我们看看ActivityStatckSupervisor中的realStartActivityLocked函数:
final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app, boolean andResume, boolean checkConfig) throws RemoteException { if (!allPausedActivitiesComplete()) { // While there are activities pausing we skipping starting any new activities until // pauses are complete. NOTE: that we also do this for activities that are starting in // the paused state because they will first be resumed then paused on the client side. ........... return false; } if (andResume) { //为显示做准备 r.startFreezingScreenLocked(app, 0); mWindowManager.setAppVisibility(r.appToken, true); .......... } // Have the window manager re-evaluate the orientation of // the screen based on the new activity order. Note that // as a result of this, it can call back into the activity // manager with a new orientation. We don't care about that, // because the activity is not currently running so we are // just restarting it anyway. if (checkConfig) { Configuration config = mWindowManager.updateOrientationFromAppTokens( mService.mConfiguration, r.mayFreezeScreenLocked(app) ? r.appToken : null); //AMS更新绘制相关的配置信息 mService.updateConfigurationLocked(config, r, false); } r.app = app; app.waitingToKill = null; r.launchCount++; ............... //将待启动Activity对应ActivityRecord加入到进程中保存 int idx = app.activities.indexOf(r); if (idx < 0) { app.activities.add(r); } //更新优先级 mService.updateLruProcessLocked(app, true, null); mService.updateOomAdjLocked(); ............... final ActivityStack stack = task.stack; try { ............... List<ResultInfo> results = null; List<ReferrerIntent> newIntents = null; if (andResume) { results = r.results; newIntents = r.newIntents; } ............... if (andResume) { app.hasShownUi = true; app.pendingUiClean = true; } app.forceProcessStateUpTo(mService.mTopProcessState); //通知应用进程启动Activity app.thread.scheduleLaunchActivity(............); if ((app.info.privateFlags&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) { //处理heavy-weight进程的情况 ......... } } catch (RemoteException e) { if (r.launchFailed) { // This is the second time we failed -- finish activity // and give up. ................ //从代码来看,第二次启动失败,才会将ActivityRecord中的launchFailed置为true mService.appDiedLocked(app); stack.requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null, "2nd-crash", false); return false; } // This is the first time we failed -- restart process and // retry. app.activities.remove(r); throw e; } r.launchFailed = false; if (andResume) { // As part of the process of launching, ActivityThread also performs // a resume. // Activity进入resumeState后,更新相应的状态 stack.minimalResumeActivityLocked(r); } else { ................ } // Launch the new version setup screen if needed. We do this -after- // launching the initial activity (that is, home), so that it can have // a chance to initialize itself while in the background, making the // switch back to it faster and look better. if (isFocusedStack(stack)) { //启动系统设置向导对应的Activity,当系统更新或初次使用时需要配置 mService.startSetupActivityLocked(); } ................ return true;}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
从上面的代码可以看出,realStartActivityLocked函数主要工作包括:
1、进一步配置ActivityRecord和ProcessRecord;
2、调用scheduleLaunchActivity,通知应用进程启动Activity;
3、在Activity启动后,AMS调用minimalResumeActivityLocked更新相应的状态。
这里我们只需要进一步看看scheduleLaunchActivity和minimalResumeActivityLocked这两个函数的流程。
1、scheduleLaunchActivity
scheduleLaunchActivity定义于ApplicationThread中:
public final void scheduleLaunchActivity(........) { //更新进程的状态 updateProcessState(procState, false); ActivityClientRecord r = new ActivityClientRecord(); //保存AMS传递过来的信息 r.token = token; r.ident = ident; r.intent = intent; ........... //更新本地配置 updatePendingConfiguration(curConfig); //发送消息,即ApplicationThread的工作其实就是与AMS通信 //实际的处理,还是交给进程主线程的代表ActivityThread处理 sendMessage(H.LAUNCH_ACTIVITY, r);}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
ActivityThread中的handler处理消息的代码如下:
public void handleMessage(Message msg) { ............... switch (msg.what) { case LAUNCH_ACTIVITY: { .............. final ActivityClientRecord r = (ActivityClientRecord) msg.obj; //利用ApplicationInfo等信息得到对应的LoadedApk,保存到ActivityClientRecord r.packageInfo = getPackageInfoNoCheck( r.activityInfo.applicationInfo, r.compatInfo); //调用handleLaunchActivity handleLaunchActivity(r, null, "LAUNCH_ACTIVITY"); .............. } break; ........... } .............}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
我们跟进一下handleLaunchActivity:
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) { // If we are getting ready to gc after going to the background, well // we are back active so skip it. // 如果Activity从前台移动到后台,则有可能准备进行Gc操作 // 现在Activity重新启动,就需要取消Gc操作了 // 对于新建Activity而言,此处无实际动作 unscheduleGcIdler(); mSomeActivitiesChanged = true; //Activity进行性能统计 if (r.profilerInfo != null) { mProfiler.setProfiler(r.profilerInfo); mProfiler.startProfiling(); } // Make sure we are running with the most recent config. // 保证Activity以最新的配置启动,即保证Activity符合最新语言、主题、分辨率等的要求 handleConfigurationChanged(null, null); ............ // Initialize before creating the activity WindowManagerGlobal.initialize(); //1、创建Activity Activity a = performLaunchActivity(r, customIntent); if (a != null) { r.createdConfig = new Configuration(mConfiguration); ............ //2、调用activity的onResume handleResumeActivity(.......); if (!r.activity.mFinished && r.startsNotResumed) { // The activity manager actually wants this one to start out paused, because it // needs to be visible but isn't in the foreground. We accomplish this by going // through the normal startup (because activities expect to go through onResume() // the first time they run, before their window is displayed), and then pausing it. // 处理可见但非前台的Activity,这种Activity在启动后将进入到pause状态 performPauseActivityIfNeeded(r, reason); } ................... } else { try { //如果启动错误,则通知AMS ActivityManagerNative.getDefault() .finishActivity(r.token, Activity.RESULT_CANCELED, null, Activity.DONT_FINISH_TASK_WITH_ACTIVITY); } catch (RemoteException ex) { ............... } }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
从上述代码可以看出,handleLaunchActivity的工作主要包括:
1、调用performLaunchActivity创建出Activity;
2、调用handleResumeActivity,完成调用目标Activity的onResume接口等工作;
3、对于可见但非前台的Activity,还需要调用performPauseActivityIfNeeded函数,调用Activity的onPause接口。
我们主要看一下performLaunchActivity和handleResumeActivity函数。
1.1 performLaunchActivity
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) { ............ Activity activity = null; try { java.lang.ClassLoader cl = r.packageInfo.getClassLoader(); //反射创建Activity activity = mInstrumentation.newActivity( cl, component.getClassName(), r.intent); ............... } catch (Exception e) { ........... } try { .............. if (activity != null) { .......... //设置Activity的主要变量,例如mMainThread、mUiThread等 //mMainThread的类型为ActivityThread;mUiThread的类型为Thread //二者实际的工作线程是同一个 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); ........... //进行主题的设置 activity.mStartedActivity = false; int theme = r.activityInfo.getThemeResource(); if (theme != 0) { activity.setTheme(theme); } //调用Activity的onCreate函数 activity.mCalled = false; if (r.isPersistable()) { mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState); } else { mInstrumentation.callActivityOnCreate(activity, r.state); } ............. r.activity = activity; r.stopped = true; if (!r.activity.mFinished) { //调用Activity的onStart函数 activity.performStart(); r.stopped = false; } //调用Activity的onRestoreInstanceState函数 if (!r.activity.mFinished) { if (r.isPersistable()) { if (r.state != null || r.persistentState != null) { mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state, r.persistentState); } } else if (r.state != null) { mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state); } } //调用Activity的onPostCreate接口 if (!r.activity.mFinished) { activity.mCalled = false; if (r.isPersistable()) { mInstrumentation.callActivityOnPostCreate(activity, r.state, r.persistentState); } else { mInstrumentation.callActivityOnPostCreate(activity, r.state); } ............. } r.paused = true; //Activity保存到进程中 mActivities.put(r.token, r); } } catch (SuperNotCalledException e) { ......... } catch (Exception e) { .......... } return activity;}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
performLaunchActivity的功能比较直观,就是利用反射创建出目标Activity,然后设置Activity的内部变量,最后依次调用Activity生命周期中的接口,主要包括onCreate、onStart等。
1.2 handleResumeActivity
接下来,看看handleResumeActivity的工作:
final void handleResumeActivity(.......) { ActivityClientRecord r = mActivities.get(token); .............. //主要是调用目标Activity的onResume函数 r = performResumeActivity(token, clearHide, reason); if (r != null) { final Activity a = r.activity; //为绘制做准备工作 .............. if (!r.activity.mFinished && willBeVisible && r.activity.mDecor != null && !r.hideForNow) { //进行绘制相关的工作 ............. } if (!r.onlyLocalRequest) { //可以看出ActivityThread用Stack的方式,保存完成onResume的Activity //r为刚刚完成onResume的新Activity,mNewActivities保存已经完成onResume的Activity //新的Activity的nextIdle指向旧的 r.nextIdle = mNewActivities; //然后将新建的Activity保存到mNewActivities中 mNewActivities = r; ........... //向ActivityThread的MessageQueue中增加一个IdleHandler Looper.myQueue().addIdleHandler(new Idler()); } r.onlyLocalRequest = false; // Tell the activity manager we have resumed. if (reallyResume) { try { //通知AMS Activity进入Resume状态 //AMS会修改对应的存储信息 ActivityManagerNative.getDefault().activityResumed(token); } catch (RemoteException ex) { ............ } } } else { ........... }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
从上面的代码可以看出,handleResumeActivity函数将会调用Activity的onResume接口,并进行绘制相关的操作,
然后向Activity的MessageQueue中增加一个IdleHandler,最终通知AMS更新Activity的状态。
在之前的博客Android7.0 MessageQueue 中,我们提到过当MessagQueue的next函数被调用时,如果队列中没有message需要处理,那么将调用添加到MessageQueue的IdleHandler的queueIdle接口。
handleResumeActivity函数向ActivityThread增加了一个IdleHandler,我们看看它的作用:
private class Idler implements MessageQueue.IdleHandler { public final boolean queueIdle() { ActivityClientRecord a = mNewActivities; .................. if (a != null) { mNewActivities = null; IActivityManager am = ActivityManagerNative.getDefault(); ActivityClientRecord prev; do { ............ if (a.activity != null && !a.activity.mFinished) { try { //调用AMS的activityIdle函数 am.activityIdle(a.token, a.createdConfig, stopProfiling); a.createdConfig = null; } catch (RemoteException ex) { .............. } //do-while循环将处理所有的已经完成onResume的Activity prev = a; a = a.nextIdle; prev.nextIdle = null; } }while (a != null); .......... } ......... //返回值为false,于是执行一次后,会被移除 return false; }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
从上面的代码可以看出,当ActivityThread空闲下来后,将为所有完成onResume的Activity调用AMS的activityIdle函数。
该函数是Activity成功创建并启动流程中的最后一步,我们稍后再分析。
至此,scheduleLaunchActivity函数分析完毕,我们看看realStartActivityLocked函数的下一个关键点minimalResumeActivityLocked。
2、minimalResumeActivityLocked
minimalResumeActivityLocked定义于ActivityStack中。ActivityStack是Activity所在Task中,保存ActivityRecord的数据结构。
我们看看minimalResumeActivityLocked的代码:
void minimalResumeActivityLocked(ActivityRecord r) { r.state = ActivityState.RESUMED; ............. mResumedActivity = r; r.task.touchActiveTime(); //mRecentTasks保存近期被调用的Task mRecentTasks.addLocked(r.task); //更新一些状态 completeResumeLocked(r); //判断AMS当前维护的Activity对应的进程是否可以sleep //若可以sleep,将调用对应ApplicationThread的scheduleSleeping函数 mStackSupervisor.checkReadyForSleepLocked(); setLaunchTime(r); ............}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
上述代码中主要的工作由completeResumeLocked来完成:
/*** Once we know that we have asked an application to put an activity in* the resumed state (either by launching it or explicitly telling it),* this function updates the rest of our state to match that fact.*/private void completeResumeLocked(ActivityRecord next) { //更新ActivityRecord的变量 next.visible = true; next.idle = false; ............ if (next.isHomeActivity()) { //对Home Activity的特殊处理 .......... } if (next.nowVisible) { // We won't get a call to reportActivityVisibleLocked() so dismiss lockscreen now. //如果已经visible将进行通知 mStackSupervisor.reportActivityVisibleLocked(next); mStackSupervisor.notifyActivityDrawnForKeyguard(); } // schedule an idle timeout in case the app doesn't do it for us. //发送一个延迟消息IDLE_TIMEOUT_MSG,延迟时间为10s //这里就是要求Activity启动后,10s内要调用AMS的activityIdle函数 //不过从代码来看,即使Activity 10s内没有调用activityIdle函数, //ActivityStackSupervisor也会自己调用activityIdleInternalLocked函数 mStackSupervisor.scheduleIdleTimeoutLocked(next); mStackSupervisor.reportResumedActivityLocked(next); ......................}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
从这部分代码,可以看出minimalResumeActivityLocked函数整体上就是负责更新一些状态,不用过于在意它的细节。
四、activityIdle函数
现在,我们看一下Activity启动的最后一步,即调用AMS的activityIdle函数:
public final void activityIdle(IBinder token, Configuration config, boolean stopProfiling) { ................ synchronized (this) { ActivityStack stack = ActivityRecord.getStackLocked(token); if (stack != null) { //主要调用ActivityStackSupervisor的activityIdleInternalLocked函数 ActivityRecord r = mStackSupervisor.activityIdleInternalLocked(token, false, config); ................. } } ..............}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
跟进activityIdleInternalLocked函数:
//ActivityThread在超时时间内,调用activityIdle时,fromTimeout的值为false//如果超时后,由ActivityStackSupervisor主动调用该函数,fromTimeout的值为truefinal ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout, Configuration config) { ................ ActivityRecord r = ActivityRecord.forTokenLocked(token); if (r != null) { .................... mHandler.removeMessages(IDLE_TIMEOUT_MSG, r); .................... if (fromTimeout) { //超时时,将通知Activity完成启动 reportActivityLaunchedLocked(fromTimeout, r, -1, -1); } if (config != null) { r.configuration = config; } r.idle = true; ................ } //当所有Resumed Activity都处于空闲状态时 if (allResumedActivitiesIdle()) { if (r != null) { mService.scheduleAppGcsLocked(); } //mLaunchingActivity是一个WakeLock,用于防止在操作Activity的过程中休眠 //由于该WakeLock不能长时间使用,因此系统设置了一个超时消息LAUNCH_TIMEOUT_MSG //处理该消息时,将释放该WakeLock //此处,当所有Activity均空闲时,说明事件处理完毕,此时需要释放该WakeLock if (mLaunchingActivity.isHeld()) { mHandler.removeMessages(LAUNCH_TIMEOUT_MSG); ............... mLaunchingActivity.release(); } ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); } // Atomically retrieve all of the other things to do. //processStoppingActivitiesLocked返回那些因本次Activity启动而被暂停(paused)的Activity final ArrayList<ActivityRecord> stops = processStoppingActivitiesLocked(true); NS = stops != null ? stops.size() : 0; if ((NF = mFinishingActivities.size()) > 0) { //finishes保存等待结束的Activity finishes = new ArrayList<>(mFinishingActivities); mFinishingActivities.clear(); } ................. // Stop any activities that are scheduled to do so but have been // waiting for the next one to start. for (int i = 0; i < NS; i++) { r = stops.get(i); final ActivityStack stack = r.task.stack; if (stack != null) { if (r.finishing) { //如果被暂停的Activity已经处于了finishing状态,则通知它们执行Destroy操作,即Activity的onDestroy函数将被调用 stack.finishCurrentActivityLocked(r, ActivityStack.FINISH_IMMEDIATELY, false); } else { //否则通知它们执行stop操作,即Activity的onStop将被调用 stack.stopActivityLocked(r); } } } // Finish any activities that are scheduled to do so but have been // waiting for the next one to start. // 处理等待结束的Activity,从代码来看最终也是调用其onDestroy接口 for (int i = 0; i < NF; i++) { r = finishes.get(i); final ActivityStack stack = r.task.stack; if (stack != null) { activityRemoved |= stack.destroyActivityLocked(r, true, "finish-idle"); } } ................ //AMS清理没有任何组建的无用进程 mService.trimApplications(); if (activityRemoved) { //如果等待结束的Activity被处理,保证前台栈顶Activity处于Resumed状态 resumeFocusedStackTopActivityLocked(); } return r;}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
至此,启动Activity最后一部分的主要工作介绍完毕。
从代码来看,这一部分最主要的工作是:
进行一些扫尾工作,即根据后台Activity是否处于finishing状态,分别调用其onStop和onDestroy接口。
同时,AMS也会清理一些无实际工作的进程。
最后需要补充的是:
我们利用am start -W启动Activity时,需要等待返回结果,详细代码可以参考启动Activity的过程:一。
在ActivityStarter的startActivityMayWait函数中:
final int startActivityMayWait(.........) { ............. //outResult != null,说明启动命令发送成功 if (outResult != null) { outResult.result = res; if (res == ActivityManager.START_SUCCESS) { mSupervisor.mWaitingActivityLaunched.add(outResult); do { try { //等待Task移动到前台 mService.wait(); } catch (InterruptedException e) { } } while (outResult.result != START_TASK_TO_FRONT && !outResult.timeout && outResult.who == null); if (outResult.result == START_TASK_TO_FRONT) { res = START_TASK_TO_FRONT; } } if (res == START_TASK_TO_FRONT) { ActivityRecord r = stack.topRunningActivityLocked(); if (r.nowVisible && r.state == RESUMED) { outResult.timeout = false; outResult.who = new ComponentName(r.info.packageName, r.info.name); outResult.totalTime = 0; outResult.thisTime = 0; } else { outResult.thisTime = SystemClock.uptimeMillis(); mSupervisor.mWaitingActivityVisible.add(outResult); do { try { //等待Activity可见 mService.wait(); } catch (InterruptedException e) { } } while (!outResult.timeout && outResult.who == null); } } } ..................}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
上面代码中,startActivityMayWait等待的信号均由ActivityStackSupervisor触发。
在启动Activity的过程:一中简单提到过,在startActivityLocked函数的最后,调用了postStartActivityUncheckedProcessing函数进行通知:
void postStartActivityUncheckedProcessing(......) { ............. // We're waiting for an activity launch to finish, but that activity simply // brought another activity to front. Let startActivityMayWait() know about // this, so it waits for the new activity to become visible instead. if (result == START_TASK_TO_FRONT && !mSupervisor.mWaitingActivityLaunched.isEmpty()) { mSupervisor.reportTaskToFrontNoLaunch(mStartActivity); } ............}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
我们看ActivityStackSupervisor的reportTaskToFrontNoLaunch函数:
void reportTaskToFrontNoLaunch(ActivityRecord r) { boolean changed = false; for (int i = mWaitingActivityLaunched.size() - 1; i >= 0; i--) { WaitResult w = mWaitingActivityLaunched.remove(i); //who表示componentName,Activity未可见前为null if (w.who == null) { changed = true; // Set result to START_TASK_TO_FRONT so that startActivityMayWait() knows that // the starting activity ends up moving another activity to front, and it should // wait for this new activity to become visible instead. // Do not modify other fields. w.result = START_TASK_TO_FRONT; } } if (changed) { //notifyAll通知ActivityStarter待启动Activity对应的Task移动到了前台 mService.notifyAll(); }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
同样,当Activity可见时,WindowManagerService将回调ActivityRecord中的windowsVisible函数:
public void windowsVisible() { synchronized (mService) { ActivityRecord r = tokenToActivityRecordLocked(this); if (r != null) { r.windowsVisibleLocked(); } }}void windowsVisibleLocked() { mStackSupervisor.reportActivityVisibleLocked(this); ...........}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
跟进一下ActivityStackSupervisor的reportActivityVisibleLocked函数:
void reportActivityVisibleLocked(ActivityRecord r) { sendWaitingVisibleReportLocked(r);}void sendWaitingVisibleReportLocked(ActivityRecord r) { boolean changed = false; for (int i = mWaitingActivityVisible.size()-1; i >= 0; i--) { WaitResult w = mWaitingActivityVisible.get(i); if (w.who == null) { changed = true; w.timeout = false; if (r != null) { //构造出ComponentName等信息 w.who = new ComponentName(r.info.packageName, r.info.name); } w.totalTime = SystemClock.uptimeMillis() - w.thisTime; w.thisTime = w.totalTime; } } if (changed) { //notifyAll通知ActivityStarter待启动Activity可见 mService.notifyAll(); }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
五、总结
大图地址
至此,AMS启动Activity的后一部分基本介绍完毕。
这一部分的代码整体流程如上图所示,我们省略一些细节,例如绘制等。
从整个逻辑来看,这部分流程比较清晰,主要思想如下:
1、启动进程,创建自己的ActivityThread和ApplicationThread。
2、进程与AMS通信,其实就是完成一个注册过程(将ApplicationThread作为Binder通信接口交给AMS保存),AMS毕竟要统一管理系统中所有的应用进程。
3、AMS通知进程创建自己的Android运行环境,加入到Android体系。
4、AMS通知进程可以启动进程中的组件了,注意四大组件的顺序以此是ContentProvider、Activity、Service、BroadcastReceiver(参考上述代码,可以容易看出这个结论,本文我们仅分析了Activity的启动过程)。
5、Activity启动完成后,通知AMS更新相关的状态,并进行一些扫尾工作。
整体而言,所有的实际工作都是由进程自己完成的,AMS仅起到一个管理的作用。
- Android 7.0 ActivityManagerService(3) 启动Activity的过程:二
- Android 7.0 ActivityManagerService(3) 启动Activity的过程:二
- Android 7.0 ActivityManagerService(2) 启动Activity的过程:一
- Android 7.0 ActivityManagerService(4) 启动Activity的过程:三
- Android 7.0 ActivityManagerService(2) 启动Activity的过程:一
- Android 7.0 ActivityManagerService(4) 启动Activity的过程:三
- Android 7.0 ActivityManagerService(1) AMS的启动过程
- Android 7.0 ActivityManagerService(1) AMS的启动过程
- ActivityManagerService的启动过程
- ActivityManagerService的启动和ActivityManagerService对Activity堆栈的管理
- android ActivityManagerService 源码分析----Activity管理(二)
- android ActivityManagerService 源码分析----Activity管理(二)
- android ActivityManagerService 源码分析----Activity管理(二)
- ActivityManagerService启动新的process过程分析
- ActivityManagerService启动过程分析
- ActivityManagerService启动过程
- Android ActivityManagerService(AMS)的Activity管理
- Android ActivityManagerService(AMS)的Activity管理
- web后端--一个小小的下载和防盗链功能
- unix 编辑命令大全(vi/vim)
- 面试复习—网络知识点-----UDP
- 前台页面调试技巧----页面打印console
- java匿名内部类 学习笔记
- Android 7.0 ActivityManagerService(3) 启动Activity的过程:二
- 【Codeforces 839D. Winter is here】& 莫比乌斯反演
- vm dhcp hostname
- C#中DataTable添加列和行的三种方法
- 网络流,增广路,Edmonds_Karp 以及 Dinic 算法(HDU 1532)
- K&R寄存器变量
- Qt 常用快捷键 + 引用第三方库
- zoj2277 The Gate to Freedom
- 理解端口与端口组