Lowmemorykiller笔记

来源:互联网 发布:中国工控网软件下载 编辑:程序博客网 时间:2024/05/16 22:29
从zygote孵化出来的进程都会记录在ActivityManagerService.mLruProcesses列表中,由ActivityManagerService进行统一管理,ActivityManagerService核心业务之一便是时时更新进程的状态,根据状态计算出进程对应的OomAdj值,这个值会传递到kernel中去,kernel有个低内存回收机制,在内存达到一定阀值时会触发清理OomAdj值高的进程,这边是Lowmemorykiller工作原理。

第一部分:进程OomAdj值的设置



这个流程中,ActivityManagerService会计算出进程的OomAdj值,然后通过Lmkd这个native进程来将OomAdj值分别写入对应进程的oom_score_adj节点去。可以通过cat /proc/%pid/oom_score_adj来查看每个进程的OomAdj值。

注意:

①OomAdj值越小表示优先级越高,越不容易被kill。

②ActivityManagerService中为进程设定的OomAdj值取值范围为-16~16,设定到oom_score_adj节点中的值是经过 OomAdj*1000/17 公式计算出来的。

③native进程OomAdj值默认为-17,也就是说native进程oom_score_adj节点中值必是-1000.


第二部分:核心调用lowmem_shrink()

这个函数主要根据当前剩余内存与lowmem_minfree来评判当前内存已经达到哪个阀值以下(每个阀值都对应一个lowmem_adj值),进而得出一个lowmem_adj基准值(只有OomAdj值大于这个lowmem_adj基准值的进程才可能被杀)。

代码在/drivers/staging/android/lowmemorykiller.c

[html] view plaincopy在CODE上查看代码片派生到我的代码片
  1. static int lowmem_shrink(struct shrinker *s, struct shrink_control *sc)  
  2. {  
  3.     struct task_struct *tsk;  
  4.     struct task_struct *selected = NULL;  
  5.     int rem = 0;  
  6.     int tasksize;  
  7.     int i;  
  8.     int min_score_adj = OOM_SCORE_ADJ_MAX + 1;  
  9.     int selected_tasksize = 0;  
  10.     int selected_oom_score_adj;  
  11.     int array_size = ARRAY_SIZE(lowmem_adj);  
  12.     int other_free = global_page_state(NR_FREE_PAGES) - totalreserve_pages;  
  13.     int other_file = global_page_state(NR_FILE_PAGES) -  
  14.                         global_page_state(NR_SHMEM);  
  15.   
  16.     if (lowmem_adj_size < array_size)  
  17.         array_size = lowmem_adj_size;  
  18.     if (lowmem_minfree_size < array_size)  
  19.         array_size = lowmem_minfree_size;  
  20.     for (i = 0; i < array_size; i++) {             //根据当前内存与lowmem_minfree数组进行评判,找到lowmem_adj基准值赋给min_score_adj;  
  21.         if (other_free < lowmem_minfree[i] &&  
  22.             other_file < lowmem_minfree[i]) {  
  23.             min_score_adj = lowmem_adj[i];  
  24.             break;  
  25.         }  
  26.     }  
  27.     if (sc->nr_to_scan > 0)  
  28.         lowmem_print(3, "lowmem_shrink %lu, %x, ofree %d %d, ma %d\n",  
  29.                 sc->nr_to_scan, sc->gfp_mask, other_free,  
  30.                 other_file, min_score_adj);  
  31.     rem = global_page_state(NR_ACTIVE_ANON) +  
  32.         global_page_state(NR_ACTIVE_FILE) +  
  33.         global_page_state(NR_INACTIVE_ANON) +  
  34.         global_page_state(NR_INACTIVE_FILE);  
  35.     if (sc->nr_to_scan <= 0 || min_score_adj == OOM_SCORE_ADJ_MAX + 1) {  
  36.         lowmem_print(5, "lowmem_shrink %lu, %x, return %d\n",  
  37.                  sc->nr_to_scan, sc->gfp_mask, rem);  
  38.         return rem;  
  39.     }  
  40.     selected_oom_score_adj = min_score_adj;  
  41.   
  42.     rcu_read_lock();  
  43.     for_each_process(tsk) {     //该for循环找出oom_score_adj值最大的进程作为目标进程(将被kill),如果最大oom_score_adj值有多个进程,那么选取rss值最大的进程为目标进程;  
  44.         struct task_struct *p;  
  45.         int oom_score_adj;  
  46.   
  47.         if (tsk->flags & PF_KTHREAD)  
  48.             continue;  
  49.   
  50.         p = find_lock_task_mm(tsk);  
  51.         if (!p)  
  52.             continue;  
  53.   
  54.         if (test_tsk_thread_flag(p, TIF_MEMDIE) &&  
  55.             time_before_eq(jiffies, lowmem_deathpending_timeout)) {  
  56.             task_unlock(p);  
  57.             rcu_read_unlock();  
  58.             return 0;  
  59.         }  
  60.         oom_score_adj = p->signal->oom_score_adj;  
  61.         if (oom_score_adj < min_score_adj) {  
  62.             task_unlock(p);  
  63.             continue;  
  64.         }  
  65.         tasksize = get_mm_rss(p->mm);  
  66.         task_unlock(p);  
  67.         if (tasksize <= 0)  
  68.             continue;  
  69.         if (selected) {  
  70.             if (oom_score_adj < selected_oom_score_adj)  
  71.                 continue;  
  72.             if (oom_score_adj == selected_oom_score_adj &&  
  73.                 tasksize <= selected_tasksize)  
  74.                 continue;  
  75.         }  
  76.         selected = p;  
  77.         selected_tasksize = tasksize;  
  78.         selected_oom_score_adj = oom_score_adj;  
  79.         lowmem_print(2, "select %d (%s), adj %d, size %d, to kill\n",  
  80.                  p->pid, p->comm, oom_score_adj, tasksize);  
  81.     }  
  82.     if (selected) {                        //前面for循环找到一个目标进程,那么便调用send_sig()干掉它。  
  83.         lowmem_print(1, "send sigkill to %d (%s), adj %d, size %d\n",  
  84.                  selected->pid, selected->comm,  
  85.                  selected_oom_score_adj, selected_tasksize);  
  86.         lowmem_deathpending_timeout = jiffies + HZ;  
  87.         send_sig(SIGKILL, selected, 0);  
  88.         set_tsk_thread_flag(selected, TIF_MEMDIE);  
  89.         rem -selected_tasksize;  
  90.     }  
  91.     lowmem_print(4, "lowmem_shrink %lu, %x, return %d\n",  
  92.              sc->nr_to_scan, sc->gfp_mask, rem);  
  93.     rcu_read_unlock();  
  94.     return rem;  
  95. }  
