Android的LMK和OOM

Android分析之LowMemoryKiller
linux操作系统的传统理念就是内存用的越多越好,尽可能拿来用,既然被尽量的使用,自然应该有清除机制。Android以linux为基础,自然部分继承了这个特性。Android使用lowmemorykiller在达到某个内存门限的情况下去选择进程删除来释放内存。关键的配置文件有如下两个,/sys/module/lowmemorykiller/parameters/adj和/sys/module/lowmemorykiller/parameters/minfree配置系统的相关参数。

 

LMK开始工作时, 首先根据阈值表确定当前的警戒级数,则高于警戒级数的进程是待杀的范围。然后遍历所有进程的oom_adj值,找到大于min_adj的进程,若找到多个,则把占用进程最大的进程存放在selected中。 最关键的一步就是,发送SIGKILL信息,杀掉该进程。


http://blog.csdn.net/anjen/article/details/6830203

 

目前Android4.0后有一些调整,主要体现在上面提到的adj和minfree配置文件的生成,以及FOREGROUND_APP_ADJ等常量的定义,解耦到了ProcessList.java中:

@ActivityManagerService.java

final ProcessList mProcessList = new ProcessList();


@ProcessList.java

    ProcessList() {
        MemInfoReader minfo = new MemInfoReader();
        minfo.readMemInfo();
        mTotalMemMb = minfo.getTotalSize()/(1024*1024);
        updateOomLevels(0, 0, false);
    }

 private void updateOomLevels(int displayWidth, int displayHeight, boolean write) {
        // Scale buckets from avail memory: at 300MB we use the lowest values to
        // 700MB or more for the top values.
        float scaleMem = ((float)(mTotalMemMb-300))/(700-300);

        // Scale buckets from screen size.
        int minSize = 320*480;  //  153600
        int maxSize = 1280*800; // 1024000  230400 870400  .264
        float scaleDisp = ((float)(displayWidth*displayHeight)-minSize)/(maxSize-minSize);
        //Slog.i("XXXXXX", "scaleDisp=" + scaleDisp + " dw=" + displayWidth + " dh=" + displayHeight);

        StringBuilder adjString = new StringBuilder();
        StringBuilder memString = new StringBuilder();

        float scale = scaleMem > scaleDisp ? scaleMem : scaleDisp;
        if (scale < 0) scale = 0;
        else if (scale > 1) scale = 1;
        for (int i=0; i<mOomAdj.length; i++) {
            long low = mOomMinFreeLow[i];
            long high = mOomMinFreeHigh[i];
            mOomMinFree[i] = (long)(low + ((high-low)*scale));

            if (i > 0) {
                adjString.append(',');
                memString.append(',');
            }
            adjString.append(mOomAdj[i]);
            memString.append((mOomMinFree[i]*1024)/PAGE_SIZE);
        }

        //Slog.i("XXXXXXX", "******************************* MINFREE: " + memString);
        if (write) {
            writeFile("/sys/module/lowmemorykiller/parameters/adj", adjString.toString());
            writeFile("/sys/module/lowmemorykiller/parameters/minfree", memString.toString());
        }
        // GB: 2048,3072,4096,6144,7168,8192
        // HC: 8192,10240,12288,14336,16384,20480
    }


进程的oom_adj值来源:

1.init.rc中,init进程的pid1omm_adj被配置为-16,永远不会被杀死。

on early-init
    # Set init and its forked children's oom_adj.
    write /proc/1/oom_adj -16

    start ueventd


2.通过Process.setOomAdj(int pid, int amt)进行设置,其中在ActivityManagerService中updateOomAdjLocked()函数中就有调用。

@Process.java

public static final native boolean setOomAdj(int pid, int amt);


@android_util_Process.cpp

jboolean android_os_Process_setOomAdj(JNIEnv* env, jobject clazz,
                                      jint pid, jint adj)
{
#ifdef HAVE_OOM_ADJ
    char text[64];
    sprintf(text, "/proc/%d/oom_adj", pid);
    int fd = open(text, O_WRONLY);
    if (fd >= 0) {
        sprintf(text, "%d", adj);
        write(fd, text, strlen(text));
        close(fd);
    }
    return true;
#endif
    return false;
}


 

