[toc]
基于 Android 7.1.1 源码,总结进程状态调整的调度策略!
1 进程 oomAdj 的调度方法 和进程的 oomAdj 调度相关的主要有`3 个方法:
updateOomAdjLocked :用于更新进程的 adj,该方法会依次调用 computeOomAdjLocked 和 applyOomAdjLocked;
computeOomAdjLocked :计算进程的 adj,返回计算后 RawAdj 值;
applyOomAdjLocked :应用 adj,当需要杀掉目标进程则返回 false;否则返回 true。
当在一些特定的场景下,系统会调用 updateOomAdjLocked 来更新指定进程的 oomAdj,该方法会先调用 computeOomAdjLocked 计算出一个新的 oomAdj,然后在调用 applyOomAdjLocked 来设置指定进程的 oomAdj!
updateOomAdjLocked 有多个重载函数:
1 2 3 4 5 6 boolean updateOomAdjLocked (ProcessRecord app) boolean updateOomAdjLocked (ProcessRecord app, int cachedAdj, ProcessRecord TOP_APP, boolean doingAll, long now) void updateOomAdjLocked ()
其中,五个参数的 updateOomAdjLocked 方法是私有方法,只提供给其他的两个方法调用!!
1 boolean updateOomAdjLocked (ProcessRecord app, int cachedAdj, ProcessRecord TOP_APP, boolean doingAll, long now)
2 调度时机 接下里,我们看看 updateOomAdjLocked 的调度时机:
2.1 Activity 调整 和 Activity 相关的调整代码主要是位于 ActivityStackSupervisor.java 和 ActivityStack.java 中:
2.1.1 realStartActivityLocked ActivityStackSupervisor.realStartActivityLocked:启动 Activity,以下是关键代码段:
1 2 3 4 mService.updateLruProcessLocked(app, true , null ); mService.updateOomAdjLocked();
在启动之前会调用 updateOomAdjLocked 更新所有进程的 oomAdj!
2.1.2 resumeTopActivityInnerLocked ActivityStack.resumeTopActivityInnerLocked: 恢复栈顶 Activity,以下是关键代码段:
1 2 3 4 5 6 7 8 9 10 11 next.state = ActivityState.RESUMED; mResumedActivity = next; next.task.touchActiveTime(); mRecentTasks.addLocked(next.task); mService.updateLruProcessLocked(next.app, true , null ); updateLRUListLocked(next); mService.updateOomAdjLocked();
更新所有进程的 oomAdj!
2.1.3 finishCurrentActivityLocked ActivityStack.finishCurrentActivityLocked: 结束 Activity,以下是关键代码段:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 if (mode == FINISH_AFTER_VISIBLE && (r.visible || r.nowVisible) && next != null && !next.nowVisible) { if (!mStackSupervisor.mStoppingActivities.contains(r)) { addToStopping(r, false ); } if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to STOPPING: " + r + " (finish requested)" ); r.state = ActivityState.STOPPING; if (oomAdj) { mService.updateOomAdjLocked(); } return r; }
更新所有进程的 oomAdj!
2.1.4 destroyActivityLocked ActivityStack.destroyActivityLocked: 摧毁 Activity,以下是关键代码段:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 if (hadApp) { if (removeFromApp) { r.app.activities.remove(r); if (mService.mHeavyWeightProcess == r.app && r.app.activities.size() <= 0 ) { mService.mHeavyWeightProcess = null ; mService.mHandler.sendEmptyMessage( ActivityManagerService.CANCEL_HEAVY_NOTIFICATION_MSG); } if (r.app.activities.isEmpty()) { mService.mServices.updateServiceConnectionActivitiesLocked(r.app); mService.updateLruProcessLocked(r.app, false , null ); mService.updateOomAdjLocked(); } } ... ... ... ... }
会更新所有进程的 oomAdj!
2.2 Service 调整 和 Service 相关的调整代码主要是位于 ActiveServices.java 中:
2.2.1 realStartServiceLocked ActiveServices.realStartServiceLocked : 启动服务,以下是关键代码段:
1 2 3 4 final boolean newService = app.services.add(r);bumpServiceExecutingLocked(r, execInFg, "create" ); mAm.updateLruProcessLocked(app, false , null ); mAm.updateOomAdjLocked();
2.2.2 bindServiceLocked ActiveServices.bindServiceLocked : 绑定服务,以下是关键代码段:
1 2 3 4 5 6 7 8 9 10 11 12 13 if (s.app != null ) { if ((flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0 ) { s.app.treatLikeActivity = true ; } if (s.whitelistManager) { s.app.whitelistManager = true ; } mAm.updateLruProcessLocked(s.app, s.app.hasClientActivities || s.app.treatLikeActivity, b.client); mAm.updateOomAdjLocked(s.app); }
只更新服务所在进程的 oomAdj!
2.2.3 unbindServiceLocked ActiveServices.unbindServiceLocked : 解绑服务,以下是关键代码段:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 if (r.binding.service.app != null ) { if (r.binding.service.app.whitelistManager) { updateWhitelistManagerLocked(r.binding.service.app); } if ((r.flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0 ) { r.binding.service.app.treatLikeActivity = true ; mAm.updateLruProcessLocked(r.binding.service.app, r.binding.service.app.hasClientActivities || r.binding.service.app.treatLikeActivity, null ); } mAm.updateOomAdjLocked(r.binding.service.app); }
只更新服务所在进程的 oomAdj!!
2.2.4 bringDownServiceLocked ActiveServices.bringDownServiceLocked : 结束服务,以下是关键代码段:
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 if (r.app != null && r.app.thread != null ) { for (int i=r.bindings.size()-1 ; i>=0 ; i--) { IntentBindRecord ibr = r.bindings.valueAt(i); if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Bringing down binding " + ibr + ": hasBound=" + ibr.hasBound); if (ibr.hasBound) { try { bumpServiceExecutingLocked(r, false , "bring down unbind" ); mAm.updateOomAdjLocked(r.app); ibr.hasBound = false ; r.app.thread.scheduleUnbindService(r, ibr.intent.getIntent()); } catch (Exception e) { Slog.w(TAG, "Exception when unbinding service " + r.shortName, e); serviceProcessGoneLocked(r); } } } } ... ... ... ... if (r.app != null ) { synchronized (r.stats.getBatteryStats()) { r.stats.stopLaunchedLocked(); } r.app.services.remove(r); if (r.whitelistManager) { updateWhitelistManagerLocked(r.app); } if (r.app.thread != null ) { updateServiceForegroundLocked(r.app, false ); try { bumpServiceExecutingLocked(r, false , "destroy" ); mDestroyingServices.add(r); r.destroying = true ; mAm.updateOomAdjLocked(r.app); r.app.thread.scheduleStopService(r); } catch (Exception e) { Slog.w(TAG, "Exception when destroying service " + r.shortName, e); serviceProcessGoneLocked(r); } } else { if (DEBUG_SERVICE) Slog.v( TAG_SERVICE, "Removed service that has no process: " + r); } } else { if (DEBUG_SERVICE) Slog.v( TAG_SERVICE, "Removed service that is not running: " + r); }
只更新服务所在进程的 oomAdj!
2.2.5 sendServiceArgsLocked ActiveServices.sendServiceArgsLocked : 发送启动参数,该方法会拉起服务的 onStart 方法,以下是关键代码段:
1 2 3 4 5 6 bumpServiceExecutingLocked(r, execInFg, "start" ); if (!oomAdjusted) { oomAdjusted = true ; mAm.updateOomAdjLocked(r.app); }
sendServiceArgsLocked 在很多地方都有调用:
realStartServiceLocked 方法在拉起 onCreate 方法之前,会对所有进程的 oomAdj 做一次调整;接着调用 sendServiceArgsLocked,但是由于其第三个参数 oomAdjusted 传入的是 true,所以不会再次 oomAdj 更新!
cleanUpRemovedTaskLocked 方法是当我们从最近任务中移除一个任务时候,我们会移除该任务所对应的 Service,那么如果 Service 没有设置 ServiceInfo.FLAG_STOP_WITH_TASK 标志位的话,并且如果服务所在进程没有死亡,那么系统会重新拉起服务:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 for (int i = services.size() - 1 ; i >= 0 ; i--) { ServiceRecord sr = services.get(i); if (sr.startRequested) { if ((sr.serviceInfo.flags&ServiceInfo.FLAG_STOP_WITH_TASK) != 0 ) { Slog.i(TAG, "Stopping service " + sr.shortName + ": remove task" ); stopServiceLocked(sr); } else { sr.pendingStarts.add(new ServiceRecord.StartItem(sr, true , sr.makeNextStartId(), baseIntent, null )); if (sr.app != null && sr.app.thread != null ) { try { sendServiceArgsLocked(sr, true , false ); } catch (TransactionTooLargeException e) { } } } } }
这里,第三个参数 oomAdjusted 传入的是 false,所以会发生 oomAdj 更新!
bringUpServiceLocked 方法中如果服务所在进程已经被启动,并且服务的 onCreate 方法已经被拉起,那就会直接 sendServiceArgsLocked 拉起服务的 onStart 方法!
1 2 3 4 if (r.app != null && r.app.thread != null ) { sendServiceArgsLocked(r, execInFg, false ); return null ; }
这里,第三个参数 oomAdjusted 也传入的是 false,所以也会发生 oomAdj 更新!
2.2.6 serviceDoneExecutingLocked ActiveServices.serviceDoneExecutingLocked 以下是关键代码段:
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 if (r.executeNesting <= 0 ) { if (r.app != null ) { if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Nesting at 0 of " + r.shortName); r.app.execServicesFg = false ; r.app.executingServices.remove(r); if (r.app.executingServices.size() == 0 ) { if (DEBUG_SERVICE || DEBUG_SERVICE_EXECUTING) Slog.v(TAG_SERVICE_EXECUTING, "No more executingServices of " + r.shortName); mAm.mHandler.removeMessages(ActivityManagerService.SERVICE_TIMEOUT_MSG, r.app); } else if (r.executeFg) { for (int i=r.app.executingServices.size()-1 ; i>=0 ; i--) { if (r.app.executingServices.valueAt(i).executeFg) { r.app.execServicesFg = true ; break ; } } } if (inDestroying) { if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "doneExecuting remove destroying " + r); mDestroyingServices.remove(r); r.bindings.clear(); } mAm.updateOomAdjLocked(r.app); }
serviceDoneExecutingLocked 方法的调用时机主要是在:
执行启动 Service 等等一些操作时抛出异
服务所在进程死亡时;
bind 操作完成后;
unbind 操作完成后等等!
2.2.7 removeConnectionLocked ActiveServices.removeConnectionLocked :当我们要移除对一个服务的绑定的时候,会触发该方法,以下是关键代码段:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0 && b.intent.hasBound) { try { bumpServiceExecutingLocked(s, false , "unbind" ); if (b.client != s.app && (c.flags&Context.BIND_WAIVE_PRIORITY) == 0 && s.app.setProcState <= ActivityManager.PROCESS_STATE_RECEIVER) { mAm.updateLruProcessLocked(s.app, false , null ); } mAm.updateOomAdjLocked(s.app); b.intent.hasBound = false ; b.intent.doRebind = false ; s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent()); } catch (Exception e) { Slog.w(TAG, "Exception when unbinding service " + s.shortName, e); serviceProcessGoneLocked(s); } }
removeConnectionLocked 的调用时机如下:
killServicesLocked :当我们要杀掉某个应用进程的时候,我们会解除该进程对其他进程中服务的绑定:
1 2 3 4 5 for (int i = app.connections.size() - 1 ; i >= 0 ; i--) { ConnectionRecord r = app.connections.valueAt(i); removeConnectionLocked(r, app, null ); }
cleanUpActivityServicesLocked :
1 2 3 4 5 6 7 8 9 if (r.connections != null ) { Iterator<ConnectionRecord> it = r.connections.iterator(); while (it.hasNext()) { ConnectionRecord c = it.next(); mService.mServices.removeConnectionLocked(c, null , r); } r.connections = null ; }
unbindServiceLocked: 当我们要接触绑定某个服务的时候,会调用 removeConnectionLocked,断开连接!
2.5.8 setServiceForegroundLocked ActiveServices.setServiceForegroundLocked:用于将一个服务设置为前台,关键代码段:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 ServiceRecord r = findServiceLocked(className, token, userId); if (r != null ) { if (id != 0 ) { ... ... ... if (r.app != null ) { updateServiceForegroundLocked(r.app, true ); } ... ... ... } else { if (r.isForeground) { r.isForeground = false ; if (r.app != null ) { mAm.updateLruProcessLocked(r.app, false , null ); updateServiceForegroundLocked(r.app, true ); } } ... ... ... ... } }
在 updateServiceForegroundLocked 方法中,会调用:AMS.updateProcessForegroundLocked 方法:
1 2 3 4 5 private void updateServiceForegroundLocked (ProcessRecord proc, boolean oomAdj) { ... ... ... ... mAm.updateProcessForegroundLocked(proc, anyForeground, oomAdj); }
AMS.updateProcessForegroundLocked 中会根据第三个参数是否为 true 来设置进程的 oomAdj:
1 2 3 4 5 6 7 8 9 final void updateProcessForegroundLocked (ProcessRecord proc, boolean isForeground, boolean oomAdj) { ... ... ... ... if (oomAdj) { updateOomAdjLocked(); } } }
更新所有进程的 oomAdj 的值!
这里我们来说一下 updateProcessForegroundLocked,我们设置一个服务为前台,实际上是设置其所在的进程为前台进程,updateProcessForegroundLocked 的调用有多处,但只有在 setServiceForegroundLocked 方法的调用链中,boolean oomAdj 为 true!!
2.3 broadcast 调整 和 broadcast 相关的调整代码主要是在 BroadcastQueue.java 中:
2.3.1 processNextBroadcast BroadcastQueue.processNextBroadcast: 发送下一个广播,以下是关键代码段:1 2 3 4 5 6 7 8 if (mOrderedBroadcasts.size() == 0 ) { mService.scheduleAppGcsLocked(); if (looped) { mService.updateOomAdjLocked(); } return ; }
只针对有序发送的广播!
2.3.2 processCurBroadcastLocked BroadcastQueue.processCurBroadcastLocked: 处理当前广播,以下是关键代码段:
1 2 3 4 5 6 7 8 9 r.receiver = app.thread.asBinder(); r.curApp = app; app.curReceiver = r; app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_RECEIVER); mService.updateLruProcessLocked(app, false , null ); mService.updateOomAdjLocked();
只针对有序发送的广播!
2.3.3 deliverToRegisteredReceiverLocked BroadcastQueue.deliverToRegisteredReceiverLocked: 分发已注册的广播,以下是关键代码段:
1 2 3 4 5 6 7 8 9 10 11 12 13 if (ordered) { r.receiver = filter.receiverList.receiver.asBinder(); r.curFilter = filter; filter.receiverList.curBroadcast = r; r.state = BroadcastRecord.CALL_IN_RECEIVE; if (filter.receiverList.app != null ) { r.curApp = filter.receiverList.app; filter.receiverList.app.curReceiver = r; mService.updateOomAdjLocked(r.curApp); } }
只针对有序发送的广播,只针对指定的目标进程!
2.4 ContentProvider 调整 和 ContentProvider 相关的调整代码主要是在 ActivityManagerService.java 中:
2.4.1 removeContentProviderXXX ActivityManagerService.removeContentProvider: 移除 provider,关键代码段:
1 2 3 4 5 if (decProviderCountLocked(conn, null , null , stable)) { updateOomAdjLocked(); }
更新所有进程的 oomAdj 值!
ActivityManagerService.removeContentProviderExternalUnchecked: 移除 provider,关键代码段:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 if (localCpr.hasExternalProcessHandles()) { if (localCpr.removeExternalProcessHandleLocked(token)) { updateOomAdjLocked(); } else { Slog.e(TAG, "Attmpt to remove content provider " + localCpr + " with no external reference for token: " + token + "." ); } } else { Slog.e(TAG, "Attmpt to remove content provider: " + localCpr + " with no external references." ); }
更新所有进程的 oomAdj 值!
2.4.2 publishContentProviders ActivityManagerService.publishContentProviders: 发布 provider,关键代码段:
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 final int N = providers.size();for (int i = 0 ; i < N; i++) { ContentProviderHolder src = providers.get(i); if (src == null || src.info == null || src.provider == null ) { continue ; } ContentProviderRecord dst = r.pubProviders.get(src.info.name); if (DEBUG_MU) Slog.v(TAG_MU, "ContentProviderRecord uid = " + dst.uid); if (dst != null ) { ComponentName comp = new ComponentName(dst.info.packageName, dst.info.name); mProviderMap.putProviderByClass(comp, dst); String names[] = dst.info.authority.split(";" ); for (int j = 0 ; j < names.length; j++) { mProviderMap.putProviderByName(names[j], dst); } ... ... ... ... synchronized (dst) { dst.provider = src.provider; dst.proc = r; dst.notifyAll(); } updateOomAdjLocked(r); maybeUpdateProviderUsageStatsLocked(r, src.info.packageName, src.info.authority); } }
更新指定进程的 oomAdj!
2.4.3 getContentProviderImpl ActivityManagerService.getContentProviderImpl: 获取 provider,下面是关键代码段!
1 2 3 4 ... ... ... ... boolean success = updateOomAdjLocked(cpr.proc);... ... ... ...
provider 所在进程的 adj!
关于 ContentProvider,我会单独开一个系列来分析
2.5 Process 调整 和 Process 相关的调整代码主要是在 ActivityManagerService.java 中:
2.5.1 setSystemProcess ActivityManagerService.setSystemProcess: 创建并设置系统进程,以下是关键代码段:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 synchronized (this ) { ProcessRecord app = newProcessRecordLocked(info, info.processName, false , 0 ); app.persistent = true ; app.pid = MY_PID; app.maxAdj = ProcessList.SYSTEM_ADJ; app.makeActive(mSystemThread.getApplicationThread(), mProcessStats); synchronized (mPidsSelfLocked) { mPidsSelfLocked.put(app.pid, app); } updateLruProcessLocked(app, false , null ); updateOomAdjLocked(); }
更新所有进程的 adj
值!
2.5.2 addAppLocked ActivityManagerService.addAppLocked: 创建 persistent 进程,以下是关键代码段:
1 2 3 4 5 6 7 8 if (app == null ) { app = newProcessRecordLocked(info, null , isolated, 0 ); updateLruProcessLocked(app, false , null ); updateOomAdjLocked(); }
更新所有进程的 oomAdj!
2.5.3 attachApplicationLocked ActivityManagerService.attachApplicationLocked: 进程创建后 attach 到 system_server 的过程,以下是关键代码段:
1 2 3 4 5 6 7 8 9 10 11 12 ... ... ... ... if (badApp) { app.kill("error during init" , true ); handleAppDiedLocked(app, false , true ); return false ; } if (!didSomething) { updateOomAdjLocked(); }
更新所有进程的 adj 值!
2.5.4 trimApplications ActivityManagerService.trimApplications: 回收应用程序内存,以下是关键代码段:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 for (i = mRemovedProcesses.size() - 1 ; i >= 0 ; i --) { final ProcessRecord app = mRemovedProcesses.get(i); if (app.activities.size() == 0 && app.curReceiver == null && app.services.size() == 0 ) { if (app.pid > 0 && app.pid != MY_PID) { app.kill("empty" , false ); } else { try { app.thread.scheduleExit(); } catch (Exception e) { } } cleanUpApplicationRecordLocked(app, false , true , -1 , false ); mRemovedProcesses.remove(i); if (app.persistent) { addAppLocked(app.info, false , null ); } } } updateOomAdjLocked();
更新所有进程的 oomAdj!
2.5.5 appDiedLocked ActivityManagerService.appDiedLocked:进程死亡,以下是关键代码段:
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 if (app.pid == pid && app.thread != null && app.thread.asBinder() == thread.asBinder()) { boolean doLowMem = app.instrumentationClass == null ; boolean doOomAdj = doLowMem; if (!app.killedByAm) { Slog.i(TAG, "Process " + app.processName + " (pid " + pid + ") has died" ); mAllowLowerMemLevel = true ; } else { mAllowLowerMemLevel = false ; doLowMem = false ; } EventLog.writeEvent(EventLogTags.AM_PROC_DIED, app.userId, app.pid, app.processName); if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP, "Dying app: " + app + ", pid: " + pid + ", thread: " + thread.asBinder()); handleAppDiedLocked(app, false , true ); if (doOomAdj) { updateOomAdjLocked(); } if (doLowMem) { doLowMemReportIfNeededLocked(app); } } else if (app.pid != pid) { }
更新所有进程的 oomAdj!
2.5.6 killAllBackgroundProcesses ActivityManagerService.killAllBackgroundProcesses: 杀死所有后台进程,以下是关键代码段:
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 synchronized (this ) { final ArrayList<ProcessRecord> procs = new ArrayList<>(); final int NP = mProcessNames.getMap().size(); for (int ip = 0 ; ip < NP; ip++) { final SparseArray<ProcessRecord> apps = mProcessNames.getMap().valueAt(ip); final int NA = apps.size(); for (int ia = 0 ; ia < NA; ia++) { final ProcessRecord app = apps.valueAt(ia); if (app.persistent) { continue ; } if (app.removed) { procs.add(app); } else if (app.setAdj >= ProcessList.CACHED_APP_MIN_ADJ) { app.removed = true ; procs.add(app); } } } final int N = procs.size(); for (int i = 0 ; i < N; i++) { removeProcessLocked(procs.get(i), false , true , "kill all background" ); } mAllowLowerMemLevel = true ; updateOomAdjLocked(); doLowMemReportIfNeededLocked(null ); }
继续分析!
2.5.7 killPackageProcessesLocked ActivityManagerService.killPackageProcessesLocked
: 杀掉指定包名相关的进程,以下是关键代码段:
1 2 3 4 5 6 7 ... ... ... int N = procs.size();for (int i=0 ; i<N; i++) { removeProcessLocked(procs.get(i), callerWillRestart, allowRestart, reason); } updateOomAdjLocked();
调整所有进程的 oomAdj!
2.5.8 setProcessForeground ActivityManagerService.setProcessForeground
:设置进程为前台进程,下面是关键代码片段:
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 synchronized (mPidsSelfLocked) { ProcessRecord pr = mPidsSelfLocked.get(pid); if (pr == null && isForeground) { Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid); return ; } ForegroundToken oldToken = mForegroundProcesses.get(pid); if (oldToken != null ) { oldToken.token.unlinkToDeath(oldToken, 0 ); mForegroundProcesses.remove(pid); if (pr != null ) { pr.forcingToForeground = null ; } changed = true ; } if (isForeground && token != null ) { ForegroundToken newToken = new ForegroundToken() { @Override public void binderDied () { foregroundTokenDied(this ); } }; newToken.pid = pid; newToken.token = token; try { token.linkToDeath(newToken, 0 ); mForegroundProcesses.put(pid, newToken); pr.forcingToForeground = token; changed = true ; } catch (RemoteException e) { } } } if (changed) { updateOomAdjLocked(); }
调整所有进程的 oomAdj
!
首先我说下 ForegroundToken
,表示一个前台句柄,其内部有一个 token
对象,该对象是一个 Binder
对象!当我们设置了一个进程为前台进程后,每个进程都会有一个 token
对象!
其使用场景是,弹出 Toast
,当一个进程中会弹出 Toast
后,该进程会被设置为前台进程,就会触发 setProcessForeground
方法!token
对象定义是在 NotificationManagerService
中:
1 final IBinder mForegroundToken = new Binder();
再说一下:ForegroundToken.binderDied
方法,当 token
死亡后,其会被调用,从而触发 foregroundTokenDied
!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 void foregroundTokenDied (ForegroundToken token) { synchronized (ActivityManagerService.this ) { synchronized (mPidsSelfLocked) { ForegroundToken cur = mForegroundProcesses.get(token.pid); if (cur != token) { return ; } mForegroundProcesses.remove(token.pid); ProcessRecord pr = mPidsSelfLocked.get(token.pid); if (pr == null ) { return ; } pr.forcingToForeground = null ; updateProcessForegroundLocked(pr, false , false ); } updateOomAdjLocked(); } }
调整所有进程的 oomAdj
!
2.5.9 setHasTopUi ActivityManagerService.setHasTopUi
:设置进程是否具有 top ui
!
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 @Override public void setHasTopUi (boolean hasTopUi) throws RemoteException { if (checkCallingPermission(permission.INTERNAL_SYSTEM_WINDOW) != PERMISSION_GRANTED) { throw new SecurityException(msg); } final int pid = Binder.getCallingPid(); final long origId = Binder.clearCallingIdentity(); try { synchronized (this ) { boolean changed = false ; ProcessRecord pr; synchronized (mPidsSelfLocked) { pr = mPidsSelfLocked.get(pid); if (pr == null ) { Slog.w(TAG, "setHasTopUi called on unknown pid: " + pid); return ; } if (pr.hasTopUi != hasTopUi) { Slog.i(TAG, "Setting hasTopUi=" + hasTopUi + " for pid=" + pid); pr.hasTopUi = hasTopUi; changed = true ; } } if (changed) { updateOomAdjLocked(pr); } } } finally { Binder.restoreCallingIdentity(origId); } }
只更新特定进程的 oomAdj
!
该方法主要是在状态栏使用,具体的代码在 StatusBarWindowManager.apply
方法中,以下是关键代码!
1 2 3 4 5 6 7 8 9 10 11 private void apply (State state) { ... ... ... if (mHasTopUi != mHasTopUiChanged) { try { mActivityManager.setHasTopUi(mHasTopUiChanged); } catch (RemoteException e) { Log.e(TAG, "Failed to call setHasTopUi" , e); } mHasTopUi = mHasTopUiChanged; } }
2.5.10 updateSleepIfNeededLocked ActivityManagerService.updateSleepIfNeededLocked
:更新睡眠状态!
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 void updateSleepIfNeededLocked () { if (mSleeping && !shouldSleepLocked()) { mSleeping = false ; startTimeTrackingFocusedActivityLocked(); mTopProcessState = ActivityManager.PROCESS_STATE_TOP; mStackSupervisor.comeOutOfSleepIfNeededLocked(); updateOomAdjLocked(); } else if (!mSleeping && shouldSleepLocked()) { mSleeping = true ; if (mCurAppTimeTracker != null ) { mCurAppTimeTracker.stop(); } mTopProcessState = ActivityManager.PROCESS_STATE_TOP_SLEEPING; mStackSupervisor.goingToSleepLocked(); updateOomAdjLocked(); checkExcessivePowerUsageLocked(false ); mHandler.removeMessages(CHECK_EXCESSIVE_WAKE_LOCKS_MSG); Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG); mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY); } }
更新所有服务的 oomAdj
!
2.6 总结 下面我用思维导图总结下,updateOomAdjLocked
的调用时机,当然了,随着版本的更替,代码逻辑和调用机制势必会发生变化,但是,已有的架构和逻辑依然具有很强的参考性 ,也能帮助我们在新的版本上快速建立代价整体结构的认识!!
3 oomAdj 算法分析 接下来,我们就要分析下 oomAdj
调度的核心算法了,我们从 updateOomAdjLocked
方法入手,我们先从最简单的一参函数看起:
3.1 [1]ActivityManagerS.updateOomAdjLocked - 更新指定进程 oomAdj 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 final boolean updateOomAdjLocked (ProcessRecord app) { final ActivityRecord TOP_ACT = resumedAppLocked(); final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null ; final boolean wasCached = app.cached; mAdjSeq++; final int cachedAdj = app.curRawAdj >= ProcessList.CACHED_APP_MIN_ADJ ? app.curRawAdj : ProcessList.UNKNOWN_ADJ; boolean success = updateOomAdjLocked(app, cachedAdj, TOP_APP, false , SystemClock.uptimeMillis()); if (wasCached != app.cached || app.curRawAdj == ProcessList.UNKNOWN_ADJ) { updateOomAdjLocked(); } return success; }
更新指定进程的 oomAdj
,被更新的进程的 app.adjSeq
值会等于 mAdjSeq
,这个我们后续再看!
对于 cachedAdj
的取值范围:
1 2 static final int UNKNOWN_ADJ = 1001 ;static final int CACHED_APP_MIN_ADJ = 900 ;
该方法主要功能:
执行五参 updateOomAdjLocked
,更新指定进程的 adj
;
当 app
经过更新 adj
操作后,其 cached
状态改变,或者 curRawAdj=UNKNOWN_ADJ
,则执行空参 updateOomAdjLocked
,更新所有进程的adj
;
继续来看:
3.1.1 ActivityManagerS.resumedAppLocked 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 private final ActivityRecord resumedAppLocked () { ActivityRecord act = mStackSupervisor.resumedAppLocked(); String pkg; int uid; if (act != null ) { pkg = act.packageName; uid = act.info.applicationInfo.uid; } else { pkg = null ; uid = -1 ; } if (uid != mCurResumedUid || (pkg != mCurResumedPackage && (pkg == null || !pkg.equals(mCurResumedPackage)))) { if (mCurResumedPackage != null ) { mBatteryStatsService.noteEvent(BatteryStats.HistoryItem.EVENT_TOP_FINISH, mCurResumedPackage, mCurResumedUid); } mCurResumedPackage = pkg; mCurResumedUid = uid; if (mCurResumedPackage != null ) { mBatteryStatsService.noteEvent(BatteryStats.HistoryItem.EVENT_TOP_START, mCurResumedPackage, mCurResumedUid); } } return act; }
3.1.1.1 ActivityStackSupervisor.resumedAppLocked 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ActivityRecord resumedAppLocked () { ActivityStack stack = mFocusedStack; if (stack == null ) { return null ; } ActivityRecord resumedActivity = stack.mResumedActivity; if (resumedActivity == null || resumedActivity.app == null ) { resumedActivity = stack.mPausingActivity; if (resumedActivity == null || resumedActivity.app == null ) { resumedActivity = stack.topRunningActivityLocked(); } } return resumedActivity; }
这里我们可以看到 resumedActivity
的获取逻辑!
首先会焦点 stack
获取 mResumedActivity
;
如果 resumedActivity
不存在,那就获取 mPausingActivity
;
如果 mPausingActivity
不存在,那就获取 top activity
!
3.3 [0]ActivityManagerS.updateOomAdjLocked - 更新 LRU 列表中的所有进程 刚才我们看了 updateOomAdjLocked
的一参和多参数方法,用来更新指定的进程的 adj
,到那时如果该进程的状态在 cache
和非 cache
之前切换了,那就会更新所有进程的 adj
状态!
这个是最核心的一个方法,方法体很长,我们耐心点来看!!
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 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 final void updateOomAdjLocked () { final ActivityRecord TOP_ACT = resumedAppLocked(); final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null ; final long now = SystemClock.uptimeMillis(); final long nowElapsed = SystemClock.elapsedRealtime(); final long oldTime = now - ProcessList.MAX_EMPTY_TIME; final int N = mLruProcesses.size(); if (false ) { RuntimeException e = new RuntimeException(); e.fillInStackTrace(); Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e); } for (int i=mActiveUids.size()-1 ; i>=0 ; i--) { final UidRecord uidRec = mActiveUids.valueAt(i); if (false && DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS, "Starting update of " + uidRec); uidRec.reset(); } mStackSupervisor.rankTaskLayersIfNeeded(); mAdjSeq++; mNewNumServiceProcs = 0 ; mNewNumAServiceProcs = 0 ; final int emptyProcessLimit; final int cachedProcessLimit; if (mProcessLimit <= 0 ) { emptyProcessLimit = cachedProcessLimit = 0 ; } else if (mProcessLimit == 1 ) { emptyProcessLimit = 1 ; cachedProcessLimit = 0 ; } else { emptyProcessLimit = ProcessList.computeEmptyProcessLimit(mProcessLimit); cachedProcessLimit = mProcessLimit - emptyProcessLimit; } int numSlots = (ProcessList.CACHED_APP_MAX_ADJ - ProcessList.CACHED_APP_MIN_ADJ + 1 ) / 2 ; int numEmptyProcs = N - mNumNonCachedProcs - mNumCachedHiddenProcs; if (numEmptyProcs > cachedProcessLimit) { numEmptyProcs = cachedProcessLimit; } int emptyFactor = numEmptyProcs / numSlots; if (emptyFactor < 1 ) emptyFactor = 1 ; int cachedFactor = (mNumCachedHiddenProcs > 0 ? mNumCachedHiddenProcs : 1 ) / numSlots; if (cachedFactor < 1 ) cachedFactor = 1 ; int stepCached = 0 ; int stepEmpty = 0 ; int numCached = 0 ; int numEmpty = 0 ; int numTrimming = 0 ; mNumNonCachedProcs = 0 ; mNumCachedHiddenProcs = 0 ; int curCachedAdj = ProcessList.CACHED_APP_MIN_ADJ; int nextCachedAdj = curCachedAdj + 1 ; int curEmptyAdj = ProcessList.CACHED_APP_MIN_ADJ; int nextEmptyAdj = curEmptyAdj + 2 ; for (int i=N-1 ; i>=0 ; i--) { ProcessRecord app = mLruProcesses.get(i); if (!app.killedByAm && app.thread != null ) { app.procStateChanged = false ; computeOomAdjLocked(app, ProcessList.UNKNOWN_ADJ, TOP_APP, true , now); if (app.curAdj >= ProcessList.UNKNOWN_ADJ) { switch (app.curProcState) { case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY: case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT: app.curRawAdj = curCachedAdj; app.curAdj = app.modifyRawOomAdj(curCachedAdj); if (DEBUG_LRU && false ) Slog.d(TAG_LRU, "Assigning activity LRU #" + i + " adj: " + app.curAdj + " (curCachedAdj=" + curCachedAdj + ")" ); if (curCachedAdj != nextCachedAdj) { stepCached++; if (stepCached >= cachedFactor) { stepCached = 0 ; curCachedAdj = nextCachedAdj; nextCachedAdj += 2 ; if (nextCachedAdj > ProcessList.CACHED_APP_MAX_ADJ) { nextCachedAdj = ProcessList.CACHED_APP_MAX_ADJ; } } } break ; default : app.curRawAdj = curEmptyAdj; app.curAdj = app.modifyRawOomAdj(curEmptyAdj); if (DEBUG_LRU && false ) Slog.d(TAG_LRU, "Assigning empty LRU #" + i + " adj: " + app.curAdj + " (curEmptyAdj=" + curEmptyAdj + ")" ); if (curEmptyAdj != nextEmptyAdj) { stepEmpty++; if (stepEmpty >= emptyFactor) { stepEmpty = 0 ; curEmptyAdj = nextEmptyAdj; nextEmptyAdj += 2 ; if (nextEmptyAdj > ProcessList.CACHED_APP_MAX_ADJ) { nextEmptyAdj = ProcessList.CACHED_APP_MAX_ADJ; } } } break ; } } applyOomAdjLocked(app, true , now, nowElapsed); switch (app.curProcState) { case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY: case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT: mNumCachedHiddenProcs++; numCached++; if (numCached > cachedProcessLimit) { app.kill("cached #" + numCached, true ); } break ; case ActivityManager.PROCESS_STATE_CACHED_EMPTY: if (numEmpty > ProcessList.TRIM_EMPTY_APPS && app.lastActivityTime < oldTime) { app.kill("empty for " + ((oldTime + ProcessList.MAX_EMPTY_TIME - app.lastActivityTime) / 1000 ) + "s" , true ); } else { numEmpty++; if (numEmpty > emptyProcessLimit) { app.kill("empty #" + numEmpty, true ); } } break ; default : mNumNonCachedProcs++; break ; } if (app.isolated && app.services.size() <= 0 ) { app.kill("isolated not needed" , true ); } else { final UidRecord uidRec = app.uidRecord; if (uidRec != null && uidRec.curProcState > app.curProcState) { uidRec.curProcState = app.curProcState; } } if (app.curProcState >= ActivityManager.PROCESS_STATE_HOME && !app.killedByAm) { numTrimming++; } } } mNumServiceProcs = mNewNumServiceProcs; final int numCachedAndEmpty = numCached + numEmpty; int memFactor; if (numCached <= ProcessList.TRIM_CACHED_APPS && numEmpty <= ProcessList.TRIM_EMPTY_APPS) { if (numCachedAndEmpty <= ProcessList.TRIM_CRITICAL_THRESHOLD) { memFactor = ProcessStats.ADJ_MEM_FACTOR_CRITICAL; } else if (numCachedAndEmpty <= ProcessList.TRIM_LOW_THRESHOLD) { memFactor = ProcessStats.ADJ_MEM_FACTOR_LOW; } else { memFactor = ProcessStats.ADJ_MEM_FACTOR_MODERATE; } } else { memFactor = ProcessStats.ADJ_MEM_FACTOR_NORMAL; } if (DEBUG_OOM_ADJ) Slog.d(TAG_OOM_ADJ, "oom: memFactor=" + memFactor + " last=" + mLastMemoryLevel + " allowLow=" + mAllowLowerMemLevel + " numProcs=" + mLruProcesses.size() + " last=" + mLastNumProcesses); if (memFactor > mLastMemoryLevel) { if (!mAllowLowerMemLevel || mLruProcesses.size() >= mLastNumProcesses) { memFactor = mLastMemoryLevel; if (DEBUG_OOM_ADJ) Slog.d(TAG_OOM_ADJ, "Keeping last mem factor!" ); } } if (memFactor != mLastMemoryLevel) { EventLogTags.writeAmMemFactor(memFactor, mLastMemoryLevel); } mLastMemoryLevel = memFactor; mLastNumProcesses = mLruProcesses.size(); boolean allChanged = mProcessStats.setMemFactorLocked(memFactor, !isSleepingLocked(), now); final int trackerMemFactor = mProcessStats.getMemFactorLocked(); if (memFactor != ProcessStats.ADJ_MEM_FACTOR_NORMAL) { if (mLowRamStartTime == 0 ) { mLowRamStartTime = now; } int step = 0 ; int fgTrimLevel; switch (memFactor) { case ProcessStats.ADJ_MEM_FACTOR_CRITICAL: fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL; break ; case ProcessStats.ADJ_MEM_FACTOR_LOW: fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW; break ; default : fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE; break ; } int factor = numTrimming / 3 ; int minFactor = 2 ; if (mHomeProcess != null ) minFactor++; if (mPreviousProcess != null ) minFactor++; if (factor < minFactor) factor = minFactor; int curLevel = ComponentCallbacks2.TRIM_MEMORY_COMPLETE; for (int i=N-1 ; i>=0 ; i--) { ProcessRecord app = mLruProcesses.get(i); if (allChanged || app.procStateChanged) { setProcessTrackerStateLocked(app, trackerMemFactor, now); app.procStateChanged = false ; } if (app.curProcState >= ActivityManager.PROCESS_STATE_HOME && !app.killedByAm) { if (app.trimMemoryLevel < curLevel && app.thread != null ) { try { if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ, "Trimming memory of " + app.processName + " to " + curLevel); app.thread.scheduleTrimMemory(curLevel); } catch (RemoteException e) { } if (false ) { if (curLevel >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE && app != mHomeProcess && app != mPreviousProcess) { mStackSupervisor.scheduleDestroyAllActivities(app, "trim" ); } } } app.trimMemoryLevel = curLevel; step++; if (step >= factor) { step = 0 ; switch (curLevel) { case ComponentCallbacks2.TRIM_MEMORY_COMPLETE: curLevel = ComponentCallbacks2.TRIM_MEMORY_MODERATE; break ; case ComponentCallbacks2.TRIM_MEMORY_MODERATE: curLevel = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND; break ; } } } else if (app.curProcState == ActivityManager.PROCESS_STATE_HEAVY_WEIGHT) { if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_BACKGROUND && app.thread != null ) { try { if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ, "Trimming memory of heavy-weight " + app.processName + " to " + ComponentCallbacks2.TRIM_MEMORY_BACKGROUND); app.thread.scheduleTrimMemory( ComponentCallbacks2.TRIM_MEMORY_BACKGROUND); } catch (RemoteException e) { } } app.trimMemoryLevel = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND; } else { if ((app.curProcState >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND || app.systemNoUi) && app.pendingUiClean) { final int level = ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN; if (app.trimMemoryLevel < level && app.thread != null ) { try { if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ, "Trimming memory of bg-ui " + app.processName + " to " + level); app.thread.scheduleTrimMemory(level); } catch (RemoteException e) { } } app.pendingUiClean = false ; } if (app.trimMemoryLevel < fgTrimLevel && app.thread != null ) { try { if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ, "Trimming memory of fg " + app.processName + " to " + fgTrimLevel); app.thread.scheduleTrimMemory(fgTrimLevel); } catch (RemoteException e) { } } app.trimMemoryLevel = fgTrimLevel; } } } else { if (mLowRamStartTime != 0 ) { mLowRamTimeSinceLastIdle += now - mLowRamStartTime; mLowRamStartTime = 0 ; } for (int i=N-1 ; i>=0 ; i--) { ProcessRecord app = mLruProcesses.get(i); if (allChanged || app.procStateChanged) { setProcessTrackerStateLocked(app, trackerMemFactor, now); app.procStateChanged = false ; } if ((app.curProcState >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND || app.systemNoUi) && app.pendingUiClean) { if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN && app.thread != null ) { try { if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ, "Trimming memory of ui hidden " + app.processName + " to " + ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN); app.thread.scheduleTrimMemory( ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN); } catch (RemoteException e) { } } app.pendingUiClean = false ; } app.trimMemoryLevel = 0 ; } } if (mAlwaysFinishActivities) { mStackSupervisor.scheduleDestroyAllActivities(null , "always-finish" ); } if (allChanged) { requestPssAllProcsLocked(now, false , mProcessStats.isMemFactorLowered()); } for (int i=mActiveUids.size()-1 ; i>=0 ; i--) { final UidRecord uidRec = mActiveUids.valueAt(i); int uidChange = UidRecord.CHANGE_PROCSTATE; if (uidRec.setProcState != uidRec.curProcState) { if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS, "Changes in " + uidRec + ": proc state from " + uidRec.setProcState + " to " + uidRec.curProcState); if (ActivityManager.isProcStateBackground(uidRec.curProcState)) { if (!ActivityManager.isProcStateBackground(uidRec.setProcState)) { uidRec.lastBackgroundTime = nowElapsed; if (!mHandler.hasMessages(IDLE_UIDS_MSG)) { mHandler.sendEmptyMessageDelayed(IDLE_UIDS_MSG, BACKGROUND_SETTLE_TIME); } } } else { if (uidRec.idle) { uidChange = UidRecord.CHANGE_ACTIVE; uidRec.idle = false ; } uidRec.lastBackgroundTime = 0 ; } uidRec.setProcState = uidRec.curProcState; enqueueUidChangeLocked(uidRec, -1 , uidChange); noteUidProcessState(uidRec.uid, uidRec.curProcState); } } if (mProcessStats.shouldWriteNowLocked(now)) { mHandler.post(new Runnable() { @Override public void run () { synchronized (ActivityManagerService.this ) { mProcessStats.writeStateAsyncLocked(); } } }); } if (DEBUG_OOM_ADJ) { final long duration = SystemClock.uptimeMillis() - now; if (false ) { Slog.d(TAG_OOM_ADJ, "Did OOM ADJ in " + duration + "ms" , new RuntimeException("here" ).fillInStackTrace()); } else { Slog.d(TAG_OOM_ADJ, "Did OOM ADJ in " + duration + "ms" ); } } }
3.2.1 变量总结 下面我们来总结,空参 updateOomAdjLocked
中遇到的一些变量:
3.2.2 过程总结 3.3 [5]ActivityManagerS.updateOomAdjLocked 最后,我们来看 5
参的 updateOomAdjLocked
方法更新指定进程的 oomAdj
,参数传递:
ProcessRecord app :要更新 oomAdj
的进程;
int cachedAdj :进程处于 cache
状态的 adj
值;
ProcessRecord TOP_APP :top activity
所在进程;
boolean doingAll :是否对所有进程都更新 adj
的值!
long now :更新的时间点!
1 2 3 4 5 6 7 8 9 10 11 12 13 private final boolean updateOomAdjLocked (ProcessRecord app, int cachedAdj, ProcessRecord TOP_APP, boolean doingAll, long now) { if (app.thread == null ) { return false ; } computeOomAdjLocked(app, cachedAdj, TOP_APP, doingAll, now); return applyOomAdjLocked(app, doingAll, now, SystemClock.elapsedRealtime()); }
我们看到,更新指定进程的 oomAdj
的会先调用 computeOomAdjLocked
计算 oomAdj
,在调用 applyOomAdjLocked
应用计算的 oomAdj
!!
3.3.1 ActivityManagerS.computeOomAdjLocked 该方法用于计算除了 cachedProcess
和 emptyProcess
进程以外的进程的 oom_adj
值!
该方法的判断分支很多,我们按照模块划分下:
3.3.1.1 已经更新/进程未启动的情况 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 private final int computeOomAdjLocked (ProcessRecord app, int cachedAdj, ProcessRecord TOP_APP, boolean doingAll, long now) { if (mAdjSeq == app.adjSeq) { return app.curRawAdj; } if (app.thread == null ) { app.adjSeq = mAdjSeq; app.curSchedGroup = ProcessList.SCHED_GROUP_BACKGROUND; app.curProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY; return (app.curAdj=app.curRawAdj=ProcessList.CACHED_APP_MAX_ADJ); } ... ... ... ...
3.3.1.2 系统进程 下面我们来看看系统进程的处理!
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 ... ... ... ... app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN; app.adjSource = null ; app.adjTarget = null ; app.empty = false ; app.cached = false ; final int activitiesSize = app.activities.size(); if (app.maxAdj <= ProcessList.FOREGROUND_APP_ADJ) { app.adjType = "fixed" ; app.adjSeq = mAdjSeq; app.curRawAdj = app.maxAdj; app.foregroundActivities = false ; app.curSchedGroup = ProcessList.SCHED_GROUP_DEFAULT; app.curProcState = ActivityManager.PROCESS_STATE_PERSISTENT; app.systemNoUi = true ; if (app == TOP_APP) { app.systemNoUi = false ; app.curSchedGroup = ProcessList.SCHED_GROUP_TOP_APP; app.adjType = "pers-top-activity" ; } else if (app.hasTopUi) { app.systemNoUi = false ; app.curSchedGroup = ProcessList.SCHED_GROUP_TOP_APP; app.adjType = "pers-top-ui" ; } else if (activitiesSize > 0 ) { for (int j = 0 ; j < activitiesSize; j++) { final ActivityRecord r = app.activities.get(j); if (r.visible) { app.systemNoUi = false ; } } } if (!app.systemNoUi) { app.curProcState = ActivityManager.PROCESS_STATE_PERSISTENT_UI; } return (app.curAdj = app.maxAdj); } ... ... ... ...
对于系统进程,其一定是要在前台的,这里首先判断了最大的 maxAdj
的取值!FOREGROUND_APP_ADJ
的取值为 0
,表示前台进程的 adj
!
maxAdj
在进程对象刚创建的时候,会被初始化为 UNKNOWN_ADJ
!
1 2 3 maxAdj = ProcessList.UNKNOWN_ADJ; curRawAdj = setRawAdj = ProcessList.INVALID_ADJ; curAdj = setAdj = verifiedAdj = ProcessList.INVALID_ADJ;
1、在设置系统进程 setSystemProcess
的时候,会被设置为如下值: 1 2 3 4 5 6 ProcessRecord app = newProcessRecordLocked(info, info.processName, false , 0 ); app.persistent = true ; app.pid = MY_PID; app.maxAdj = ProcessList.SYSTEM_ADJ; app.makeActive(mSystemThread.getApplicationThread(), mProcessStats);
2、在启动 persistent app
的时候,会调用 addAppLocked
方法,设置为如下值: 1 2 3 4 if ((info.flags & PERSISTENT_MASK) == PERSISTENT_MASK) { app.persistent = true ; app.maxAdj = ProcessList.PERSISTENT_PROC_ADJ; }
这两个值对应的 adj
优先级都高于 FOREGROUND_APP_ADJ
,都属于 persistent adj
,都会进入该分支 !
这一段的逻辑如下:
如果进程的 maxAdj
比 FOREGROUND_APP_ADJ
小,说明其是常驻进程或者系统进程,那么就做如下判断:
当前的 top activity
所在进程就是该进程,那么有:
1 2 3 4 app.systemNoUi = false ; app.curSchedGroup = ProcessList.SCHED_GROUP_TOP_APP; app.curProcState = ActivityManager.PROCESS_STATE_PERSISTENT_UI; app.foregroundActivities = false ;
当前进程不是 top process
,但是显示 top-level
级别的 ui
,那么有:
1 2 3 4 app.systemNoUi = false ; app.curSchedGroup = ProcessList.SCHED_GROUP_TOP_APP; app.curProcState = ActivityManager.PROCESS_STATE_PERSISTENT_UI; app.foregroundActivities = false ;
如果即不是top process
,也没有显示top-level ui
,那就要判断下内部的是否持有可见的activity
,如果有那么systemNoUi
为
false
,curProcState = ActivityManager.PROCESS_STATE_PERSISTENT_UI
;
1 2 3 4 app.systemNoUi = false ; / true app.curSchedGroup = ProcessList.SCHED_GROUP_TOP_APP; app.curProcState = ActivityManager.PROCESS_STATE_PERSISTENT_UI; / ActivityManager.PROCESS_STATE_PERSISTENT; app.foregroundActivities = false ;
对于 persistent
进程的情况,最后返回的是 app.curAdj = app.curRawAdj = app.maxAdj
!
3.3.1.3 前台进程 对于其他的进程来说,maxAdj
只会在初始化的时候被设置为 ProcessList.UNKNOWN_ADJ
; 显然,他们是需要进入下面的分支的,判断其是否属于前台进程 :
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 ... ... ... ... app.systemNoUi = false ; final int PROCESS_STATE_CUR_TOP = mTopProcessState; int adj;int schedGroup;int procState;boolean foregroundActivities = false ;BroadcastQueue queue; if (app == TOP_APP) { adj = ProcessList.FOREGROUND_APP_ADJ; schedGroup = ProcessList.SCHED_GROUP_TOP_APP; app.adjType = "top-activity" ; foregroundActivities = true ; procState = PROCESS_STATE_CUR_TOP; } else if (app.instrumentationClass != null ) { adj = ProcessList.FOREGROUND_APP_ADJ; schedGroup = ProcessList.SCHED_GROUP_DEFAULT; app.adjType = "instrumentation" ; procState = ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE; } else if ((queue = isReceivingBroadcast(app)) != null ) { adj = ProcessList.FOREGROUND_APP_ADJ; schedGroup = (queue == mFgBroadcastQueue) ? ProcessList.SCHED_GROUP_DEFAULT : ProcessList.SCHED_GROUP_BACKGROUND; app.adjType = "broadcast" ; procState = ActivityManager.PROCESS_STATE_RECEIVER; } else if (app.executingServices.size() > 0 ) { adj = ProcessList.FOREGROUND_APP_ADJ; schedGroup = app.execServicesFg ? ProcessList.SCHED_GROUP_DEFAULT : ProcessList.SCHED_GROUP_BACKGROUND; app.adjType = "exec-service" ; procState = ActivityManager.PROCESS_STATE_SERVICE; } else { schedGroup = ProcessList.SCHED_GROUP_BACKGROUND; adj = cachedAdj; procState = ActivityManager.PROCESS_STATE_CACHED_EMPTY; app.cached = true ; app.empty = true ; app.adjType = "cch-empty" ; } ... ... ... ...
首先来说一下:mTopProcessState
,其表示 top process
的状态,其默认取值为:1 int mTopProcessState = ActivityManager.PROCESS_STATE_TOP;
当我们的系统进入睡眠状态的时候,会更新其状态,具体的方法在 updateSleepIfNeededLocked
方法:
当系统不睡眠时候,设置 mTopProcessState = ActivityManager.PROCESS_STATE_TOP
;
当系统睡眠时候,设置 mTopProcessState = ActivityManager.PROCESS_STATE_TOP_SLEEPING
;
我们来看看,那些进程能归类于前台进程 :
1、当前进程是 top process
,进行如下处理:
1 2 3 4 5 adj = ProcessList.FOREGROUND_APP_ADJ; schedGroup = ProcessList.SCHED_GROUP_TOP_APP; foregroundActivities = true ; procState = PROCESS_STATE_CUR_TOP;
这里的 PROCESS_STATE_CUR_TOP
就是 mTopProcessState
,且 foregroundActivities
只有在该条件下才为 true
;
4、当前进程不是 top process
,但是其内部运行着 instrumentation
用于测试的话:
1 2 3 4 5 adj = ProcessList.FOREGROUND_APP_ADJ; schedGroup = ProcessList.SCHED_GROUP_DEFAULT; foregroundActivities = false ; procState = ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE;
继续来看:
3、当前进程不是 top process
,内部没有运行着 instrumentation
,但是其内部有正在接受处理广播的 BroadcastReceiver
的话:
1 2 3 4 5 adj = ProcessList.FOREGROUND_APP_ADJ; schedGroup = (queue == mFgBroadcastQueue) ? ProcessList.SCHED_GROUP_DEFAULT : ProcessList.SCHED_GROUP_BACKGROUND; foregroundActivities = false ; procState = ActivityManager.PROCESS_STATE_RECEIVER;
如果广播所在的队列是后台队列,所属的调度组为:SCHED_GROUP_BACKGROUND
,如果是前台,调度组为 SCHED_GROUP_DEFAULT
;
4、当前进程不是 top process
,内部没有运行着 instrumentation
,也没有接受处理广播的 BroadcastReceiver
,但是有正在执行的 Service
的话:
1 2 3 4 5 adj = ProcessList.FOREGROUND_APP_ADJ; schedGroup = app.execServicesFg ? ProcessList.SCHED_GROUP_DEFAULT : ProcessList.SCHED_GROUP_BACKGROUND; foregroundActivities = false ; procState = ActivityManager.PROCESS_STATE_SERVICE;
如果后台执行,所属的调度组为:SCHED_GROUP_BACKGROUND
,如果是前台,调度组为 SCHED_GROUP_DEFAULT
;
5、其他不属于以上的情况,说明其不是前台进程,有如下处理:
1 2 3 4 5 6 7 schedGroup = ProcessList.SCHED_GROUP_BACKGROUND; adj = cachedAdj; procState = ActivityManager.PROCESS_STATE_CACHED_EMPTY; foregroundActivities = false ; app.cached = true ; app.empty = true ;
对于这种情况,我们将其当作 cache
进程处理,后续会进行调整!
对于前台进程,其 oom_adj
均被赋值为 FOREGROUND_APP_ADJ
,即从 LowMemoryKiller
的角度来看,它们的重要性是一致的。 但这些进程的 procState
不同,于是从 ActivityManagerService
主动回收内存的角度来看,它们的重要性不同。
这里我们关注一个变量 foregroundActivities
,这里只有在 app == TOP_APP
的情况下为 true
,表示持有前台 activity
!
我们继续来看!
3.3.1.4 处理非前台 activity 所在进程 处理完了前台进程,接下来,处理非前台 activity
的情况,这里可以看作上面部分的延续,以下几种情况,会进入下面的逻辑,进一步的调整其 adj
!
如果该进程是前台进程,但不是 top process
,并且内部持有 activity
,其 adj
为 FOREGROUND_APP_ADJ
!
如果该进程不是前台进程,并且内部持有 activity
,其 adj
为 cachedAdj
!
这里的 top process
是 top 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 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 ... ... ... ... if (!foregroundActivities && activitiesSize > 0 ) { int minLayer = ProcessList.VISIBLE_APP_LAYER_MAX; for (int j = 0 ; j < activitiesSize; j++) { final ActivityRecord r = app.activities.get(j); if (r.app != app) { Log.e(TAG, "Found activity " + r + " in proc activity list using " + r.app + " instead of expected " + app); if (r.app == null || (r.app.uid == app.uid)) { r.app = app; } else { continue ; } } if (r.visible) { if (adj > ProcessList.VISIBLE_APP_ADJ) { adj = ProcessList.VISIBLE_APP_ADJ; app.adjType = "visible" ; } if (procState > PROCESS_STATE_CUR_TOP) { procState = PROCESS_STATE_CUR_TOP; } schedGroup = ProcessList.SCHED_GROUP_DEFAULT; app.cached = false ; app.empty = false ; foregroundActivities = true ; if (r.task != null && minLayer > 0 ) { final int layer = r.task.mLayerRank; if (layer >= 0 && minLayer > layer) { minLayer = layer; } } break ; } else if (r.state == ActivityState.PAUSING || r.state == ActivityState.PAUSED) { if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) { adj = ProcessList.PERCEPTIBLE_APP_ADJ; app.adjType = "pausing" ; } if (procState > PROCESS_STATE_CUR_TOP) { procState = PROCESS_STATE_CUR_TOP; } schedGroup = ProcessList.SCHED_GROUP_DEFAULT; app.cached = false ; app.empty = false ; foregroundActivities = true ; } else if (r.state == ActivityState.STOPPING) { if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) { adj = ProcessList.PERCEPTIBLE_APP_ADJ; app.adjType = "stopping" ; } if (!r.finishing) { if (procState > ActivityManager.PROCESS_STATE_LAST_ACTIVITY) { procState = ActivityManager.PROCESS_STATE_LAST_ACTIVITY; } } app.cached = false ; app.empty = false ; foregroundActivities = true ; } else { if (procState > ActivityManager.PROCESS_STATE_CACHED_ACTIVITY) { procState = ActivityManager.PROCESS_STATE_CACHED_ACTIVITY; app.adjType = "cch-act" ; } } } if (adj == ProcessList.VISIBLE_APP_ADJ) { adj += minLayer; } } ... ... ... ...
如果进程中没有 top activity
,但是内部运行着 activity
,还需要进入如下的判断:
1、如果 r.visible,表示内部有 activity 是可见的:
如果 adj > ProcessList.VISIBLE_APP_ADJ
:100 ,那就调整到 ProcessList.VISIBLE_APP_ADJ
;
如果 procState > PROCESS_STATE_CUR_TOP
,那就调整到 top process state
;
设置 foregroundActivities
为 true
;
然后结束处理 ;
然后继续处理其他 activity
4、其他情况:
如果 procState > ActivityManager.PROCESS_STATE_CACHED_ACTIVITY
: 14 ,那就设置 procState
为 PROCESS_STATE_CACHED_ACTIVITY
,然后继续处理其他 activity
!
5、最后,如果 adj
等于 VISIBLE_APP_ADJ:100
,在其之上加入 minLayer
调整,这样的话,最后的 adj
介于 100
和 200
之间!
我们得到:
对于 如果该进程是前台进程,但不是 top process
这种情况,其 adj
为 FOREGROUND_APP_ADJ:0
,不会做 adj
调整 ,但是其 procState
会发生变化 ,其变化依据是依赖于进程内部的 activity
的状态,根据【3.3.1.3】节我们知道,其 procState
的取值如下:1 2 3 4 procState = PROCESS_STATE_CUR_TOP; procState = ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE; procState = ActivityManager.PROCESS_STATE_RECEIVER; procState = ActivityManager.PROCESS_STATE_SERVICE;
可以看到,如果其内部持有非 top activity
,这里的调整,顶多会将其调整到 PROCESS_STATE_CUR_TOP
级别!
而对于非前台进程,在【3.3.1.3】节,会被置为如下的状态 :1 2 3 adj = cachedAdj; procState = ActivityManager.PROCESS_STATE_CACHED_EMPTY; foregroundActivities = false ;
可以看到,如果其内持有非 top activity
,会根据其 activity
的状态,其 adj
被调整为:1 2 3 4 5 ProcessList.VISIBLE_APP_ADJ ProcessList.PERCEPTIBLE_APP_ADJ
其 procState
被调整为:
1 2 3 4 5 6 7 8 ActivityManager.PROCESS_STATE_CUR_TOP ActivityManager.PROCESS_STATE_LAST_ACTIVITY ActivityManager.PROCESS_STATE_CACHED_ACTIVITY
我们接着来看!!
3.3.1.5 调整可感知进程 接下来处理可感知的进程,可以看到,能够进入该分支的需要满足下面某一个条件:
adj
的值大于 PERCEPTIBLE_APP_ADJ(200)
:
procState
的值大于 PROCESS_STATE_FOREGROUND_SERVICE(4)
:
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 ... ... ... ... // 见上面[3.1.2.1.4]! //【5】接下来,处理 adj 大于 PERCEPTIBLE_APP_ADJ(200) // 或者 procState 大于 PROCESS_STATE_FOREGROUND_SERVICE(4)的情况! if (adj > ProcessList.PERCEPTIBLE_APP_ADJ || procState > ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE) { if (app.foregroundServices) { //【5.1】如果该进程中有前台服务,那么用户是可以感知到这种进程的,所以是可见的! // 设置 adj 最低为 PERCEPTIBLE_APP_ADJ(200) // 设置 procState 最低为 PROCESS_STATE_FOREGROUND_SERVICE(4) adj = ProcessList.PERCEPTIBLE_APP_ADJ; procState = ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE; app.cached = false; app.adjType = "fg-service"; schedGroup = ProcessList.SCHED_GROUP_DEFAULT; } else if (app.forcingToForeground != null) { //【5.2】如果进程 forcingToForeground 不为 null,说明进程被强制设置到前台,同样可见! // 设置 adj 最低为 PERCEPTIBLE_APP_ADJ(200) // 设置 procState 最低为 PROCESS_STATE_IMPORTANT_FOREGROUND(6) adj = ProcessList.PERCEPTIBLE_APP_ADJ; procState = ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND; app.cached = false; app.adjType = "force-fg"; app.adjSource = app.forcingToForeground; schedGroup = ProcessList.SCHED_GROUP_DEFAULT; } } ... ... ... ... // 见下面[3.1.2.1.6]!
对于系统进程和前台进程 adj
的优先级均是高于 ProcessList.FOREGROUND_APP_ADJ
,所以第一个条件是不满足的!
我们来看看那些进程属于可感知的进程 :
app.foregroundServices
为 true
,表示服务被 start
后,调用了 startForeground
方法 此时我们来看看进程的属性:
1 2 3 adj = ProcessList.PERCEPTIBLE_APP_ADJ; procState = ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE; schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
在 Service
的被启动后,可以调用 startForeground
,让服务进程变为可感知的
app.foregroundServices
为 false
,但是 app.forcingToForeground != null
,表示调用了 setProcessForeground
方法 此时我们来看看进程的属性:
1 2 3 adj = ProcessList.PERCEPTIBLE_APP_ADJ; procState = ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND; schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
当我们在进程中调用了 setProcessForeground
方法后,该进程的 app.forcingToForeground
不为 null
,这样进程就会变为可感知的!!
注意
这里要重点看第二个条件:procState > ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE : 4
只要满足该条件的进程,也可以进入该分支,即使对于前台进程,其 adj == FOREGROUND_APP_ADJ
,也可能会进入该分支,比如:
不是 top process
,其内部没有非top activity
,但是其内部有正在接受处理广播的 BroadcastReceiver
,其 procState == PROCESS_STATE_RECEIVER:11
!
不是 top process
,其内部没有非top activity
,但是其内部有正在执行的 Service
,其 procState == PROCESS_STATE_SERVICE:10
!
如果其被显示设置成了前台的话,adj
和 procState
也会发生调整!
接着来看:
3.3.1.6 heavy weight 进程 下面是处理 heavy weight
类型的进程!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ... ... ... ... // 见上面[3.1.2.1.5] //【6】接下来,处理 heavy weight 进程! if (app == mHeavyWeightProcess) { //【6.1】设置进程 adj 最低为 HEAVY_WEIGHT_APP_ADJ if (adj > ProcessList.HEAVY_WEIGHT_APP_ADJ) { // 400 adj = ProcessList.HEAVY_WEIGHT_APP_ADJ; schedGroup = ProcessList.SCHED_GROUP_BACKGROUND; app.cached = false; app.adjType = "heavy"; } //【6.2】设置进程状态 procState 最低为 PROCESS_STATE_HEAVY_WEIGHT if (procState > ActivityManager.PROCESS_STATE_HEAVY_WEIGHT) { // 9 procState = ActivityManager.PROCESS_STATE_HEAVY_WEIGHT; } } ... ... ... ... // 见下面[3.1.2.1.7]
ams
通过 mHeavyWeightProcess
来保存系统中的 heavy weight
进程!
注意 ,对于 adj
的调整,只有 cacheAdj
或者 unKnowAdj
的情况下,如果满足条件,才会被调整为 HEAVY_WEIGHT_APP_ADJ
;
而对于 stateProc
,只要 procState > ActivityManager.PROCESS_STATE_HEAVY_WEIGHT:9
,并且该进程是 heavy weight
进程,那就会发生调整,这个可以参见【3.3.1.6】节!
接着来看:
3.3.1.7 home 进程 下面是处理 home
进程!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ... ... ... ... if (app == mHomeProcess) { if (adj > ProcessList.HOME_APP_ADJ) { adj = ProcessList.HOME_APP_ADJ; schedGroup = ProcessList.SCHED_GROUP_BACKGROUND; app.cached = false ; app.adjType = "home" ; } if (procState > ActivityManager.PROCESS_STATE_HOME) { procState = ActivityManager.PROCESS_STATE_HOME; } } ... ... ... ...
注意:
对于 home process
的情况,只有 cacheAdj
或者 unKnowAdj
的情况下,才会被调整 adj
和 procState
!
而对于 foreground process
,visible process
,perceptible process
和 heavy weight process
来说,他们的 adj
和 procState
都远远高于 home process
,所以是不会调整的!
接着来看:
3.3.1.8 持有 activity 的 previous 进程 下面是处理持有 activity
的 previous
进程:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 ... ... ... ... if (app == mPreviousProcess && app.activities.size() > 0 ) { if (adj > ProcessList.PREVIOUS_APP_ADJ) { adj = ProcessList.PREVIOUS_APP_ADJ; schedGroup = ProcessList.SCHED_GROUP_BACKGROUND; app.cached = false ; app.adjType = "previous" ; } if (procState > ActivityManager.PROCESS_STATE_LAST_ACTIVITY) { procState = ActivityManager.PROCESS_STATE_LAST_ACTIVITY; } } if (false ) Slog.i(TAG, "OOM " + app + ": initial adj=" + adj + " reason=" + app.adjType); ... ... ... ...
持有 activity
的 previous
进程 ,就是上一个显示 activity
的进程!
注意:
对于 previous process
的情况,只有 cacheAdj
或者 unKnowAdj
的情况下,才会被调整 adj
和 procState
!
而对于 foreground process
,visible process
,perceptible process
和 heavy weight process
, home process
来说,他们的 adj
和 procState
都远远高于 previous process
,所以是不会调整的!
接着来看:
3.3.1.9 处于 back-up 的进程 下面是处理处于 back-up
的进程:
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 ... ... ... ... app.adjSeq = mAdjSeq; app.curRawAdj = adj; app.hasStartedServices = false ; if (mBackupTarget != null && app == mBackupTarget.app) { if (adj > ProcessList.BACKUP_APP_ADJ) { if (DEBUG_BACKUP) Slog.v(TAG_BACKUP, "oom BACKUP_APP_ADJ for " + app); adj = ProcessList.BACKUP_APP_ADJ; if (procState > ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND) { procState = ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND; } app.adjType = "backup" ; app.cached = false ; } if (procState > ActivityManager.PROCESS_STATE_BACKUP) { procState = ActivityManager.PROCESS_STATE_BACKUP; } } ... ... ... ...
对于正在备份的进程有:
mBackupTarget != null && app == mBackupTarget.app
条件满足,那就做如下调整:
如果 adj > ProcessList.BACKUP_APP_ADJ
的话:1 2 adj = ProcessList.BACKUP_APP_ADJ; procState = ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND;
否则,只调整 procState
优先级最低为 PROCESS_STATE_BACKUP
注意:
正在备份的进程和前面遇到的进程并不冲突 ,比如,一个前台进程也有可能正在做备份操作,所以这里将其对应的调整放在了其他进程之后!
我们继续来看:
3.3.1.10 处理持有 services 的进程 下面是处理处于持有 services
的进程,当进程中持有 services
并且别其他进程绑定后,该进程的 adj
和 state
会发生变化!
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 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 ... ... ... ... boolean mayBeTop = false ; for (int is = app.services.size()-1 ; is >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND || procState > ActivityManager.PROCESS_STATE_TOP); is--) { ServiceRecord s = app.services.valueAt(is); if (s.startRequested) { app.hasStartedServices = true ; if (procState > ActivityManager.PROCESS_STATE_SERVICE) { procState = ActivityManager.PROCESS_STATE_SERVICE; } if (app.hasShownUi && app != mHomeProcess) { if (adj > ProcessList.SERVICE_ADJ) { app.adjType = "cch-started-ui-services" ; } } else { if (now < (s.lastActivity + ActiveServices.MAX_SERVICE_INACTIVITY)) { if (adj > ProcessList.SERVICE_ADJ) { adj = ProcessList.SERVICE_ADJ; app.adjType = "started-services" ; app.cached = false ; } } if (adj > ProcessList.SERVICE_ADJ) { app.adjType = "cch-started-services" ; } } } for (int conni = s.connections.size()-1 ; conni >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND || procState > ActivityManager.PROCESS_STATE_TOP); conni--) { ArrayList<ConnectionRecord> clist = s.connections.valueAt(conni); for (int i = 0 ; i < clist.size() && (adj > ProcessList.FOREGROUND_APP_ADJ || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND || procState > ActivityManager.PROCESS_STATE_TOP); i++) { ConnectionRecord cr = clist.get(i); if (cr.binding.client == app) { continue ; } if ((cr.flags & Context.BIND_WAIVE_PRIORITY) == 0 ) { ProcessRecord client = cr.binding.client; int clientAdj = computeOomAdjLocked(client, cachedAdj, TOP_APP, doingAll, now); int clientProcState = client.curProcState; if (clientProcState >= ActivityManager.PROCESS_STATE_CACHED_ACTIVITY) { clientProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY; } String adjType = null ; if ((cr.flags & Context.BIND_ALLOW_OOM_MANAGEMENT) != 0 ) { if (app.hasShownUi && app != mHomeProcess) { if (adj > clientAdj) { adjType = "cch-bound-ui-services" ; } app.cached = false ; clientAdj = adj; clientProcState = procState; } else { if (now >= (s.lastActivity + ActiveServices.MAX_SERVICE_INACTIVITY)) { if (adj > clientAdj) { adjType = "cch-bound-services" ; } clientAdj = adj; } } } if (adj > clientAdj) { if (app.hasShownUi && app != mHomeProcess && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) { adjType = "cch-bound-ui-services" ; } else { if ((cr.flags & (Context.BIND_ABOVE_CLIENT | Context.BIND_IMPORTANT)) != 0 ) { adj = clientAdj >= ProcessList.PERSISTENT_SERVICE_ADJ ? clientAdj : ProcessList.PERSISTENT_SERVICE_ADJ; } else if ((cr.flags & Context.BIND_NOT_VISIBLE) != 0 && clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ && adj > ProcessList.PERCEPTIBLE_APP_ADJ) { adj = ProcessList.PERCEPTIBLE_APP_ADJ; } else if (clientAdj >= ProcessList.PERCEPTIBLE_APP_ADJ) { adj = clientAdj; } else { if (adj > ProcessList.VISIBLE_APP_ADJ) { adj = Math.max(clientAdj, ProcessList.VISIBLE_APP_ADJ); } } if (!client.cached) { app.cached = false ; } adjType = "service" ; } } if ((cr.flags & Context.BIND_NOT_FOREGROUND) == 0 ) { if (client.curSchedGroup > schedGroup) { if ((cr.flags & Context.BIND_IMPORTANT) != 0 ) { schedGroup = client.curSchedGroup; } else { schedGroup = ProcessList.SCHED_GROUP_DEFAULT; } } if (clientProcState <= ActivityManager.PROCESS_STATE_TOP) { if (clientProcState == ActivityManager.PROCESS_STATE_TOP) { mayBeTop = true ; clientProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY; } else { if ((cr.flags & Context.BIND_FOREGROUND_SERVICE) != 0 ) { clientProcState = ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE; } else if (mWakefulness == PowerManagerInternal.WAKEFULNESS_AWAKE && (cr.flags & Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE) != 0 ) { clientProcState = ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE; } else { clientProcState = ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND; } } } } else { if (clientProcState < ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND) { clientProcState = ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND; } } if (procState > clientProcState) { procState = clientProcState; } if (procState < ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND && (cr.flags & Context.BIND_SHOWING_UI) != 0 ) { app.pendingUiClean = true ; } if (adjType != null ) { app.adjType = adjType; app.adjTypeCode = ActivityManager.RunningAppProcessInfo .REASON_SERVICE_IN_USE; app.adjSource = cr.binding.client; app.adjSourceProcState = clientProcState; app.adjTarget = s.name; } } if ((cr.flags & Context.BIND_TREAT_LIKE_ACTIVITY) != 0 ) { app.treatLikeActivity = true ; } final ActivityRecord a = cr.activity; if ((cr.flags&Context.BIND_ADJUST_WITH_ACTIVITY) != 0 ) { if (a != null && adj > ProcessList.FOREGROUND_APP_ADJ && (a.visible || a.state == ActivityState.RESUMED || a.state == ActivityState.PAUSING)) { adj = ProcessList.FOREGROUND_APP_ADJ; if ((cr.flags & Context.BIND_NOT_FOREGROUND) == 0 ) { if ((cr.flags & Context.BIND_IMPORTANT) != 0 ) { schedGroup = ProcessList.SCHED_GROUP_TOP_APP_BOUND; } else { schedGroup = ProcessList.SCHED_GROUP_DEFAULT; } } app.cached = false ; app.adjType = "service" ; app.adjTypeCode = ActivityManager.RunningAppProcessInfo .REASON_SERVICE_IN_USE; app.adjSource = a; app.adjSourceProcState = procState; app.adjTarget = s.name; } } } } } ... ... ... ...
1、进入条件:
`is >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND|| procState > ActivityManager.PROCESS_STATE_TOP`
第一个条件 :该进程中运行着服务!第二个条件 :该进程的 `adj > ProcessList.FOREGROUND_APP_ADJ`,只要优先级低于前台进程,都可以满足;
或者 `schedGroup == ProcessList.SCHED_GROUP_BACKGROUND`,只要调度组为后台类型,就可以满足;
或者 `procState > ActivityManager.PROCESS_STATE_TOP`,只要进程状态优先级低于 `top state`;
2、处理 Service
的逻辑如下 :
处理进程中通过 startService
启动的服务:
处理进程中被其他进程 bind
的服务,针对 bind
时候传入的 flags
进行不同的处理:
如果设置了 Context.BIND_WAIVE_PRIORITY
:
如果设置了 Context.BIND_TREAT_LIKE_ACTIVITY
:
如果设置了 Context.BIND_ADJUST_WITH_ACTIVITY
:
3.3.1.11 处理持有 providers 的进程 最后,来看看对持有 ContentProvider
进程的处理, 由于 ContentProvider
也是有 client
的,所以客户端的绑定也会影响其进程!
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 ... ... ... ... for (int provi = app.pubProviders.size()-1 ; provi >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND || procState > ActivityManager.PROCESS_STATE_TOP); provi--) { ContentProviderRecord cpr = app.pubProviders.valueAt(provi); for (int i = cpr.connections.size()-1 ; i >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND || procState > ActivityManager.PROCESS_STATE_TOP); i--) { ContentProviderConnection conn = cpr.connections.get(i); ProcessRecord client = conn.client; if (client == app) { continue ; } int clientAdj = computeOomAdjLocked(client, cachedAdj, TOP_APP, doingAll, now); int clientProcState = client.curProcState; if (clientProcState >= ActivityManager.PROCESS_STATE_CACHED_ACTIVITY) { clientProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY; } if (adj > clientAdj) { if (app.hasShownUi && app != mHomeProcess && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) { app.adjType = "cch-ui-provider" ; } else { adj = clientAdj > ProcessList.FOREGROUND_APP_ADJ ? clientAdj : ProcessList.FOREGROUND_APP_ADJ; app.adjType = "provider" ; } app.cached &= client.cached; app.adjTypeCode = ActivityManager.RunningAppProcessInfo .REASON_PROVIDER_IN_USE; app.adjSource = client; app.adjSourceProcState = clientProcState; app.adjTarget = cpr.name; } if (clientProcState <= ActivityManager.PROCESS_STATE_TOP) { if (clientProcState == ActivityManager.PROCESS_STATE_TOP) { mayBeTop = true ; clientProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY; } else { clientProcState = ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE; } } if (procState > clientProcState) { procState = clientProcState; } if (client.curSchedGroup > schedGroup) { schedGroup = ProcessList.SCHED_GROUP_DEFAULT; } } if (cpr.hasExternalProcessHandles()) { if (adj > ProcessList.FOREGROUND_APP_ADJ) { adj = ProcessList.FOREGROUND_APP_ADJ; schedGroup = ProcessList.SCHED_GROUP_DEFAULT; app.cached = false ; app.adjType = "provider" ; app.adjTarget = cpr.name; } if (procState > ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) { procState = ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND; } } } if (app.lastProviderTime > 0 && (app.lastProviderTime + CONTENT_PROVIDER_RETAIN_TIME) > now) { if (adj > ProcessList.PREVIOUS_APP_ADJ) { adj = ProcessList.PREVIOUS_APP_ADJ; schedGroup = ProcessList.SCHED_GROUP_BACKGROUND; app.cached = false ; app.adjType = "provider" ; } if (procState > ActivityManager.PROCESS_STATE_LAST_ACTIVITY) { procState = ActivityManager.PROCESS_STATE_LAST_ACTIVITY; } } ... ... ...
这个方法的流程很长,我们总结一下整个的计算过程:
整个的计算过程是从优先级高的 adj
开始,逐级向下遍历,逐渐的调整进程的 oomAdj
和 procState
的状态,知道找到一个合适的 oomAdj
和 procState
值!
3.3.1.12 最后调整阶段 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 ... ... ... if (mayBeTop && procState > ActivityManager.PROCESS_STATE_TOP) { switch (procState) { case ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND: case ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND: case ActivityManager.PROCESS_STATE_SERVICE: procState = ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE; break ; default : procState = ActivityManager.PROCESS_STATE_TOP; break ; } } if (procState >= ActivityManager.PROCESS_STATE_CACHED_EMPTY) { if (app.hasClientActivities) { procState = ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT; app.adjType = "cch-client-act" ; } else if (app.treatLikeActivity) { procState = ActivityManager.PROCESS_STATE_CACHED_ACTIVITY; app.adjType = "cch-as-act" ; } } if (adj == ProcessList.SERVICE_ADJ) { if (doingAll) { app.serviceb = mNewNumAServiceProcs > (mNumServiceProcs / 3 ); mNewNumServiceProcs++; if (!app.serviceb) { if (mLastMemoryLevel > ProcessStats.ADJ_MEM_FACTOR_NORMAL && app.lastPss >= mProcessList.getCachedRestoreThresholdKb()) { app.serviceHighRam = true ; app.serviceb = true ; } else { mNewNumAServiceProcs++; } } else { app.serviceHighRam = false ; } } if (app.serviceb) { adj = ProcessList.SERVICE_B_ADJ; } } app.curRawAdj = adj; if (adj > app.maxAdj) { adj = app.maxAdj; if (app.maxAdj <= ProcessList.PERCEPTIBLE_APP_ADJ) { schedGroup = ProcessList.SCHED_GROUP_DEFAULT; } } app.curAdj = app.modifyRawOomAdj(adj); app.curSchedGroup = schedGroup; app.curProcState = procState; app.foregroundActivities = foregroundActivities; return app.curRawAdj; }
这里调用了 modifyRawOomAdj
方法,根据 BIND_ABOVE_CLIENT
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 int modifyRawOomAdj (int adj) { if (hasAboveClient) { if (adj < ProcessList.FOREGROUND_APP_ADJ) { } else if (adj < ProcessList.VISIBLE_APP_ADJ) { adj = ProcessList.VISIBLE_APP_ADJ; } else if (adj < ProcessList.PERCEPTIBLE_APP_ADJ) { adj = ProcessList.PERCEPTIBLE_APP_ADJ; } else if (adj < ProcessList.CACHED_APP_MIN_ADJ) { adj = ProcessList.CACHED_APP_MIN_ADJ; } else if (adj < ProcessList.CACHED_APP_MAX_ADJ) { adj++; } } return adj; }
LRU list
中,从后往前数,前 1/3
的 service
进程就是 AService
进程,其余的就是 BService
进程;
3.3.2 ActivityManagerS.applyOomAdjLocked 最后,applyOomAdjLocked
方法用来应用计算出的 adj
!
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 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 private final boolean applyOomAdjLocked (ProcessRecord app, boolean doingAll, long now, long nowElapsed) { boolean success = true ; if (app.curRawAdj != app.setRawAdj) { app.setRawAdj = app.curRawAdj; } int changes = 0 ; if (app.curAdj != app.setAdj) { ProcessList.setOomAdj(app.pid, app.info.uid, app.curAdj); if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ, "Set " + app.pid + " " + app.processName + " adj " + app.curAdj + ": " + app.adjType); app.setAdj = app.curAdj; app.verifiedAdj = ProcessList.INVALID_ADJ; } if (app.setSchedGroup != app.curSchedGroup) { int oldSchedGroup = app.setSchedGroup; app.setSchedGroup = app.curSchedGroup; if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ, "Setting sched group of " + app.processName + " to " + app.curSchedGroup); if (app.waitingToKill != null && app.curReceiver == null && app.setSchedGroup == ProcessList.SCHED_GROUP_BACKGROUND) { app.kill(app.waitingToKill, true ); success = false ; } else { int processGroup; switch (app.curSchedGroup) { case ProcessList.SCHED_GROUP_BACKGROUND: processGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE; break ; case ProcessList.SCHED_GROUP_TOP_APP: case ProcessList.SCHED_GROUP_TOP_APP_BOUND: processGroup = Process.THREAD_GROUP_TOP_APP; break ; default : processGroup = Process.THREAD_GROUP_DEFAULT; break ; } long oldId = Binder.clearCallingIdentity(); try { Process.setProcessGroup(app.pid, processGroup); if (app.curSchedGroup == ProcessList.SCHED_GROUP_TOP_APP) { if (oldSchedGroup != ProcessList.SCHED_GROUP_TOP_APP) { if (mInVrMode && app.vrThreadTid != 0 ) { try { Process.setThreadScheduler(app.vrThreadTid, Process.SCHED_FIFO | Process.SCHED_RESET_ON_FORK, 1 ); } catch (IllegalArgumentException e) { } } if (mUseFifoUiScheduling) { app.savedPriority = Process.getThreadPriority(app.pid); try { Process.setThreadScheduler(app.pid, Process.SCHED_FIFO | Process.SCHED_RESET_ON_FORK, 1 ); } catch (IllegalArgumentException e) { } if (app.renderThreadTid != 0 ) { try { Process.setThreadScheduler(app.renderThreadTid, Process.SCHED_FIFO | Process.SCHED_RESET_ON_FORK, 1 ); } catch (IllegalArgumentException e) { } if (DEBUG_OOM_ADJ) { Slog.d("UI_FIFO" , "Set RenderThread (TID " + app.renderThreadTid + ") to FIFO" ); } } else { if (DEBUG_OOM_ADJ) { Slog.d("UI_FIFO" , "Not setting RenderThread TID" ); } } } else { Process.setThreadPriority(app.pid, -10 ); if (app.renderThreadTid != 0 ) { try { Process.setThreadPriority(app.renderThreadTid, -10 ); } catch (IllegalArgumentException e) { } } } } } else if (oldSchedGroup == ProcessList.SCHED_GROUP_TOP_APP && app.curSchedGroup != ProcessList.SCHED_GROUP_TOP_APP) { if (app.vrThreadTid != 0 ) { Process.setThreadScheduler(app.vrThreadTid, Process.SCHED_OTHER, 0 ); } if (mUseFifoUiScheduling) { Process.setThreadScheduler(app.pid, Process.SCHED_OTHER, 0 ); Process.setThreadPriority(app.pid, app.savedPriority); if (app.renderThreadTid != 0 ) { Process.setThreadScheduler(app.renderThreadTid, Process.SCHED_OTHER, 0 ); Process.setThreadPriority(app.renderThreadTid, -4 ); } } else { Process.setThreadPriority(app.pid, 0 ); if (app.renderThreadTid != 0 ) { Process.setThreadPriority(app.renderThreadTid, 0 ); } } } } catch (Exception e) { Slog.w(TAG, "Failed setting process group of " + app.pid + " to " + app.curSchedGroup); e.printStackTrace(); } finally { Binder.restoreCallingIdentity(oldId); } } } if (app.repForegroundActivities != app.foregroundActivities) { app.repForegroundActivities = app.foregroundActivities; changes |= ProcessChangeItem.CHANGE_ACTIVITIES; } if (app.repProcState != app.curProcState) { app.repProcState = app.curProcState; changes |= ProcessChangeItem.CHANGE_PROCESS_STATE; if (app.thread != null ) { try { if (false ) { Slog.i(TAG, "Sending new process state " + app.repProcState + " to " + app ); } app.thread.setProcessState(app.repProcState); } catch (RemoteException e) { } } } if (app.setProcState == ActivityManager.PROCESS_STATE_NONEXISTENT || ProcessList.procStatesDifferForMem(app.curProcState, app.setProcState)) { if (false && mTestPssMode && app.setProcState >= 0 && app.lastStateTime <= (now - 200 )) { long start = SystemClock.uptimeMillis(); long pss = Debug.getPss(app.pid, mTmpLong, null ); recordPssSampleLocked(app, app.curProcState, pss, mTmpLong[0 ], mTmpLong[1 ], now); mPendingPssProcesses.remove(app); Slog.i(TAG, "Recorded pss for " + app + " state " + app.setProcState + " to " + app.curProcState + ": " + (SystemClock.uptimeMillis()-start) + "ms" ); } app.lastStateTime = now; app.nextPssTime = ProcessList.computeNextPssTime(app.curProcState, true , mTestPssMode, isSleepingLocked(), now); if (DEBUG_PSS) Slog.d(TAG_PSS, "Process state change from " + ProcessList.makeProcStateString(app.setProcState) + " to " + ProcessList.makeProcStateString(app.curProcState) + " next pss in " + (app.nextPssTime-now) + ": " + app); } else { if (now > app.nextPssTime || (now > (app.lastPssTime + ProcessList.PSS_MAX_INTERVAL) && now > (app.lastStateTime + ProcessList.minTimeFromStateChange( mTestPssMode)))) { requestPssLocked(app, app.setProcState); app.nextPssTime = ProcessList.computeNextPssTime(app.curProcState, false , mTestPssMode, isSleepingLocked(), now); } else if (false && DEBUG_PSS) Slog.d(TAG_PSS, "Not requesting PSS of " + app + ": next=" + (app.nextPssTime-now)); } if (app.setProcState != app.curProcState) { if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ, "Proc state change of " + app.processName + " to " + app.curProcState); boolean setImportant = app.setProcState < ActivityManager.PROCESS_STATE_SERVICE; boolean curImportant = app.curProcState < ActivityManager.PROCESS_STATE_SERVICE; if (setImportant && !curImportant) { BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics(); synchronized (stats) { app.lastWakeTime = stats.getProcessWakeTime(app.info.uid, app.pid, nowElapsed); } app.lastCpuTime = app.curCpuTime; } maybeUpdateUsageStatsLocked(app, nowElapsed); app.setProcState = app.curProcState; if (app.setProcState >= ActivityManager.PROCESS_STATE_HOME) { app.notCachedSinceIdle = false ; } if (!doingAll) { setProcessTrackerStateLocked(app, mProcessStats.getMemFactorLocked(), now); } else { app.procStateChanged = true ; } } else if (app.reportedInteraction && (nowElapsed - app.interactionEventTime) > USAGE_STATS_INTERACTION_INTERVAL) { maybeUpdateUsageStatsLocked(app, nowElapsed); } if (changes != 0 ) { if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS, "Changes in " + app + ": " + changes); int i = mPendingProcessChanges.size()-1 ; ProcessChangeItem item = null ; while (i >= 0 ) { item = mPendingProcessChanges.get(i); if (item.pid == app.pid) { if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS, "Re-using existing item: " + item); break ; } i--; } if (i < 0 ) { final int NA = mAvailProcessChanges.size(); if (NA > 0 ) { item = mAvailProcessChanges.remove(NA-1 ); if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS, "Retrieving available item: " + item); } else { item = new ProcessChangeItem(); if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS, "Allocating new item: " + item); } item.changes = 0 ; item.pid = app.pid; item.uid = app.info.uid; if (mPendingProcessChanges.size() == 0 ) { if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS, "*** Enqueueing dispatch processes changed!" ); mUiHandler.obtainMessage(DISPATCH_PROCESSES_CHANGED_UI_MSG).sendToTarget(); } mPendingProcessChanges.add(item); } item.changes |= changes; item.processState = app.repProcState; item.foregroundActivities = app.repForegroundActivities; if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG_PROCESS_OBSERVERS, "Item " + Integer.toHexString(System.identityHashCode(item)) + " " + app.toShortString() + ": changes=" + item.changes + " procState=" + item.processState + " foreground=" + item.foregroundActivities + " type=" + app.adjType + " source=" + app.adjSource + " target=" + app.adjTarget); } return success; }
4 总结 首先,我们知道对于进程的优先级,Android
有 2
套分级机制:
ActivityManagerService
中对进程优先级的分级,以 PROCESS_STATE_
开头,定义在 ActivityManager.java
中;
LowMemoryKiller
通过 oomAdj
对进程优先级的分级;
//开始逆序处理LRU中的每一个进程
// 对应重要性大于home的进程而言,重要性越高,内存回收等级越低
// 对于重要性小于home的进程,排在LRU表越靠后,即越重要回收等级越高
// 这么安排的理由有两个:1、此时越不重要的进程,其中运行的组件越少,能够回收的内存不多,不需要高回收等级
// 2、越不重要的进程越有可能被LMK kill掉,没必要以高等级回收内存
Android 并不是 kill 掉所有 Empty 进程后,才 kill 后台进程。 它是将 CACHED_APP_MIN_ADJ 和 CACHED_APP_MAX_ADJ 之间的范围,分成 3 个 slot。
然后在每个 slot 中,分别分配一定量的后台进程和 Empty 进程。 在单独的 slot 中,会先 kill 掉 empty 进程,后 kill 掉后台进程。 只有当一个 slot 中的进程 kill 完毕后,才会 kill 掉下一个 slot 中的进程。 我们将从后面的代码中,得到对应的分析依据,这里先有个印象即可。
http://blog.csdn.net/Gaugamela/article/details/54176460
http://www.cnblogs.com/tiger-wang-ms/p/6445213.html