该函数的逻辑很简单,就是kill掉Oomadj值大的进程来回收内存。

注意:由于native进程的Oomadj值为-17,SystemServer进程的Oomadj值为-16,毫无疑问native进程不会被Lowmemorykiller干掉。


第三部分:Oomadj的计算

OomAdj的计算主要在computeOomAdjLocked()函数中完成。

[html] view plaincopy在CODE上查看代码片派生到我的代码片
  1.     private final int computeOomAdjLocked(ProcessRecord app, int cachedAdj, ProcessRecord TOP_APP,  
  2.             boolean doingAll, long now) {  
  3.         if (mAdjSeq == app.adjSeq) {  
  4.             // This adjustment has already been computed.  
  5.             return app.curRawAdj;  
  6.         }  
  7.   
  8.         if (app.thread == null) {  
  9.             app.adjSeq = mAdjSeq;  
  10.             app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;  
  11.             app.curProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;  
  12.             return (app.curAdj=app.curRawAdj=ProcessList.CACHED_APP_MAX_ADJ);  
  13.         }  
  14.   
  15.         app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;  
  16.         app.adjSource = null;  
  17.         app.adjTarget = null;  
  18.         app.empty = false;  
  19.         app.cached = false;  
  20.   
  21.         final int activitiesSize = app.activities.size();  
  22.   
  23.         if (app.maxAdj <= ProcessList.FOREGROUND_APP_ADJ) {      //如果是常驻进程、SystemServer进程,那么该条件是满足的,对于一般进程maxAdj值为UNKNOWN_ADJ  
  24.             // The max adjustment doesn't allow this app to be anything  
  25.             // below foreground, so it is not worth doing work for it.  
  26.             app.adjType = "fixed";  
  27.             app.adjSeq = mAdjSeq;  
  28.             app.curRawAdj = app.maxAdj;  
  29.             app.foregroundActivities = false;  
  30.             app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;  
  31.             app.curProcState = ActivityManager.PROCESS_STATE_PERSISTENT;  
  32.             // System processes can do UI, and when they do we want to have  
  33.             // them trim their memory after the user leaves the UI.  To  
  34.             // facilitate this, here we need to determine whether or not it  
  35.             // is currently showing UI.  
  36.             app.systemNoUi = true;  
  37.             if (app == TOP_APP) {  
  38.                 app.systemNoUi = false;  
  39.             } else if (activitiesSize > 0) {  
  40.                 for (int j = 0; j < activitiesSize; j++) {  
  41.                     final ActivityRecord r = app.activities.get(j);  
  42.                     if (r.visible) {  
  43.                         app.systemNoUi = false;  
  44.                     }  
  45.                 }  
  46.             }  
  47.             if (!app.systemNoUi) {                                      //如果进程是当前resume activity的进程,或者有可见的activity,那么把curProcState修改成PROCESS_STATE_PERSISTENT_UI  
  48.                 app.curProcState = ActivityManager.PROCESS_STATE_PERSISTENT_UI;  
  49.             }  
  50.             return (app.curAdj=app.maxAdj);  
  51.         }  
  52.   
  53.         app.systemNoUi = false;         /*以下逻辑是计算普通进程的Oomadj值,主要计算进程的adj、schedGroup、procState、foregroundActivities四个变量*/  
  54.         // Determine the importance of the process, starting with most  
  55.         // important to least, and assign an appropriate OOM adjustment.  
  56.         int adj;  
  57.         int schedGroup;  
  58.         int procState;  
  59.         boolean foregroundActivities = false;  
  60.         BroadcastQueue queue;  
  61.         if (app == TOP_APP) {           //这大段if else逻辑里面的条件是权重最高的,如果满足这些条件之一,那么几个状态值基本就确定下来了,如果都不满足,那么最后一个else会给一个初值;  
  62.             // The last app on the list is the foreground app.  
  63.             adj = ProcessList.FOREGROUND_APP_ADJ;  
  64.             schedGroup = Process.THREAD_GROUP_DEFAULT;  
  65.             app.adjType = "top-activity";  
  66.             foregroundActivities = true;  
  67.             procState = ActivityManager.PROCESS_STATE_TOP;  
  68.         } else if (app.instrumentationClass != null) {  
  69.             // Don't want to kill running instrumentation.  
  70.             adj = ProcessList.FOREGROUND_APP_ADJ;  
  71.             schedGroup = Process.THREAD_GROUP_DEFAULT;  
  72.             app.adjType = "instrumentation";  
  73.             procState = ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;  
  74.         } else if ((queue = isReceivingBroadcast(app)) != null) {  
  75.             // An app that is currently receiving a broadcast also  
  76.             // counts as being in the foreground for OOM killer purposes.  
  77.             // It's placed in a sched group based on the nature of the  
  78.             // broadcast as reflected by which queue it's active in.  
  79.             adj = ProcessList.FOREGROUND_APP_ADJ;  
  80.             schedGroup = (queue == mFgBroadcastQueue)  
  81.                     ? Process.THREAD_GROUP_DEFAULT : Process.THREAD_GROUP_BG_NONINTERACTIVE;  
  82.             app.adjType = "broadcast";  
  83.             procState = ActivityManager.PROCESS_STATE_RECEIVER;  
  84.         } else if (app.executingServices.size() > 0) {  
  85.             // An app that is currently executing a service callback also  
  86.             // counts as being in the foreground.  
  87.             adj = ProcessList.FOREGROUND_APP_ADJ;  
  88.             schedGroup = app.execServicesFg ?  
  89.                     Process.THREAD_GROUP_DEFAULT : Process.THREAD_GROUP_BG_NONINTERACTIVE;  
  90.             app.adjType = "exec-service";  
  91.             procState = ActivityManager.PROCESS_STATE_SERVICE;  
  92.             //Slog.i(TAG, "EXEC " + (app.execServicesFg ? "FG" : "BG") + ": " + app);  
  93.         } else {  
  94.             // As far as we know the process is empty.  We may change our mind later.  
  95.             schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;  
  96.             // At this point we don't actually know the adjustment.  Use the cached adj  
  97.             // value that the caller wants us to.  
  98.             adj = cachedAdj;                    //cachedAdj值为进程的上一次计算出来的Oomadj值或UNKNOWN_ADJ,我们把它假设成UNKNOWN_ADJ好了。  
  99.             procState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;  
  100.             app.cached = true;  
  101.             app.empty = true;  
  102.             app.adjType = "cch-empty";  
  103.         }  
  104.   
  105.         // Examine all activities if not already foreground.  
  106.         if (!foregroundActivities && activitiesSize > 0) {           //这段逻辑主要遍历进程中的所有activity,根据这些activity的状态来更新adj、procState等值;  
  107.             for (int j = 0; j < activitiesSize; j++) {  
  108.                 final ActivityRecord r = app.activities.get(j);  
  109.                 if (r.app != app) {  
  110.                     Slog.w(TAG, "Wtf, activity " + r + " in proc activity list not using proc "  
  111.                             + app + "?!?");  
  112.                     continue;  
  113.                 }  
  114.                 if (r.visible) {  
  115.                     // App has a visible activity; only upgrade adjustment.  
  116.                     if (adj > ProcessList.VISIBLE_APP_ADJ) {  
  117.                         adj = ProcessList.VISIBLE_APP_ADJ;  
  118.                         app.adjType = "visible";  
  119.                     }  
  120.                     if (procState > ActivityManager.PROCESS_STATE_TOP) {  
  121.                         procState = ActivityManager.PROCESS_STATE_TOP;  
  122.                     }  
  123.                     schedGroup = Process.THREAD_GROUP_DEFAULT;  
  124.                     app.cached = false;  
  125.                     app.empty = false;  
  126.                     foregroundActivities = true;  
  127.                     break;  
  128.                 } else if (r.state == ActivityState.PAUSING || r.state == ActivityState.PAUSED) {  
  129.                     if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {  
  130.                         adj = ProcessList.PERCEPTIBLE_APP_ADJ;  
  131.                         app.adjType = "pausing";  
  132.                     }  
  133.                     if (procState > ActivityManager.PROCESS_STATE_TOP) {  
  134.                         procState = ActivityManager.PROCESS_STATE_TOP;  
  135.                     }  
  136.                     schedGroup = Process.THREAD_GROUP_DEFAULT;  
  137.                     app.cached = false;  
  138.                     app.empty = false;  
  139.                     foregroundActivities = true;  
  140.                 } else if (r.state == ActivityState.STOPPING) {  
  141.                     if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {  
  142.                         adj = ProcessList.PERCEPTIBLE_APP_ADJ;  
  143.                         app.adjType = "stopping";  
  144.                     }  
  145.                     // For the process state, we will at this point consider the  
  146.                     // process to be cached.  It will be cached either as an activity  
  147.                     // or empty depending on whether the activity is finishing.  We do  
  148.                     // this so that we can treat the process as cached for purposes of  
  149.                     // memory trimming (determing current memory level, trim command to  
  150.                     // send to process) since there can be an arbitrary number of stopping  
  151.                     // processes and they should soon all go into the cached state.  
  152.                     if (!r.finishing) {  
  153.                         if (procState > ActivityManager.PROCESS_STATE_LAST_ACTIVITY) {  
  154.                             procState = ActivityManager.PROCESS_STATE_LAST_ACTIVITY;  
  155.                         }  
  156.                     }  
  157.                     app.cached = false;  
  158.                     app.empty = false;  
  159.                     foregroundActivities = true;  
  160.                 } else {  
  161.                     if (procState > ActivityManager.PROCESS_STATE_CACHED_ACTIVITY) {  
  162.                         procState = ActivityManager.PROCESS_STATE_CACHED_ACTIVITY;  
  163.                         app.adjType = "cch-act";  
  164.                     }  
  165.                 }  
  166.             }  
  167.         }  
  168.   
  169.         if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {     //根据进程是否有前台后台service来更新adj、procState等值,当然如果以前算出来的adj<=PERCEPTIBLE_APP_ADJ,那就没必要考虑前台后台service了;  
  170.             if (app.foregroundServices) {  
  171.                 // The user is aware of this app, so make it visible.  
  172.                 adj = ProcessList.PERCEPTIBLE_APP_ADJ;  
  173.                 procState = ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;  
  174.                 app.cached = false;  
  175.                 app.adjType = "fg-service";  
  176.                 schedGroup = Process.THREAD_GROUP_DEFAULT;  
  177.             } else if (app.forcingToForeground != null) {  
  178.                 // The user is aware of this app, so make it visible.  
  179.                 adj = ProcessList.PERCEPTIBLE_APP_ADJ;  
  180.                 procState = ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;  
  181.                 app.cached = false;  
  182.                 app.adjType = "force-fg";  
  183.                 app.adjSource = app.forcingToForeground;  
  184.                 schedGroup = Process.THREAD_GROUP_DEFAULT;  
  185.             }  
  186.         }  
  187.   
  188.         if (app == mHeavyWeightProcess) {       //判断进程是否mHeavyWeightProcess进程  
  189.             if (adj > ProcessList.HEAVY_WEIGHT_APP_ADJ) {  
  190.                 // We don't want to kill the current heavy-weight process.  
  191.                 adj = ProcessList.HEAVY_WEIGHT_APP_ADJ;  
  192.                 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;  
  193.                 app.cached = false;  
  194.                 app.adjType = "heavy";  
  195.             }  
  196.             if (procState > ActivityManager.PROCESS_STATE_HEAVY_WEIGHT) {  
  197.                 procState = ActivityManager.PROCESS_STATE_HEAVY_WEIGHT;  
  198.             }  
  199.         }  
  200.   
  201.         if (app == mHomeProcess) {              //判断是否launcher进程;  
  202.             if (adj > ProcessList.HOME_APP_ADJ) {  
  203.                 // This process is hosting what we currently consider to be the  
  204.                 // home app, so we don't want to let it go into the background.  
  205.                 adj = ProcessList.HOME_APP_ADJ;  
  206.                 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;  
  207.                 app.cached = false;  
  208.                 app.adjType = "home";  
  209.             }  
  210.             if (procState > ActivityManager.PROCESS_STATE_HOME) {  
  211.                 procState = ActivityManager.PROCESS_STATE_HOME;  
  212.             }  
  213.         }  
  214.   
  215.         if (app == mPreviousProcess && app.activities.size() > 0) {<span style="white-space:pre">  </span>//mPreviousProcess代表last Stoped activity所在的进程  
  216.             if (adj > ProcessList.PREVIOUS_APP_ADJ) {  
  217.                 // This was the previous process that showed UI to the user.  
  218.                 // We want to try to keep it around more aggressively, to give  
  219.                 // a good experience around switching between two apps.  
  220.                 adj = ProcessList.PREVIOUS_APP_ADJ;  
  221.                 schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;  
  222.                 app.cached = false;  
  223.                 app.adjType = "previous";  
  224.             }  
  225.             if (procState > ActivityManager.PROCESS_STATE_LAST_ACTIVITY) {  
  226.                 procState = ActivityManager.PROCESS_STATE_LAST_ACTIVITY;  
  227.             }  
  228.         }  
  229. <span style="white-space:pre">    </span>/*至此已经初步设置了Oomadj值,下面的逻辑就是根据service、provider来微调<span style="font-family: Arial, Helvetica, sans-serif;">Oomadj值</span>*/  
  230.         if (false) Slog.i(TAG, "OOM " + app + ": initial adj=" + adj  
  231.                 + " reason=" + app.adjType);  
  232.   
  233.         // By default, we use the computed adjustment.  It may be changed if  
  234.         // there are applications dependent on our services or providers, but  
  235.         // this gives us a baseline and makes sure we don't get into an  
  236.         // infinite recursion.  
  237.         app.adjSeq = mAdjSeq;  
  238.         app.curRawAdj = adj;  
  239.         app.hasStartedServices = false;  
  240.   
  241.         if (mBackupTarget != null && app == mBackupTarget.app) {<span style="white-space:pre">        </span>//判断进程是否正在备份  
  242.             // If possible we want to avoid killing apps while they're being backed up  
  243.             if (adj > ProcessList.BACKUP_APP_ADJ) {  
  244.                 if (DEBUG_BACKUP) Slog.v(TAG, "oom BACKUP_APP_ADJ for " + app);  
  245.                 adj = ProcessList.BACKUP_APP_ADJ;  
  246.                 if (procState > ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND) {  
  247.                     procState = ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND;  
  248.                 }  
  249.                 app.adjType = "backup";  
  250.                 app.cached = false;  
  251.             }  
  252.             if (procState > ActivityManager.PROCESS_STATE_BACKUP) {  
  253.                 procState = ActivityManager.PROCESS_STATE_BACKUP;  
  254.             }  
  255.         }  
[html] view plaincopy在CODE上查看代码片派生到我的代码片
  1. boolean mayBeTop = false;  
  2.   
  3. for (int is = app.services.size()-1;  
  4.         is >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ  
  5.                 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE  
  6.                 || procState > ActivityManager.PROCESS_STATE_TOP);  
  7.         is--) {  
  8.     ServiceRecord s = app.services.valueAt(is);  
  9.     if (s.startRequested) {<span style="white-space:pre">                 </span>//<span style="font-family: Arial, Helvetica, sans-serif;">startRequested=true表示service已经启动了,没有被stop;</span>  
  10.         app.hasStartedServices = true;  
  11.         if (procState > ActivityManager.PROCESS_STATE_SERVICE) {  
  12.             procState = ActivityManager.PROCESS_STATE_SERVICE;  
  13.         }  
  14.         if (app.hasShownUi && app != mHomeProcess) {  
  15.             // If this process has shown some UI, let it immediately  
  16.             // go to the LRU list because it may be pretty heavy with  
  17.             // UI stuff.  We'll tag it with a label just to help  
  18.             // debug and understand what is going on.  
  19.             if (adj > ProcessList.SERVICE_ADJ) {  
  20.                 app.adjType = "cch-started-ui-services";  
  21.             }  
  22.         } else {  
  23.             if (now < (s.lastActivity + ActiveServices.MAX_SERVICE_INACTIVITY)) {  
  24.                 // This service has seen some activity within  
  25.                 // recent memory, so we will keep its process ahead  
  26.                 // of the background processes.  
  27.                 if (adj > ProcessList.SERVICE_ADJ) {  
  28.                     adj = ProcessList.SERVICE_ADJ;  
  29.                     app.adjType = "started-services";  
  30.                     app.cached = false;  
  31.                 }  
  32.             }  
  33.             // If we have let the service slide into the background  
  34.             // state, still have some text describing what it is doing  
  35.             // even though the service no longer has an impact.  
  36.             if (adj > ProcessList.SERVICE_ADJ) {  
  37.                 app.adjType = "cch-started-services";  
  38.             }  
  39.         }  
  40.     }  
  41.     for (int conni = s.connections.size()-1;  
  42.             conni >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ  
  43.                     || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE  
  44.                     || procState > ActivityManager.PROCESS_STATE_TOP);  
  45.             conni--) {  
  46.         ArrayList<ConnectionRecord> clist = s.connections.valueAt(conni);  
  47.         for (int i = 0;  
  48.                 i < clist.size() && (adj > ProcessList.FOREGROUND_APP_ADJ  
  49.                         || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE  
  50.                         || procState > ActivityManager.PROCESS_STATE_TOP);  
  51.                 i++) {  
  52.             // XXX should compute this based on the max of  
  53.             // all connected clients.  
  54.             ConnectionRecord cr = clist.get(i);  
  55.             if (cr.binding.client == app) {  
  56.                 // Binding to ourself is not interesting.  
  57.                 continue;  
  58.             }  
  59.             if ((cr.flags&Context.BIND_WAIVE_PRIORITY) == 0) {  
  60.                 ProcessRecord client = cr.binding.client;  
  61.                 int clientAdj = computeOomAdjLocked(client, cachedAdj,  
  62.                         TOP_APP, doingAll, now);  
  63.                 int clientProcState = client.curProcState;  
  64.                 if (clientProcState >= ActivityManager.PROCESS_STATE_CACHED_ACTIVITY) {  
  65.                     // If the other app is cached for any reason, for purposes here  
  66.                     // we are going to consider it empty.  The specific cached state  
  67.                     // doesn't propagate except under certain conditions.  
  68.                     clientProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;  
  69.                 }  
  70.                 String adjType = null;  
  71.                 if ((cr.flags&Context.BIND_ALLOW_OOM_MANAGEMENT) != 0) {  
  72.                     // Not doing bind OOM management, so treat  
  73.                     // this guy more like a started service.  
  74.                     if (app.hasShownUi && app != mHomeProcess) {  
  75.                         // If this process has shown some UI, let it immediately  
  76.                         // go to the LRU list because it may be pretty heavy with  
  77.                         // UI stuff.  We'll tag it with a label just to help  
  78.                         // debug and understand what is going on.  
  79.                         if (adj > clientAdj) {  
  80.                             adjType = "cch-bound-ui-services";  
  81.                         }  
  82.                         app.cached = false;  
  83.                         clientAdj = adj;  
  84.                         clientProcState = procState;  
  85.                     } else {  
  86.                         if (now >= (s.lastActivity  
  87.                                 + ActiveServices.MAX_SERVICE_INACTIVITY)) {  
  88.                             // This service has not seen activity within  
  89.                             // recent memory, so allow it to drop to the  
  90.                             // LRU list if there is no other reason to keep  
  91.                             // it around.  We'll also tag it with a label just  
  92.                             // to help debug and undertand what is going on.  
  93.                             if (adj > clientAdj) {  
  94.                                 adjType = "cch-bound-services";  
  95.                             }  
  96.                             clientAdj = adj;  
  97.                         }  
  98.                     }  
  99.                 }  
  100.                 if (adj > clientAdj) {  
  101.                     // If this process has recently shown UI, and  
  102.                     // the process that is binding to it is less  
  103.                     // important than being visible, then we don't  
  104.                     // care about the binding as much as we care  
  105.                     // about letting this process get into the LRU  
  106.                     // list to be killed and restarted if needed for  
  107.                     // memory.  
  108.                     if (app.hasShownUi && app != mHomeProcess  
  109.                             && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {  
  110.                         adjType = "cch-bound-ui-services";  
  111.                     } else {  
  112.                         if ((cr.flags&(Context.BIND_ABOVE_CLIENT  
  113.                                 |Context.BIND_IMPORTANT)) != 0) {  
  114.                             adj = clientAdj >= ProcessList.PERSISTENT_SERVICE_ADJ  
  115.                                     ? clientAdj : ProcessList.PERSISTENT_SERVICE_ADJ;  
  116.                         } else if ((cr.flags&Context.BIND_NOT_VISIBLE) != 0  
  117.                                 && clientAdj < ProcessList.PERCEPTIBLE_APP_ADJ  
  118.                                 && adj > ProcessList.PERCEPTIBLE_APP_ADJ) {  
  119.                             adj = ProcessList.PERCEPTIBLE_APP_ADJ;  
  120.                         } else if (clientAdj > ProcessList.VISIBLE_APP_ADJ) {  
  121.                             adj = clientAdj;  
  122.                         } else {  
  123.                             if (adj > ProcessList.VISIBLE_APP_ADJ) {  
  124.                                 adj = ProcessList.VISIBLE_APP_ADJ;  
  125.                             }  
  126.                         }  
  127.                         if (!client.cached) {  
  128.                             app.cached = false;  
  129.                         }  
  130.                         adjType = "service";  
  131.                     }  
  132.                 }  
  133.                 if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {  
  134.                     if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {  
  135.                         schedGroup = Process.THREAD_GROUP_DEFAULT;  
  136.                     }  
  137.                     if (clientProcState <= ActivityManager.PROCESS_STATE_TOP) {  
  138.                         if (clientProcState == ActivityManager.PROCESS_STATE_TOP) {  
  139.                             // Special handling of clients who are in the top state.  
  140.                             // We *may* want to consider this process to be in the  
  141.                             // top state as well, but only if there is not another  
  142.                             // reason for it to be running.  Being on the top is a  
  143.                             // special state, meaning you are specifically running  
  144.                             // for the current top app.  If the process is already  
  145.                             // running in the background for some other reason, it  
  146.                             // is more important to continue considering it to be  
  147.                             // in the background state.  
  148.                             mayBeTop = true;  
  149.                             clientProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;  
  150.                         } else {  
  151.                             // Special handling for above-top states (persistent  
  152.                             // processes).  These should not bring the current process  
  153.                             // into the top state, since they are not on top.  Instead  
  154.                             // give them the best state after that.  
  155.                             clientProcState =  
  156.                                     ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;  
  157.                         }  
  158.                     }  
  159.                 } else {  
  160.                     if (clientProcState <  
  161.                             ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND) {  
  162.                         clientProcState =  
  163.                                 ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND;  
  164.                     }  
  165.                 }  
  166.                 if (procState > clientProcState) {  
  167.                     procState = clientProcState;  
  168.                 }  
  169.                 if (procState < ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND  
  170.                         && (cr.flags&Context.BIND_SHOWING_UI) != 0) {  
  171.                     app.pendingUiClean = true;  
  172.                 }  
  173.                 if (adjType != null) {  
  174.                     app.adjType = adjType;  
  175.                     app.adjTypeCode = ActivityManager.RunningAppProcessInfo  
  176.                             .REASON_SERVICE_IN_USE;  
  177.                     app.adjSource = cr.binding.client;  
  178.                     app.adjSourceProcState = clientProcState;  
  179.                     app.adjTarget = s.name;  
  180.                 }  
  181.             }  
  182.             if ((cr.flags&Context.BIND_TREAT_LIKE_ACTIVITY) != 0) {  
  183.                 app.treatLikeActivity = true;  
  184.             }  
  185.             final ActivityRecord a = cr.activity;  
  186.             if ((cr.flags&Context.BIND_ADJUST_WITH_ACTIVITY) != 0) {  
  187.                 if (a != null && adj > ProcessList.FOREGROUND_APP_ADJ &&  
  188.                         (a.visible || a.state == ActivityState.RESUMED  
  189.                          || a.state == ActivityState.PAUSING)) {  
  190.                     adj = ProcessList.FOREGROUND_APP_ADJ;  
  191.                     if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {  
  192.                         schedGroup = Process.THREAD_GROUP_DEFAULT;  
  193.                     }  
  194.                     app.cached = false;  
  195.                     app.adjType = "service";  
  196.                     app.adjTypeCode = ActivityManager.RunningAppProcessInfo  
  197.                             .REASON_SERVICE_IN_USE;  
  198.                     app.adjSource = a;  
  199.                     app.adjSourceProcState = procState;  
  200.                     app.adjTarget = s.name;  
  201.                 }  
  202.             }  
  203.         }  
  204.     }  
  205. }  
  206.   
  207. for (int provi = app.pubProviders.size()-1;  
  208.         provi >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ  
  209.                 || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE  
  210.                 || procState > ActivityManager.PROCESS_STATE_TOP);  
  211.         provi--) {  
  212.     ContentProviderRecord cpr = app.pubProviders.valueAt(provi);  
  213.     for (int i = cpr.connections.size()-1;  
  214.             i >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ  
  215.                     || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE  
  216.                     || procState > ActivityManager.PROCESS_STATE_TOP);  
  217.             i--) {  
  218.         ContentProviderConnection conn = cpr.connections.get(i);  
  219.         ProcessRecord client = conn.client;  
  220.         if (client == app) {  
  221.             // Being our own client is not interesting.  
  222.             continue;  
  223.         }  
  224.         int clientAdj = computeOomAdjLocked(client, cachedAdj, TOP_APP, doingAll, now);  
  225.         int clientProcState = client.curProcState;  
  226.         if (clientProcState >= ActivityManager.PROCESS_STATE_CACHED_ACTIVITY) {  
  227.             // If the other app is cached for any reason, for purposes here  
  228.             // we are going to consider it empty.  
  229.             clientProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;  
  230.         }  
  231.         if (adj > clientAdj) {  
  232.             if (app.hasShownUi && app != mHomeProcess  
  233.                     && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {  
  234.                 app.adjType = "cch-ui-provider";  
  235.             } else {  
  236.                 adj = clientAdj > ProcessList.FOREGROUND_APP_ADJ  
  237.                         ? clientAdj : ProcessList.FOREGROUND_APP_ADJ;  
  238.                 app.adjType = "provider";  
  239.             }  
  240.             app.cached &= client.cached;  
  241.             app.adjTypeCode = ActivityManager.RunningAppProcessInfo  
  242.                     .REASON_PROVIDER_IN_USE;  
  243.             app.adjSource = client;  
  244.             app.adjSourceProcState = clientProcState;  
  245.             app.adjTarget = cpr.name;  
  246.         }  
  247.         if (clientProcState <= ActivityManager.PROCESS_STATE_TOP) {  
  248.             if (clientProcState == ActivityManager.PROCESS_STATE_TOP) {  
  249.                 // Special handling of clients who are in the top state.  
  250.                 // We *may* want to consider this process to be in the  
  251.                 // top state as well, but only if there is not another  
  252.                 // reason for it to be running.  Being on the top is a  
  253.                 // special state, meaning you are specifically running  
  254.                 // for the current top app.  If the process is already  
  255.                 // running in the background for some other reason, it  
  256.                 // is more important to continue considering it to be  
  257.                 // in the background state.  
  258.                 mayBeTop = true;  
  259.                 clientProcState = ActivityManager.PROCESS_STATE_CACHED_EMPTY;  
  260.             } else {  
  261.                 // Special handling for above-top states (persistent  
  262.                 // processes).  These should not bring the current process  
  263.                 // into the top state, since they are not on top.  Instead  
  264.                 // give them the best state after that.  
  265.                 clientProcState =  
  266.                         ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;  
  267.             }  
  268.         }  
  269.         if (procState > clientProcState) {  
  270.             procState = clientProcState;  
  271.         }  
  272.         if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {  
  273.             schedGroup = Process.THREAD_GROUP_DEFAULT;  
  274.         }  
  275.     }  
  276.     // If the provider has external (non-framework) process  
  277.     // dependencies, ensure that its adjustment is at least  
  278.     // FOREGROUND_APP_ADJ.  
  279.     if (cpr.hasExternalProcessHandles()) {  
  280.         if (adj > ProcessList.FOREGROUND_APP_ADJ) {  
  281.             adj = ProcessList.FOREGROUND_APP_ADJ;  
  282.             schedGroup = Process.THREAD_GROUP_DEFAULT;  
  283.             app.cached = false;  
  284.             app.adjType = "provider";  
  285.             app.adjTarget = cpr.name;  
  286.         }  
  287.         if (procState > ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) {  
  288.             procState = ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;  
  289.         }  
  290.     }  
  291. }  