最后值得提到的就是ActivityManageService.java中的OOM了,主要是当后台进程数达到阀值ProcessList.MAX_HIDDEN_APPS 15后对被杀进程的选择,而且进程的oom_adj也会适当地被调整。

@ActivityManagerServcie.java

    final void updateOomAdjLocked() {
        final ActivityRecord TOP_ACT = resumedAppLocked();
        final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;

        if (false) {
            RuntimeException e = new RuntimeException();
            e.fillInStackTrace();
            Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
        }

        mAdjSeq++;
        mNewNumServiceProcs = 0;

        // Let's determine how many processes we have running vs.
        // how many slots we have for background processes; we may want
        // to put multiple processes in a slot of there are enough of
        // them.
        int numSlots = ProcessList.HIDDEN_APP_MAX_ADJ - ProcessList.HIDDEN_APP_MIN_ADJ + 1;
        int factor = (mLruProcesses.size()-4)/numSlots;
        if (factor < 1) factor = 1;
        int step = 0;
        int numHidden = 0;
        
        // First update the OOM adjustment for each of the
        // application processes based on their current state.
        int i = mLruProcesses.size();
        int curHiddenAdj = ProcessList.HIDDEN_APP_MIN_ADJ;
        while (i > 0) {
            i--;
            ProcessRecord app = mLruProcesses.get(i);
            //Slog.i(TAG, "OOM " + app + ": cur hidden=" + curHiddenAdj);
            updateOomAdjLocked(app, curHiddenAdj, TOP_APP, true);
            if (curHiddenAdj < ProcessList.HIDDEN_APP_MAX_ADJ
                && app.curAdj == curHiddenAdj) {
                step++;
                if (step >= factor) {
                    step = 0;
                    curHiddenAdj++;
                }
            }
            if (!app.killedBackground) {
                if (app.curAdj >= ProcessList.HIDDEN_APP_MIN_ADJ) {
                    numHidden++;
                    if (numHidden > mProcessLimit) {
                        Slog.i(TAG, "No longer want " + app.processName
                                + " (pid " + app.pid + "): hidden #" + numHidden);
                        EventLog.writeEvent(EventLogTags.AM_KILL, app.pid,
                                app.processName, app.setAdj, "too many background");
                        app.killedBackground = true;
                        Process.killProcessQuiet(app.pid);
                    }
                }
            }
        }


 

    private final int computeOomAdjLocked(ProcessRecord app, int hiddenAdj,
            ProcessRecord TOP_APP, boolean recursed, boolean doingAll) {
        if (mAdjSeq == app.adjSeq) {
            // This adjustment has already been computed.  If we are calling
            // from the top, we may have already computed our adjustment with
            // an earlier hidden adjustment that isn't really for us... if
            // so, use the new hidden adjustment.
            if (!recursed && app.hidden) {
                app.curAdj = app.curRawAdj = hiddenAdj;
            }
            return app.curRawAdj;
        }

        if (app.thread == null) {
            app.adjSeq = mAdjSeq;
            app.curSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
            return (app.curAdj=ProcessList.HIDDEN_APP_MAX_ADJ);
        }

        app.adjTypeCode = ActivityManager.RunningAppProcessInfo.REASON_UNKNOWN;
        app.adjSource = null;
        app.adjTarget = null;
        app.empty = false;
        app.hidden = false;

        final int activitiesSize = app.activities.size();

        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.keeping = true;
            app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
            // System process 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;
                        break;
                    }
                }
            }
            return (app.curAdj=app.maxAdj);
        }

        final boolean hadForegroundActivities = app.foregroundActivities;

        app.foregroundActivities = false;
        app.keeping = false;
        app.systemNoUi = false;

        // Determine the importance of the process, starting with most
        // important to least, and assign an appropriate OOM adjustment.
        int adj;
        int schedGroup;
        if (app == TOP_APP) {
            // The last app on the list is the foreground app.
            adj = ProcessList.FOREGROUND_APP_ADJ;
            schedGroup = Process.THREAD_GROUP_DEFAULT;
            app.adjType = "top-activity";
            app.foregroundActivities = true;
        } else if (app.instrumentationClass != null) {
            // Don't want to kill running instrumentation.
            adj = ProcessList.FOREGROUND_APP_ADJ;
            schedGroup = Process.THREAD_GROUP_DEFAULT;
            app.adjType = "instrumentation";
        } else if (app.curReceiver != null ||
                (mPendingBroadcast != null && mPendingBroadcast.curApp == app)) {
            // An app that is currently receiving a broadcast also
            // counts as being in the foreground.
            adj = ProcessList.FOREGROUND_APP_ADJ;
            schedGroup = Process.THREAD_GROUP_DEFAULT;
            app.adjType = "broadcast";
        } else if (app.executingServices.size() > 0) {
            // An app that is currently executing a service callback also
            // counts as being in the foreground.
            adj = ProcessList.FOREGROUND_APP_ADJ;
            schedGroup = Process.THREAD_GROUP_DEFAULT;
            app.adjType = "exec-service";
        } else if (activitiesSize > 0) {
            // This app is in the background with paused activities.
            // We inspect activities to potentially upgrade adjustment further below.
            adj = hiddenAdj;
            schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
            app.hidden = true;
            app.adjType = "bg-activities";
        } else {
            // A very not-needed process.  If this is lower in the lru list,
            // we will push it in to the empty bucket.
            adj = hiddenAdj;
            schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
            app.hidden = true;
            app.empty = true;
            app.adjType = "bg-empty";
        }

        // Examine all activities if not already foreground.
        if (!app.foregroundActivities && activitiesSize > 0) {
            for (int j = 0; j < activitiesSize; j++) {
                final ActivityRecord r = app.activities.get(j);
                if (r.visible) {
                    // App has a visible activity; only upgrade adjustment.
                    if (adj > ProcessList.VISIBLE_APP_ADJ) {
                        adj = ProcessList.VISIBLE_APP_ADJ;
                        app.adjType = "visible";
                    }
                    schedGroup = Process.THREAD_GROUP_DEFAULT;
                    app.hidden = false;
                    app.foregroundActivities = true;
                    break;
                } else if (r.state == ActivityState.PAUSING || r.state == ActivityState.PAUSED
                        || r.state == ActivityState.STOPPING) {
                    // Only upgrade adjustment.
                    if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
                        adj = ProcessList.PERCEPTIBLE_APP_ADJ;
                        app.adjType = "stopping";
                    }
                    app.hidden = false;
                    app.foregroundActivities = true;
                }
            }
        }

        if (adj > ProcessList.PERCEPTIBLE_APP_ADJ) {
            if (app.foregroundServices) {
                // The user is aware of this app, so make it visible.
                adj = ProcessList.PERCEPTIBLE_APP_ADJ;
                app.hidden = false;
                app.adjType = "foreground-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;
                app.hidden = false;
                app.adjType = "force-foreground";
                app.adjSource = app.forcingToForeground;
                schedGroup = Process.THREAD_GROUP_DEFAULT;
            }
        }

        if (adj > ProcessList.HEAVY_WEIGHT_APP_ADJ && app == mHeavyWeightProcess) {
            // We don't want to kill the current heavy-weight process.
            adj = ProcessList.HEAVY_WEIGHT_APP_ADJ;
            schedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
            app.hidden = false;
            app.adjType = "heavy";
        }

        if (adj > ProcessList.HOME_APP_ADJ && app == mHomeProcess) {
            // 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.hidden = false;
            app.adjType = "home";
        }

        if (adj > ProcessList.PREVIOUS_APP_ADJ && app == mPreviousProcess
                && app.activities.size() > 0) {
            // 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.hidden = false;
            app.adjType = "previous";
        }

        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;

        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, "oom BACKUP_APP_ADJ for " + app);
                adj = ProcessList.BACKUP_APP_ADJ;
                app.adjType = "backup";
                app.hidden = false;
            }
        }

        if (app.services.size() != 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
                || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
            final long now = SystemClock.uptimeMillis();
            // This process is more important if the top activity is
            // bound to the service.
            Iterator<ServiceRecord> jt = app.services.iterator();
            while (jt.hasNext() && adj > ProcessList.FOREGROUND_APP_ADJ) {
                ServiceRecord s = jt.next();
                if (s.startRequested) {
                    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 = "started-bg-ui-services";
                        }
                    } else {
                        if (now < (s.lastActivity+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.hidden = 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 = "started-bg-services";
                        }
                    }
                    // Don't kill this process because it is doing work; it
                    // has said it is doing work.
                    app.keeping = true;
                }
                if (s.connections.size() > 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
                        || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
                    Iterator<ArrayList<ConnectionRecord>> kt
                            = s.connections.values().iterator();
                    while (kt.hasNext() && adj > ProcessList.FOREGROUND_APP_ADJ) {
                        ArrayList<ConnectionRecord> clist = kt.next();
                        for (int i=0; i<clist.size() && adj > ProcessList.FOREGROUND_APP_ADJ; 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;
                            }
                            if ((cr.flags&Context.BIND_WAIVE_PRIORITY) == 0) {
                                ProcessRecord client = cr.binding.client;
                                int clientAdj = adj;
                                int myHiddenAdj = hiddenAdj;
                                if (myHiddenAdj > client.hiddenAdj) {
                                    if (client.hiddenAdj >= ProcessList.VISIBLE_APP_ADJ) {
                                        myHiddenAdj = client.hiddenAdj;
                                    } else {
                                        myHiddenAdj = ProcessList.VISIBLE_APP_ADJ;
                                    }
                                }
                                clientAdj = computeOomAdjLocked(
                                    client, myHiddenAdj, TOP_APP, true, doingAll);
                                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 = "bound-bg-ui-services";
                                        }
                                        app.hidden = false;
                                        clientAdj = adj;
                                    } else {
                                        if (now >= (s.lastActivity+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 = "bound-bg-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 = "bound-bg-ui-services";
                                    } else {
                                        if ((cr.flags&(Context.BIND_ABOVE_CLIENT
                                                |Context.BIND_IMPORTANT)) != 0) {
                                            adj = clientAdj;
                                        } 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.VISIBLE_APP_ADJ) {
                                            adj = clientAdj;
                                        } else {
                                            app.pendingUiClean = true;
                                            if (adj > ProcessList.VISIBLE_APP_ADJ) {
                                                adj = ProcessList.VISIBLE_APP_ADJ;
                                            }
                                        }
                                        if (!client.hidden) {
                                            app.hidden = false;
                                        }
                                        if (client.keeping) {
                                            app.keeping = true;
                                        }
                                        adjType = "service";
                                    }
                                }
                                if (adjType != null) {
                                    app.adjType = adjType;
                                    app.adjTypeCode = ActivityManager.RunningAppProcessInfo
                                            .REASON_SERVICE_IN_USE;
                                    app.adjSource = cr.binding.client;
                                    app.adjSourceOom = clientAdj;
                                    app.adjTarget = s.name;
                                }
                                if ((cr.flags&Context.BIND_NOT_FOREGROUND) == 0) {
                                    if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
                                        schedGroup = Process.THREAD_GROUP_DEFAULT;
                                    }
                                }
                            }
                            if ((cr.flags&Context.BIND_ADJUST_WITH_ACTIVITY) != 0) {
                                ActivityRecord a = cr.activity;
                                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) {
                                        schedGroup = Process.THREAD_GROUP_DEFAULT;
                                    }
                                    app.hidden = false;
                                    app.adjType = "service";
                                    app.adjTypeCode = ActivityManager.RunningAppProcessInfo
                                            .REASON_SERVICE_IN_USE;
                                    app.adjSource = a;
                                    app.adjSourceOom = adj;
                                    app.adjTarget = s.name;
                                }
                            }
                        }
                    }
                }
            }
            
            // Finally, if this process has active services running in it, we
            // would like to avoid killing it unless it would prevent the current
            // application from running.  By default we put the process in
            // with the rest of the background processes; as we scan through
            // its services we may bump it up from there.
            if (adj > hiddenAdj) {
                adj = hiddenAdj;
                app.hidden = false;
                app.adjType = "bg-services";
            }
        }

        if (app.pubProviders.size() != 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
                || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
            Iterator<ContentProviderRecord> jt = app.pubProviders.values().iterator();
            while (jt.hasNext() && (adj > ProcessList.FOREGROUND_APP_ADJ
                    || schedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE)) {
                ContentProviderRecord cpr = jt.next();
                if (cpr.clients.size() != 0) {
                    Iterator<ProcessRecord> kt = cpr.clients.iterator();
                    while (kt.hasNext() && adj > ProcessList.FOREGROUND_APP_ADJ) {
                        ProcessRecord client = kt.next();
                        if (client == app) {
                            // Being our own client is not interesting.
                            continue;
                        }
                        int myHiddenAdj = hiddenAdj;
                        if (myHiddenAdj > client.hiddenAdj) {
                            if (client.hiddenAdj > ProcessList.FOREGROUND_APP_ADJ) {
                                myHiddenAdj = client.hiddenAdj;
                            } else {
                                myHiddenAdj = ProcessList.FOREGROUND_APP_ADJ;
                            }
                        }
                        int clientAdj = computeOomAdjLocked(
                            client, myHiddenAdj, TOP_APP, true, doingAll);
                        if (adj > clientAdj) {
                            if (app.hasShownUi && app != mHomeProcess
                                    && clientAdj > ProcessList.PERCEPTIBLE_APP_ADJ) {
                                app.adjType = "bg-ui-provider";
                            } else {
                                adj = clientAdj > ProcessList.FOREGROUND_APP_ADJ
                                        ? clientAdj : ProcessList.FOREGROUND_APP_ADJ;
                                app.adjType = "provider";
                            }
                            if (!client.hidden) {
                                app.hidden = false;
                            }
                            if (client.keeping) {
                                app.keeping = true;
                            }
                            app.adjTypeCode = ActivityManager.RunningAppProcessInfo
                                    .REASON_PROVIDER_IN_USE;
                            app.adjSource = client;
                            app.adjSourceOom = clientAdj;
                            app.adjTarget = cpr.name;
                        }
                        if (client.curSchedGroup == Process.THREAD_GROUP_DEFAULT) {
                            schedGroup = Process.THREAD_GROUP_DEFAULT;
                        }
                    }
                }
                // If the provider has external (non-framework) process
                // dependencies, ensure that its adjustment is at least
                // FOREGROUND_APP_ADJ.
                if (cpr.externals != 0) {
                    if (adj > ProcessList.FOREGROUND_APP_ADJ) {
                        adj = ProcessList.FOREGROUND_APP_ADJ;
                        schedGroup = Process.THREAD_GROUP_DEFAULT;
                        app.hidden = false;
                        app.keeping = true;
                        app.adjType = "provider";
                        app.adjTarget = cpr.name;
                    }
                }
            }
        }

        app.curRawAdj = adj;
        
        //Slog.i(TAG, "OOM ADJ " + app + ": pid=" + app.pid +
        //      " adj=" + adj + " curAdj=" + app.curAdj + " maxAdj=" + app.maxAdj);
        if (adj > app.maxAdj) {
            adj = app.maxAdj;
            if (app.maxAdj <= ProcessList.PERCEPTIBLE_APP_ADJ) {
                schedGroup = Process.THREAD_GROUP_DEFAULT;
            }
        }
        if (adj < ProcessList.HIDDEN_APP_MIN_ADJ) {
            app.keeping = true;
        }

        if (app.hasAboveClient) {
            // If this process has bound to any services with BIND_ABOVE_CLIENT,
            // then we need to drop its adjustment to be lower than the service's
            // in order to honor the request.  We want to drop it by one adjustment
            // level...  but there is special meaning applied to various levels so
            // we will skip some of them.
            if (adj < ProcessList.FOREGROUND_APP_ADJ) {
                // System process will not get dropped, ever
            } 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.HIDDEN_APP_MIN_ADJ) {
                adj = ProcessList.HIDDEN_APP_MIN_ADJ;
            } else if (adj < ProcessList.HIDDEN_APP_MAX_ADJ) {
                adj++;
            }
        }

        if (adj == ProcessList.SERVICE_ADJ) {
            if (doingAll) {
                app.serviceb = mNewNumServiceProcs > (mNumServiceProcs/3);
                mNewNumServiceProcs++;
            }
            if (app.serviceb) {
                adj = ProcessList.SERVICE_B_ADJ;
            }
        } else {
            app.serviceb = false;
        }

        app.curAdj = adj;
        app.curSchedGroup = schedGroup;

        if (hadForegroundActivities != app.foregroundActivities) {
            mHandler.obtainMessage(DISPATCH_FOREGROUND_ACTIVITIES_CHANGED, app.pid, app.info.uid,
                    app.foregroundActivities).sendToTarget();
        }

        return app.curRawAdj;
    }



 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值