読者です 読者をやめる 読者になる 読者になる

のねのBlog

パソコンやソフト開発で起きた問題など書きます。よろしくお願いします。

Did OOM ADJ in 0ms

長い関数だなー。
Cross Reference: /frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

   20500     final void updateOomAdjLocked() {
   20501         final ActivityRecord TOP_ACT = resumedAppLocked();
   20502         final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
   20503         final long now = SystemClock.uptimeMillis();
   20504         final long nowElapsed = SystemClock.elapsedRealtime();
   20505         final long oldTime = now - ProcessList.MAX_EMPTY_TIME;
   20506         final int N = mLruProcesses.size();
   20507 
   20508         if (false) {
   20509             RuntimeException e = new RuntimeException();
   20510             e.fillInStackTrace();
   20511             Slog.i(TAG, "updateOomAdj: top=" + TOP_ACT, e);
   20512         }
   20513 
   20514         // Reset state in all uid records.
   20515         for (int i=mActiveUids.size()-1; i>=0; i--) {
   20516             final UidRecord uidRec = mActiveUids.valueAt(i);
   20517             if (false && DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
   20518                     "Starting update of " + uidRec);
   20519             uidRec.reset();
   20520         }
   20521 
   20522         mStackSupervisor.rankTaskLayersIfNeeded();
   20523 
   20524         mAdjSeq++;
   20525         mNewNumServiceProcs = 0;
   20526         mNewNumAServiceProcs = 0;
   20527 
   20528         final int emptyProcessLimit;
   20529         final int cachedProcessLimit;
   20530         if (mProcessLimit <= 0) {
   20531             emptyProcessLimit = cachedProcessLimit = 0;
   20532         } else if (mProcessLimit == 1) {
   20533             emptyProcessLimit = 1;
   20534             cachedProcessLimit = 0;
   20535         } else {
   20536             emptyProcessLimit = ProcessList.computeEmptyProcessLimit(mProcessLimit);
   20537             cachedProcessLimit = mProcessLimit - emptyProcessLimit;
   20538         }
   20539 
   20540         // Let's determine how many processes we have running vs.
   20541         // how many slots we have for background processes; we may want
   20542         // to put multiple processes in a slot of there are enough of
   20543         // them.
   20544         int numSlots = (ProcessList.CACHED_APP_MAX_ADJ
   20545                 - ProcessList.CACHED_APP_MIN_ADJ + 1) / 2;
   20546         int numEmptyProcs = N - mNumNonCachedProcs - mNumCachedHiddenProcs;
   20547         if (numEmptyProcs > cachedProcessLimit) {
   20548             // If there are more empty processes than our limit on cached
   20549             // processes, then use the cached process limit for the factor.
   20550             // This ensures that the really old empty processes get pushed
   20551             // down to the bottom, so if we are running low on memory we will
   20552             // have a better chance at keeping around more cached processes
   20553             // instead of a gazillion empty processes.
   20554             numEmptyProcs = cachedProcessLimit;
   20555         }
   20556         int emptyFactor = numEmptyProcs/numSlots;
   20557         if (emptyFactor < 1) emptyFactor = 1;
   20558         int cachedFactor = (mNumCachedHiddenProcs > 0 ? mNumCachedHiddenProcs : 1)/numSlots;
   20559         if (cachedFactor < 1) cachedFactor = 1;
   20560         int stepCached = 0;
   20561         int stepEmpty = 0;
   20562         int numCached = 0;
   20563         int numEmpty = 0;
   20564         int numTrimming = 0;
   20565 
   20566         mNumNonCachedProcs = 0;
   20567         mNumCachedHiddenProcs = 0;
   20568 
   20569         // First update the OOM adjustment for each of the
   20570         // application processes based on their current state.
   20571         int curCachedAdj = ProcessList.CACHED_APP_MIN_ADJ;
   20572         int nextCachedAdj = curCachedAdj+1;
   20573         int curEmptyAdj = ProcessList.CACHED_APP_MIN_ADJ;
   20574         int nextEmptyAdj = curEmptyAdj+2;
   20575         for (int i=N-1; i>=0; i--) {
   20576             ProcessRecord app = mLruProcesses.get(i);
   20577             if (!app.killedByAm && app.thread != null) {
   20578                 app.procStateChanged = false;
   20579                 computeOomAdjLocked(app, ProcessList.UNKNOWN_ADJ, TOP_APP, true, now);
   20580 
   20581                 // If we haven't yet assigned the final cached adj
   20582                 // to the process, do that now.
   20583                 if (app.curAdj >= ProcessList.UNKNOWN_ADJ) {
   20584                     switch (app.curProcState) {
   20585                         case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY:
   20586                         case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
   20587                             // This process is a cached process holding activities...
   20588                             // assign it the next cached value for that type, and then
   20589                             // step that cached level.
   20590                             app.curRawAdj = curCachedAdj;
   20591                             app.curAdj = app.modifyRawOomAdj(curCachedAdj);
   20592                             if (DEBUG_LRU && false) Slog.d(TAG_LRU, "Assigning activity LRU #" + i
   20593                                     + " adj: " + app.curAdj + " (curCachedAdj=" + curCachedAdj
   20594                                     + ")");
   20595                             if (curCachedAdj != nextCachedAdj) {
   20596                                 stepCached++;
   20597                                 if (stepCached >= cachedFactor) {
   20598                                     stepCached = 0;
   20599                                     curCachedAdj = nextCachedAdj;
   20600                                     nextCachedAdj += 2;
   20601                                     if (nextCachedAdj > ProcessList.CACHED_APP_MAX_ADJ) {
   20602                                         nextCachedAdj = ProcessList.CACHED_APP_MAX_ADJ;
   20603                                     }
   20604                                 }
   20605                             }
   20606                             break;
   20607                         default:
   20608                             // For everything else, assign next empty cached process
   20609                             // level and bump that up.  Note that this means that
   20610                             // long-running services that have dropped down to the
   20611                             // cached level will be treated as empty (since their process
   20612                             // state is still as a service), which is what we want.
   20613                             app.curRawAdj = curEmptyAdj;
   20614                             app.curAdj = app.modifyRawOomAdj(curEmptyAdj);
   20615                             if (DEBUG_LRU && false) Slog.d(TAG_LRU, "Assigning empty LRU #" + i
   20616                                     + " adj: " + app.curAdj + " (curEmptyAdj=" + curEmptyAdj
   20617                                     + ")");
   20618                             if (curEmptyAdj != nextEmptyAdj) {
   20619                                 stepEmpty++;
   20620                                 if (stepEmpty >= emptyFactor) {
   20621                                     stepEmpty = 0;
   20622                                     curEmptyAdj = nextEmptyAdj;
   20623                                     nextEmptyAdj += 2;
   20624                                     if (nextEmptyAdj > ProcessList.CACHED_APP_MAX_ADJ) {
   20625                                         nextEmptyAdj = ProcessList.CACHED_APP_MAX_ADJ;
   20626                                     }
   20627                                 }
   20628                             }
   20629                             break;
   20630                     }
   20631                 }
   20632 
   20633                 applyOomAdjLocked(app, true, now, nowElapsed);
   20634 
   20635                 // Count the number of process types.
   20636                 switch (app.curProcState) {
   20637                     case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY:
   20638                     case ActivityManager.PROCESS_STATE_CACHED_ACTIVITY_CLIENT:
   20639                         mNumCachedHiddenProcs++;
   20640                         numCached++;
   20641                         if (numCached > cachedProcessLimit) {
   20642                             app.kill("cached #" + numCached, true);
   20643                         }
   20644                         break;
   20645                     case ActivityManager.PROCESS_STATE_CACHED_EMPTY:
   20646                         if (numEmpty > ProcessList.TRIM_EMPTY_APPS
   20647                                 && app.lastActivityTime < oldTime) {
   20648                             app.kill("empty for "
   20649                                     + ((oldTime + ProcessList.MAX_EMPTY_TIME - app.lastActivityTime)
   20650                                     / 1000) + "s", true);
   20651                         } else {
   20652                             numEmpty++;
   20653                             if (numEmpty > emptyProcessLimit) {
   20654                                 app.kill("empty #" + numEmpty, true);
   20655                             }
   20656                         }
   20657                         break;
   20658                     default:
   20659                         mNumNonCachedProcs++;
   20660                         break;
   20661                 }
   20662 
   20663                 if (app.isolated && app.services.size() <= 0) {
   20664                     // If this is an isolated process, and there are no
   20665                     // services running in it, then the process is no longer
   20666                     // needed.  We agressively kill these because we can by
   20667                     // definition not re-use the same process again, and it is
   20668                     // good to avoid having whatever code was running in them
   20669                     // left sitting around after no longer needed.
   20670                     app.kill("isolated not needed", true);
   20671                 } else {
   20672                     // Keeping this process, update its uid.
   20673                     final UidRecord uidRec = app.uidRecord;
   20674                     if (uidRec != null && uidRec.curProcState > app.curProcState) {
   20675                         uidRec.curProcState = app.curProcState;
   20676                     }
   20677                 }
   20678 
   20679                 if (app.curProcState >= ActivityManager.PROCESS_STATE_HOME
   20680                         && !app.killedByAm) {
   20681                     numTrimming++;
   20682                 }
   20683             }
   20684         }
   20685 
   20686         mNumServiceProcs = mNewNumServiceProcs;
   20687 
   20688         // Now determine the memory trimming level of background processes.
   20689         // Unfortunately we need to start at the back of the list to do this
   20690         // properly.  We only do this if the number of background apps we
   20691         // are managing to keep around is less than half the maximum we desire;
   20692         // if we are keeping a good number around, we'll let them use whatever
   20693         // memory they want.
   20694         final int numCachedAndEmpty = numCached + numEmpty;
   20695         int memFactor;
   20696         if (numCached <= ProcessList.TRIM_CACHED_APPS
   20697                 && numEmpty <= ProcessList.TRIM_EMPTY_APPS) {
   20698             if (numCachedAndEmpty <= ProcessList.TRIM_CRITICAL_THRESHOLD) {
   20699                 memFactor = ProcessStats.ADJ_MEM_FACTOR_CRITICAL;
   20700             } else if (numCachedAndEmpty <= ProcessList.TRIM_LOW_THRESHOLD) {
   20701                 memFactor = ProcessStats.ADJ_MEM_FACTOR_LOW;
   20702             } else {
   20703                 memFactor = ProcessStats.ADJ_MEM_FACTOR_MODERATE;
   20704             }
   20705         } else {
   20706             memFactor = ProcessStats.ADJ_MEM_FACTOR_NORMAL;
   20707         }
   20708         // We always allow the memory level to go up (better).  We only allow it to go
   20709         // down if we are in a state where that is allowed, *and* the total number of processes
   20710         // has gone down since last time.
   20711         if (DEBUG_OOM_ADJ) Slog.d(TAG_OOM_ADJ, "oom: memFactor=" + memFactor
   20712                 + " last=" + mLastMemoryLevel + " allowLow=" + mAllowLowerMemLevel
   20713                 + " numProcs=" + mLruProcesses.size() + " last=" + mLastNumProcesses);
   20714         if (memFactor > mLastMemoryLevel) {
   20715             if (!mAllowLowerMemLevel || mLruProcesses.size() >= mLastNumProcesses) {
   20716                 memFactor = mLastMemoryLevel;
   20717                 if (DEBUG_OOM_ADJ) Slog.d(TAG_OOM_ADJ, "Keeping last mem factor!");
   20718             }
   20719         }
   20720         if (memFactor != mLastMemoryLevel) {
   20721             EventLogTags.writeAmMemFactor(memFactor, mLastMemoryLevel);
   20722         }
   20723         mLastMemoryLevel = memFactor;
   20724         mLastNumProcesses = mLruProcesses.size();
   20725         boolean allChanged = mProcessStats.setMemFactorLocked(memFactor, !isSleepingLocked(), now);
   20726         final int trackerMemFactor = mProcessStats.getMemFactorLocked();
   20727         if (memFactor != ProcessStats.ADJ_MEM_FACTOR_NORMAL) {
   20728             if (mLowRamStartTime == 0) {
   20729                 mLowRamStartTime = now;
   20730             }
   20731             int step = 0;
   20732             int fgTrimLevel;
   20733             switch (memFactor) {
   20734                 case ProcessStats.ADJ_MEM_FACTOR_CRITICAL:
   20735                     fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL;
   20736                     break;
   20737                 case ProcessStats.ADJ_MEM_FACTOR_LOW:
   20738                     fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW;
   20739                     break;
   20740                 default:
   20741                     fgTrimLevel = ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE;
   20742                     break;
   20743             }
   20744             int factor = numTrimming/3;
   20745             int minFactor = 2;
   20746             if (mHomeProcess != null) minFactor++;
   20747             if (mPreviousProcess != null) minFactor++;
   20748             if (factor < minFactor) factor = minFactor;
   20749             int curLevel = ComponentCallbacks2.TRIM_MEMORY_COMPLETE;
   20750             for (int i=N-1; i>=0; i--) {
   20751                 ProcessRecord app = mLruProcesses.get(i);
   20752                 if (allChanged || app.procStateChanged) {
   20753                     setProcessTrackerStateLocked(app, trackerMemFactor, now);
   20754                     app.procStateChanged = false;
   20755                 }
   20756                 if (app.curProcState >= ActivityManager.PROCESS_STATE_HOME
   20757                         && !app.killedByAm) {
   20758                     if (app.trimMemoryLevel < curLevel && app.thread != null) {
   20759                         try {
   20760                             if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
   20761                                     "Trimming memory of " + app.processName + " to " + curLevel);
   20762                             app.thread.scheduleTrimMemory(curLevel);
   20763                         } catch (RemoteException e) {
   20764                         }
   20765                         if (false) {
   20766                             // For now we won't do this; our memory trimming seems
   20767                             // to be good enough at this point that destroying
   20768                             // activities causes more harm than good.
   20769                             if (curLevel >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE
   20770                                     && app != mHomeProcess && app != mPreviousProcess) {
   20771                                 // Need to do this on its own message because the stack may not
   20772                                 // be in a consistent state at this point.
   20773                                 // For these apps we will also finish their activities
   20774                                 // to help them free memory.
   20775                                 mStackSupervisor.scheduleDestroyAllActivities(app, "trim");
   20776                             }
   20777                         }
   20778                     }
   20779                     app.trimMemoryLevel = curLevel;
   20780                     step++;
   20781                     if (step >= factor) {
   20782                         step = 0;
   20783                         switch (curLevel) {
   20784                             case ComponentCallbacks2.TRIM_MEMORY_COMPLETE:
   20785                                 curLevel = ComponentCallbacks2.TRIM_MEMORY_MODERATE;
   20786                                 break;
   20787                             case ComponentCallbacks2.TRIM_MEMORY_MODERATE:
   20788                                 curLevel = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
   20789                                 break;
   20790                         }
   20791                     }
   20792                 } else if (app.curProcState == ActivityManager.PROCESS_STATE_HEAVY_WEIGHT) {
   20793                     if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_BACKGROUND
   20794                             && app.thread != null) {
   20795                         try {
   20796                             if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
   20797                                     "Trimming memory of heavy-weight " + app.processName
   20798                                     + " to " + ComponentCallbacks2.TRIM_MEMORY_BACKGROUND);
   20799                             app.thread.scheduleTrimMemory(
   20800                                     ComponentCallbacks2.TRIM_MEMORY_BACKGROUND);
   20801                         } catch (RemoteException e) {
   20802                         }
   20803                     }
   20804                     app.trimMemoryLevel = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
   20805                 } else {
   20806                     if ((app.curProcState >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
   20807                             || app.systemNoUi) && app.pendingUiClean) {
   20808                         // If this application is now in the background and it
   20809                         // had done UI, then give it the special trim level to
   20810                         // have it free UI resources.
   20811                         final int level = ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN;
   20812                         if (app.trimMemoryLevel < level && app.thread != null) {
   20813                             try {
   20814                                 if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
   20815                                         "Trimming memory of bg-ui " + app.processName
   20816                                         + " to " + level);
   20817                                 app.thread.scheduleTrimMemory(level);
   20818                             } catch (RemoteException e) {
   20819                             }
   20820                         }
   20821                         app.pendingUiClean = false;
   20822                     }
   20823                     if (app.trimMemoryLevel < fgTrimLevel && app.thread != null) {
   20824                         try {
   20825                             if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
   20826                                     "Trimming memory of fg " + app.processName
   20827                                     + " to " + fgTrimLevel);
   20828                             app.thread.scheduleTrimMemory(fgTrimLevel);
   20829                         } catch (RemoteException e) {
   20830                         }
   20831                     }
   20832                     app.trimMemoryLevel = fgTrimLevel;
   20833                 }
   20834             }
   20835         } else {
   20836             if (mLowRamStartTime != 0) {
   20837                 mLowRamTimeSinceLastIdle += now - mLowRamStartTime;
   20838                 mLowRamStartTime = 0;
   20839             }
   20840             for (int i=N-1; i>=0; i--) {
   20841                 ProcessRecord app = mLruProcesses.get(i);
   20842                 if (allChanged || app.procStateChanged) {
   20843                     setProcessTrackerStateLocked(app, trackerMemFactor, now);
   20844                     app.procStateChanged = false;
   20845                 }
   20846                 if ((app.curProcState >= ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND
   20847                         || app.systemNoUi) && app.pendingUiClean) {
   20848                     if (app.trimMemoryLevel < ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN
   20849                             && app.thread != null) {
   20850                         try {
   20851                             if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(TAG_OOM_ADJ,
   20852                                     "Trimming memory of ui hidden " + app.processName
   20853                                     + " to " + ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
   20854                             app.thread.scheduleTrimMemory(
   20855                                     ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
   20856                         } catch (RemoteException e) {
   20857                         }
   20858                     }
   20859                     app.pendingUiClean = false;
   20860                 }
   20861                 app.trimMemoryLevel = 0;
   20862             }
   20863         }
   20864 
   20865         if (mAlwaysFinishActivities) {
   20866             // Need to do this on its own message because the stack may not
   20867             // be in a consistent state at this point.
   20868             mStackSupervisor.scheduleDestroyAllActivities(null, "always-finish");
   20869         }
   20870 
   20871         if (allChanged) {
   20872             requestPssAllProcsLocked(now, false, mProcessStats.isMemFactorLowered());
   20873         }
   20874 
   20875         // Update from any uid changes.
   20876         for (int i=mActiveUids.size()-1; i>=0; i--) {
   20877             final UidRecord uidRec = mActiveUids.valueAt(i);
   20878             int uidChange = UidRecord.CHANGE_PROCSTATE;
   20879             if (uidRec.setProcState != uidRec.curProcState) {
   20880                 if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
   20881                         "Changes in " + uidRec + ": proc state from " + uidRec.setProcState
   20882                         + " to " + uidRec.curProcState);
   20883                 if (ActivityManager.isProcStateBackground(uidRec.curProcState)) {
   20884                     if (!ActivityManager.isProcStateBackground(uidRec.setProcState)) {
   20885                         uidRec.lastBackgroundTime = nowElapsed;
   20886                         if (!mHandler.hasMessages(IDLE_UIDS_MSG)) {
   20887                             // Note: the background settle time is in elapsed realtime, while
   20888                             // the handler time base is uptime.  All this means is that we may
   20889                             // stop background uids later than we had intended, but that only
   20890                             // happens because the device was sleeping so we are okay anyway.
   20891                             mHandler.sendEmptyMessageDelayed(IDLE_UIDS_MSG, BACKGROUND_SETTLE_TIME);
   20892                         }
   20893                     }
   20894                 } else {
   20895                     if (uidRec.idle) {
   20896                         uidChange = UidRecord.CHANGE_ACTIVE;
   20897                         uidRec.idle = false;
   20898                     }
   20899                     uidRec.lastBackgroundTime = 0;
   20900                 }
   20901                 uidRec.setProcState = uidRec.curProcState;
   20902                 enqueueUidChangeLocked(uidRec, -1, uidChange);
   20903                 noteUidProcessState(uidRec.uid, uidRec.curProcState);
   20904             }
   20905         }
   20906 
   20907         if (mProcessStats.shouldWriteNowLocked(now)) {
   20908             mHandler.post(new Runnable() {
   20909                 @Override public void run() {
   20910                     synchronized (ActivityManagerService.this) {
   20911                         mProcessStats.writeStateAsyncLocked();
   20912                     }
   20913                 }
   20914             });
   20915         }
   20916 
   20917         if (DEBUG_OOM_ADJ) {
   20918             final long duration = SystemClock.uptimeMillis() - now;
   20919             if (false) {
   20920                 Slog.d(TAG_OOM_ADJ, "Did OOM ADJ in " + duration + "ms",    <========
   20921                         new RuntimeException("here").fillInStackTrace());
   20922             } else {
   20923                 Slog.d(TAG_OOM_ADJ, "Did OOM ADJ in " + duration + "ms");   <========
   20924             }
   20925         }
   20926     }