[html] view plaincopy在CODE上查看代码片派生到我的代码片
  1. if (mayBeTop && procState > ActivityManager.PROCESS_STATE_TOP) {  
  2.     // A client of one of our services or providers is in the top state.  We  
  3.     // *may* want to be in the top state, but not if we are already running in  
  4.     // the background for some other reason.  For the decision here, we are going  
  5.     // to pick out a few specific states that we want to remain in when a client  
  6.     // is top (states that tend to be longer-term) and otherwise allow it to go  
  7.     // to the top state.  
  8.     switch (procState) {  
  9.         case ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND:  
  10.         case ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND:  
  11.         case ActivityManager.PROCESS_STATE_SERVICE:  
  12.             // These all are longer-term states, so pull them up to the top  
  13.             // of the background states, but not all the way to the top state.  
  14.             procState = ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;  
  15.             break;  
  16.         default:  
  17.             // Otherwise, top is a better choice, so take it.  
  18.             procState = ActivityManager.PROCESS_STATE_TOP;  
  19.             break;  
  20.     }  
  21. }  
  22.   
  23. if (procState >= ActivityManager.PROCESS_STATE_CACHED_EMPTY) {  
  24.     if (app.hasClientActivities) {  
  25.         // This is a cached process, but with client activities.  Mark it so.  
  26.         procState = ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT;  
  27.         app.adjType = "cch-client-act";  
  28.     } else if (app.treatLikeActivity) {  
  29.         // This is a cached process, but somebody wants us to treat it like it has  
  30.         // an activity, okay!  
  31.         procState = ActivityManager.PROCESS_STATE_CACHED_ACTIVITY;  
  32.         app.adjType = "cch-as-act";  
  33.     }  
  34. }  
  35.   
  36. if (adj == ProcessList.SERVICE_ADJ) {  
  37.     if (doingAll) {  
  38.         app.serviceb = mNewNumAServiceProcs > (mNumServiceProcs/3);  
  39.         mNewNumServiceProcs++;  
  40.         //Slog.i(TAG, "ADJ " + app + " serviceb=" + app.serviceb);  
  41.         if (!app.serviceb) {  
  42.             // This service isn't far enough down on the LRU list to  
  43.             // normally be a B service, but if we are low on RAM and it  
  44.             // is large we want to force it down since we would prefer to  
  45.             // keep launcher over it.  
  46.             if (mLastMemoryLevel > ProcessStats.ADJ_MEM_FACTOR_NORMAL  
  47.                     && app.lastPss >= mProcessList.getCachedRestoreThresholdKb()) {  
  48.                 app.serviceHighRam = true;  
  49.                 app.serviceb = true;  
  50.                 //Slog.i(TAG, "ADJ " + app + " high ram!");  
  51.             } else {  
  52.                 mNewNumAServiceProcs++;  
  53.                 //Slog.i(TAG, "ADJ " + app + " not high ram!");  
  54.             }  
  55.         } else {  
  56.             app.serviceHighRam = false;  
  57.         }  
  58.     }  
  59.     if (app.serviceb) {  
  60.         adj = ProcessList.SERVICE_B_ADJ;  
  61.     }  
  62. }  
  63.   
  64. app.curRawAdj = adj;  
  65.   
  66. //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +  
  67. //      " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);  
  68. if (adj > app.maxAdj) {  
  69.     adj = app.maxAdj;  
  70.     if (app.maxAdj <= ProcessList.PERCEPTIBLE_APP_ADJ) {  
  71.         schedGroup = Process.THREAD_GROUP_DEFAULT;  
  72.     }  
  73. }  
  74.   
  75. // Do final modification to adj.  Everything we do between here and applying  
  76. // the final setAdj must be done in this function, because we will also use  
  77. // it when computing the final cached adj later.  Note that we don't need to  
  78. // worry about this for max adj above, since max adj will always be used to  
  79. // keep it out of the cached vaues.  
  80. app.curAdj = app.modifyRawOomAdj(adj);  
  81. app.curSchedGroup = schedGroup;  
  82. app.curProcState = procState;  
  83. app.foregroundActivities = foregroundActivities;  
  84.   
  85. return app.curRawAdj; 
0 0
原创粉丝点击