Android Gems — Android的LowMemoryKiller杀进程策略
2016-11-18 00:04
417 查看
Anroid的杀进程策略是基于kernel里的LowMemoryKiller模块,LMK的实现在这里不展开分析,大致的原理就是LMK注册了内核的shrinker(lowmem_shrinker),内核线程kswapd,在linux回收内存分页的时候,通过shrinker回调回来给LMK。LMK根据每个进程的oom_adj值,将大于某个阈值的进程都发送SIGKILL信号杀掉。oom_adj的阈值因内存情况不同而不同,具体的对应关系可以查看/sys/module/lowmemorykiller/parameters/adj和/sys/module/lowmemorykiller/parameters/minfree这两个文件。oom_adj的值从-17到16,值越小,代表越重要,越晚被杀,比如一个应用如果在前台的时候,oom_adj的值就会减到0。也就是说设为负值的那些应用,会比前台应用还晚被杀。于是,系统杀进程的策略就可以通过调整每个进程的oom_adj的值来实现。oom_adj的值有如下类:
// 不可见的Activity static final int CACHED_APP_MAX_ADJ = 15; static final int CACHED_APP_MIN_ADJ = 9; // 比较老的Service static final int SERVICE_B_ADJ = 8; // 上一个应用,这样在做任务切换,或者返回的时候,能够快速载入 static final int PREVIOUS_APP_ADJ = 7; // 桌面 App static final int HOME_APP_ADJ = 6; // Service static final int SERVICE_ADJ = 5; // 重量级应用,早期版本可以在manifest里加cantSaveState来声明,新版已经注释了,目前没看到哪里可以设置 static final int HEAVY_WEIGHT_APP_ADJ = 4; // 备份代理应用,manifest里Application标签里可以声明backAgent static final int BACKUP_APP_ADJ = 3; // 可感知的App,比如有Pause状态的Activity,Stopping状态的Activity,被一个可见的进程BindService的进程等 static final int PERCEPTIBLE_APP_ADJ = 2; // 前台可见的Activity, static final int VISIBLE_APP_ADJ = 1; // 前台App,包括Top App,Instrumentation Test App,正在接收broadcast的App,正在执行的Service等 static final int FOREGROUND_APP_ADJ = 0; // 被Persist App BindService的进程 static final int PERSISTENT_SERVICE_ADJ = -11; // 声明了persist的进程 static final int PERSISTENT_PROC_ADJ = -12; // 系统进程,比如system server static final int SYSTEM_ADJ = -16; // 不被系统管的Native进程,比如/system/bin下运行的那些服务(surfaceflinger etc) static final int NATIVE_ADJ = -17;oom_adj的值受很多因素影响:应用是否有activity,activity是否可见,是否有service,service是否被bind的其他进程的oom_adj等等。在Framework里oom_adj的调整主要由ActivityManagerService这个类负责,任何可能会影响到进程oom_adj的值的情况,就会调用updateOomAdjLocked来更新各进程的oom_adj值,比如:
1,Activity切换
2,Service start/stop/bind
3,Broadcast分发处理
updateOomAdjLocked会遍历当前进程列表,对每个进程ProcessRecord都调用computeOomAdjLocked来重新计算oom_adj,最后applyOomAdjLocked来使oom_adj生效。
我们看看updateOomAdjLocked的实现:
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 oldTime = now - ProcessList.MAX_EMPTY_TIME; final int N = mLruProcesses.size(); ...... ...... for (int i=N-1; i>=0; i--) { ProcessRecord app = mLruProcesses.get(i); // 找到最早的一次service活动时间 if (mEnableBServicePropagation && app.serviceb && (app.curAdj == ProcessList.SERVICE_B_ADJ)) { numBServices++; for (int s = app.services.size() - 1; s >= 0; s--) { ServiceRecord sr = app.services.valueAt(s); if (DEBUG_OOM_ADJ) Slog.d(TAG,"app.processName = " + app.processName + " serviceb = " + app.serviceb + " s = " + s + " sr.lastActivity = " + sr.lastActivity + " packageName = " + sr.packageName + " processName = " + sr.processName); if (SystemClock.uptimeMillis() - sr.lastActivity < mMinBServiceAgingTime) { if (DEBUG_OOM_ADJ) { Slog.d(TAG,"Not aged enough!!!"); } continue; } if (serviceLastActivity == 0) { serviceLastActivity = sr.lastActivity; selectedAppRecord = app; } else if (sr.lastActivity < serviceLastActivity) { serviceLastActivity = sr.lastActivity; selectedAppRecord = app; } } } if (DEBUG_OOM_ADJ && selectedAppRecord != null) Slog.d(TAG, "Identified app.processName = " + selectedAppRecord.processName + " app.pid = " + selectedAppRecord.pid); if (!app.killedByAm && app.thread != null) { app.procStateChanged = false; // 重新计算进程app的oom_adj computeOomAdjLocked(app, ProcessList.UNKNOWN_ADJ, TOP_APP, true, now); // If we haven't yet assigned the final cached adj // to the process, do that now. // 如果没找到对应的oom_adj,那么根据app的进程状态,如果有activity存在,那么oom_adj设为curCachedAdj, // 否则就是empty进程,讲oom_adj设为curEmptyAdj if (app.curAdj >= ProcessList.UNKNOWN_ADJ) { switch (app.curProcState) { case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY: case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT: // This process is a cached process holding activities... // assign it the next cached value for that type, and then // step that cached level. 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: // For everything else, assign next empty cached process // level and bump that up. Note that this means that // long-running services that have dropped down to the // cached level will be treated as empty (since their process // state is still as a service), which is what we want. 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使新的oom_adj生效 applyOomAdjLocked(app, true, now); // Count the number of process types. switch (app.curProcState) { case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY: case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT: mNumCachedHiddenProcs++; numCached++; // 计算Cached进程个数,超过cachedProcessLimit即直接kill if (numCached > cachedProcessLimit) { app.kill("cached #" + numCached, true); } break; case ActivityManager.PROCESS_STATE_CACHED_EMPTY: // 计算empty进程个数,超过上限即kill 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; } ...... ...... } } // 在低内存的情况下,把过老的service的oom_adj的值调大到CACHED_APP_MAX_ADJ,以便可以被优先杀死 if ((numBServices > mBServiceAppThreshold) && (true == mAllowLowerMemLevel) && (selectedAppRecord != null)) { ProcessList.setOomAdj(selectedAppRecord.pid, selectedAppRecord.info.uid, ProcessList.CACHED_APP_MAX_ADJ); selectedAppRecord.setAdj = selectedAppRecord.curAdj; if (DEBUG_OOM_ADJ) Slog.d(TAG,"app.processName = " + selectedAppRecord.processName + " app.pid = " + selectedAppRecord.pid + " is moved to higher adj"); } // finish所有后台的activity,这个有系统开关可以控制,Settings.Global.ALWAYS_FINISH_ACTIVITIES,也就是开发者选项里的“不保留活动”, // 也可以通过ActivityManagerNative的setAlwaysFinish来设置,这需要声明权限android.Manifest.permission.SET_ALWAYS_FINISH if (mAlwaysFinishActivities) { // Need to do this on its own message because the stack may not // be in a consistent state at this point. mStackSupervisor.scheduleDestroyAllActivities(null, "always-finish"); } ...... ...... }系统将进程分三类:
一, empty process,没有service,也没有activity,空进程没有执行逻辑,可以优先被杀,empty process有数量限制,超过限制之后就马上被kill。 二, cached process,只有不可见的activity,这类进程优先级比empty高些,但也同样可以被杀,用户不会有太明显的感知,表现就是返回到他的activity之后,
进程被重新被创建,Activity也会重新onCreate。
empty和cached进程的上限是ProcessList.MAX_CACHED_APPS=32个,而empty的上限是ProcessList.computeEmptyProcessLimit(ProcessList.MAX_CACHED_APPS),默认是16。
三,其他是第三类,包括有前台可见的Activity的进程,有前台Service的进程等。
三类进程数之和就等于LruProcesses队列的大小。
private final int computeOomAdjLocked(ProcessRecord app, int cachedAdj, ProcessRecord TOP_APP, boolean doingAll, long now) { if (mAdjSeq == app.adjSeq) { // This adjustment has already been computed. return app.curRawAdj; } if (app.thread == null) { app.adjSeq = mAdjSeq; app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE; app.curProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY; return (app.curAdj=app.curRawAdj=ProcessList.CACHED_APP_MAX_ADJ); } app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN; app.adjSource = null; app.adjTarget = null; app.empty = false; app.cached = false; final int activitiesSize = app.activities.size(); // app最大的adj和前台app的adj一样,说明是系统进程,adj就设为maxAdj if (app.maxAdj <= ProcessList.FOREGROUND_APP_ADJ) { // The max adjustment doesn't allow this app to be anything // below foreground, so it is not worth doing work for it. app.adjType = "fixed"; app.adjSeq = mAdjSeq; app.curRawAdj = app.maxAdj; app.foregroundActivities = false; app.curSchedGroup = Process.THREAD_GROUP_DEFAULT; app.curProcState = ActivityManager.PROCESS_STATE_PERSISTENT; // System processes can do UI, and when they do we want to have // them trim their memory after the user leaves the UI. To // facilitate this, here we need to determine whether or not it // is currently showing UI. app.systemNoUi = true; if (app == TOP_APP) { app.systemNoUi = false; } 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); } app.systemNoUi = false; final int PROCESS_STATE_TOP = mTopProcessState; // Determine the importance of the process, starting with most // important to least, and assign an appropriate OOM adjustment. int adj; int schedGroup; int procState; boolean foregroundActivities = false; BroadcastQueue queue; if (app == TOP_APP) { // App正在系统顶层,adj设为FOREGROUND_APP_ADJ // The last app on the list is the foreground app. adj = ProcessList.FOREGROUND_APP_ADJ; schedGroup = Process.THREAD_GROUP_DEFAULT; app.adjType = "top-activity"; foregroundActivities = true; procState = PROCESS_STATE_TOP; if(app == mHomeProcess) { mHomeKilled = false; mHomeProcessName = mHomeProcess.processName; } } else if (app.instrumentationClass != null) { // App正执行Instrumentation,adj设为FOREGROUND_APP_ADJ // Don't want to kill running instrumentation. adj = ProcessList.FOREGROUND_APP_ADJ; schedGroup = Process.THREAD_GROUP_DEFAULT; app.adjType = "instrumentation"; procState = ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE; } else if ((queue = isReceivingBroadcast(app)) != null) { // App正在接收broadcast,adj设为FOREGROUND_APP_ADJ // An app that is currently receiving a broadcast also // counts as being in the foreground for OOM killer purposes. // It's placed in a sched group based on the nature of the // broadcast as reflected by which queue it's active in. adj = ProcessList.FOREGROUND_APP_ADJ; schedGroup = (queue == mFgBroadcastQueue) ? Process.THREAD_GROUP_DEFAULT : Process.THREAD_GROUP_BG_NONINTERACTIVE; app.adjType = "broadcast"; procState = ActivityManager.PROCESS_STATE_RECEIVER; } else if (app.executingServices.size() > 0) { // App的Service正在执行,adj设为FOREGROUND_APP_ADJ // An app that is currently executing a service callback also // counts as being in the foreground. adj = ProcessList.FOREGROUND_APP_ADJ; schedGroup = app.execServicesFg ? Process.THREAD_GROUP_DEFAULT : Process.THREAD_GROUP_BG_NONINTERACTIVE; app.adjType = "exec-service"; procState = ActivityManager.PROCESS_STATE_SERVICE; //Slog.i(TAG, "EXEC " + (app.execServicesFg ? "FG" : "BG") + ": " + app); } else { // As far as we know the process is empty. We may change our mind later. schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE; // At this point we don't actually know the adjustment. Use the cached adj // value that the caller wants us to. adj = cachedAdj; procState = ActivityManager.PROCESS_STATE_CACHED_EMPTY; // 初始状态cached和empty都设为true,根据进程的执行状态再改 app.cached = true; app.empty = true; app.adjType = "cch-empty"; // 桌面App,既不是empty也不是cached,adj设为PERSISTENT_PROC_ADJ if (mHomeKilled && app.processName.equals(mHomeProcessName)) { adj = ProcessList.PERSISTENT_PROC_ADJ; schedGroup = Process.THREAD_GROUP_DEFAULT; app.cached = false; app.empty = false; app.adjType = "top-activity"; } } // Examine all activities if not already foreground. if (!foregroundActivities && activitiesSize > 0) { // 遍历非前台的activity for (int j = 0; j < activitiesSize; j++) { final ActivityRecord r = app.activities.get(j); if (r.app != app) { Slog.w(TAG, "Wtf, activity " + r + " in proc activity list not using proc " + app + "?!? Using " + r.app + " instead."); continue; } if (r.visible) { // 可见的Activity,如果Activity不在最顶层,而且被顶层完全挡住的时候visible状态会被设为false, // 如果是可见的,那么adj设为VISIBLE_APP_ADJ,cached和empty也设为false // App has a visible activity; only upgrade adjustment. if (adj > ProcessList.VISIBLE_APP_ADJ) { adj = ProcessList.VISIBLE_APP_ADJ; app.adjType = "visible"; } if (procState > PROCESS_STATE_TOP) { procState = PROCESS_STATE_TOP; } schedGroup = Process.THREAD_GROUP_DEFAULT; app.cached = false; app.empty = false; foregroundActivities = true; break; } else if (r.state == ActivityState.PAUSING || r.state == ActivityState.PAUSED) { // Pause状态的Activity,adj设为PERCEPTIBLE_APP_ADJ,cached和empty也设为false if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) { adj = ProcessList.PERCEPTIBLE_APP_ADJ; app.adjType = "pausing"; } if (procState > PROCESS_STATE_TOP) { procState = PROCESS_STATE_TOP; } schedGroup = Process.THREAD_GROUP_DEFAULT; app.cached = false; app.empty = false; foregroundActivities = true; } else if (r.state == ActivityState.STOPPING) { // Stopping状态的app,adj设为PERCEPTIBLE_APP_ADJ,cached和empty也设为false if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) { adj = ProcessList.PERCEPTIBLE_APP_ADJ; app.adjType = "stopping"; } // For the process state, we will at this point consider the // process to be cached. It will be cached either as an activity // or empty depending on whether the activity is finishing. We do // this so that we can treat the process as cached for purposes of // memory trimming (determing current memory level, trim command to // send to process) since there can be an arbitrary number of stopping // processes and they should soon all go into the cached state. 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 { // 进这个分支说明进程有不可见的Activity,adj会设为CACHED_APP_MIN_ADJ和CACHED_APP_MAX_ADJ之间的数 if (procState > ActivityManager.PROCESS_STATE_CACHED_ACTIVITY) { procState = ActivityManager.PROCESS_STATE_CACHED_ACTIVITY; app.adjType = "cch-act"; } } } } if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) { // 如果有前台的Service,adj设为PERCEPTIBLE_APP_ADJ,可通过ActivityManagerNative将Service设为foreground if (app.foregroundServices) { // The user is aware of this app, so make it visible. adj = ProcessList.PERCEPTIBLE_APP_ADJ; procState = ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE; app.cached = false; app.adjType = "fg-service"; schedGroup = Process.THREAD_GROUP_DEFAULT; } else if (app.forcingToForeground != null) { // The user is aware of this app, so make it visible. adj = ProcessList.PERCEPTIBLE_APP_ADJ; procState = ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND; app.cached = false; app.adjType = "force-fg"; app.adjSource = app.forcingToForeground; schedGroup = Process.THREAD_GROUP_DEFAULT; } } if (app == mHeavyWeightProcess) { if (adj > ProcessList.HEAVY_WEIGHT_APP_ADJ) { // We don't want to kill the current heavy-weight process. adj = ProcessList.HEAVY_WEIGHT_APP_ADJ; schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE; app.cached = false; app.adjType = "heavy"; } if (procState > ActivityManager.PROCESS_STATE_HEAVY_WEIGHT) { procState = ActivityManager.PROCESS_STATE_HEAVY_WEIGHT; } } if (app == mHomeProcess) { // 如果桌面App,adj设为HOME_APP_ADJ if (adj > ProcessList.HOME_APP_ADJ) { // This process is hosting what we currently consider to be the // home app, so we don't want to let it go into the background. adj = ProcessList.HOME_APP_ADJ; schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE; app.cached = false; app.adjType = "home"; } if (procState > ActivityManager.PROCESS_STATE_HOME) { procState = ActivityManager.PROCESS_STATE_HOME; } } // 如果是刚刚切换出去的App,adj设为PREVIOUS_APP_ADJ if (app == mPreviousProcess && app.activities.size() > 0) { if (adj > ProcessList.PREVIOUS_APP_ADJ) { // This was the previous process that showed UI to the user. // We want to try to keep it around more aggressively, to give // a good experience around switching between two apps. adj = ProcessList.PREVIOUS_APP_ADJ; schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE; 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); // By default, we use the computed adjustment. It may be changed if // there are applications dependent on our services or providers, but // this gives us a baseline and makes sure we don't get into an // infinite recursion. app.adjSeq = mAdjSeq; app.curRawAdj = adj; app.hasStartedServices = false; // Backup App,adj设为BACKUP_APP_ADJ if (mBackupTarget != null && app == mBackupTarget.app) { // If possible we want to avoid killing apps while they're being backed up 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; } } boolean mayBeTop = false; // 如果App有Service,adj设为SERVICE_ADJ for (int is = app.services.size()-1; is >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE || 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 this process has shown some UI, let it immediately // go to the LRU list because it may be pretty heavy with // UI stuff. We'll tag it with a label just to help // debug and understand what is going on. if (adj > ProcessList.SERVICE_ADJ) { app.adjType = "cch-started-ui-services"; } } else { if (now < (s.lastActivity + ActiveServices.MAX_SERVICE_INACTIVITY)) { // This service has seen some activity within // recent memory, so we will keep its process ahead // of the background processes. if (adj > ProcessList.SERVICE_ADJ) { adj = ProcessList.SERVICE_ADJ; app.adjType = "started-services"; app.cached = false; } } // If we have let the service slide into the background // state, still have some text describing what it is doing // even though the service no longer has an impact. if (adj > ProcessList.SERVICE_ADJ) { app.adjType = "cch-started-services"; } } } // 如果App有Service,那么需要检查是否有外部的App在Bind它,如果一个高优先级的App,bind了你的Service,那么你的优先级也会同样有提升 for (int conni = s.connections.size()-1; conni >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE || 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 == Process.THREAD_GROUP_BG_NONINTERACTIVE || procState > ActivityManager.PROCESS_STATE_TOP); i++) { // XXX should compute this based on the max of // all connected clients. ConnectionRecord cr = clist.get(i); if (cr.binding.client == app) { // Binding to ourself is not interesting. continue; } // 只有bind的时候不加BIND_WAIVE_PRIORITY这个flag才会影响对方的adj 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) { // If the other app is cached for any reason, for purposes here // we are going to consider it empty. The specific cached state // doesn't propagate except under certain conditions. clientProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY; } String adjType = null; if ((cr.flags&Context.BIND_ALLOW_OOM_MANAGEMENT) != 0) { // Not doing bind OOM management, so treat // this guy more like a started service. if (app.hasShownUi && app != mHomeProcess) { // If this process has shown some UI, let it immediately // go to the LRU list because it may be pretty heavy with // UI stuff. We'll tag it with a label just to help // debug and understand what is going on. if (adj > clientAdj) { adjType = "cch-bound-ui-services"; } app.cached = false; clientAdj = adj; clientProcState = procState; } else { if (now >= (s.lastActivity + ActiveServices.MAX_SERVICE_INACTIVITY)) { // This service has not seen activity within // recent memory, so allow it to drop to the // LRU list if there is no other reason to keep // it around. We'll also tag it with a label just // to help debug and undertand what is going on. if (adj > clientAdj) { adjType = "cch-bound-services"; } clientAdj = adj; } } } if (adj > clientAdj) { // If this process has recently shown UI, and // the process that is binding to it is less // important than being visible, then we don't // care about the binding as much as we care // about letting this process get into the LRU // list to be killed and restarted if needed for // memory. 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) { // 如果Client Bind的时候加了BIND_ABOVE_CLIENT和BIND_IMPORTANT,那么讲client的adj值给Service,最低不小于PERSISTENT_SERVICE_ADJ 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) { // 如果Client Bind的时候加了BIND_NOT_VISIBLE,并且client的adj比PERCEPTIBLE_APP_ADJ小的时候,将PERCEPTIBLE_APP_ADJ给adj adj = ProcessList.PERCEPTIBLE_APP_ADJ; } else if (clientAdj > ProcessList.VISIBLE_APP_ADJ) { // 把Client的adj给adj,因为adj是> clientAdj的,所以Service的adj还是得到了提升 adj = clientAdj; } else { // 这里client的adj是要小于等于VISIBLE_APP_ADJ的,所以adj将会提升至VISIBLE_APP_ADJ if (adj > ProcessList.VISIBLE_APP_ADJ) { adj = ProcessList.VISIBLE_APP_ADJ; } } if (!client.cached) { app.cached = false; } adjType = "service"; } } ...... ...... ...... } // ContentProvider的连接也同样会影响到app的adj for (int provi = app.pubProviders.size()-1; provi >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE || 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 == Process.THREAD_GROUP_BG_NONINTERACTIVE || procState > ActivityManager.PROCESS_STATE_TOP); i--) { ContentProviderConnection conn = cpr.connections.get(i); ProcessRecord client = conn.client; if (client == app) { // Being our own client is not interesting. continue; } int clientAdj = computeOomAdjLocked(client, cachedAdj, TOP_APP, doingAll, now); int clientProcState = client.curProcState; if (clientProcState >= ActivityManager.PROCESS_STATE_CACHED_ACTIVITY) { // If the other app is cached for any reason, for purposes here // we are going to consider it empty. 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 the provider has external (non-framework) process // dependencies, ensure that its adjustment is at least // FOREGROUND_APP_ADJ. if (cpr.hasExternalProcessHandles()) { if (adj > ProcessList.FOREGROUND_APP_ADJ) { adj = ProcessList.FOREGROUND_APP_ADJ; schedGroup = Process.THREAD_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; } } } ...... ...... app.curAdj = app.modifyRawOomAdj(adj); app.curSchedGroup = schedGroup; app.curProcState = procState; app.foregroundActivities = foregroundActivities; return app.curRawAdj; }computeOomAdjLocked计算完oom_adj之后,就调用applyOomAdjLocked使之生效,applyOomAdjLocked比较简单,调用ProcessList的setOomAdj,通过LocalSocket连接到
lmkd,通过进程间通信写入。作者简介:田力,网易彩票Android端创始人,小米视频创始人,现任roobo技术经理、视频云技术总监欢迎关注微信公众号 磨剑石,定期推送技术心得以及源码分析等文章,谢谢
相关文章推荐
- Android进程优先级architecture : low memory killer (/system/core/lmkd/lmkd.c)
- Android内存管理篇 - 从updateOomAdjLocked看lowmemorykiller之外的Android进程回收机制
- 【android】进程优先级(Framework设置优先级,LowMemoryKiller查杀)
- android java进程管理(八)之lowmemorykiller
- Android low memory killer 详解
- Android内存管理机制之一:lowmemory killer
- Android内核详解之Low memory killer
- Android Low memory killer(下)
- Android对Linux内核的增强:Low Memory Killer(低内存管理)
- Android Low Memory Killer
- Android分析之LowMemoryKiller
- Android low memory killer 详解
- Android内核详解之Low memory killer
- Android学习之lowmemorykiller driver
- (转)Android内存管理机制之一:lowmemory killer
- Android分析之LowMemoryKiller
- Android分析之LowMemoryKiller
- Android Low memory killer
- Android内存管理机制之一:low memory killer
- Android内存分配分配机制 Low Memory Killer