Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0c69030d authored by Jing Ji's avatar Jing Ji Committed by Android (Google) Code Review
Browse files

Merge "OomAdjust Performance Improvement"

parents f5a5d65b 094c3ef6
Loading
Loading
Loading
Loading
+2 −2
Original line number Original line Diff line number Diff line
@@ -1819,7 +1819,7 @@ public final class ActiveServices {
                                || (callerApp.getCurProcState() <= ActivityManager.PROCESS_STATE_TOP
                                || (callerApp.getCurProcState() <= ActivityManager.PROCESS_STATE_TOP
                                        && (flags & Context.BIND_TREAT_LIKE_ACTIVITY) != 0),
                                        && (flags & Context.BIND_TREAT_LIKE_ACTIVITY) != 0),
                        b.client);
                        b.client);
                mAm.updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_BIND_SERVICE);
                mAm.updateOomAdjLocked(s.app, OomAdjuster.OOM_ADJ_REASON_BIND_SERVICE);
            }
            }


            if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Bind " + s + " with " + b
            if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Bind " + s + " with " + b
@@ -2701,7 +2701,7 @@ public final class ActiveServices {
        bumpServiceExecutingLocked(r, execInFg, "create");
        bumpServiceExecutingLocked(r, execInFg, "create");
        mAm.updateLruProcessLocked(app, false, null);
        mAm.updateLruProcessLocked(app, false, null);
        updateServiceForegroundLocked(r.app, /* oomAdj= */ false);
        updateServiceForegroundLocked(r.app, /* oomAdj= */ false);
        mAm.updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_START_SERVICE);
        mAm.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_START_SERVICE);


        boolean created = false;
        boolean created = false;
        try {
        try {
+26 −0
Original line number Original line Diff line number Diff line
@@ -282,6 +282,19 @@ final class ActivityManagerConstants extends ContentObserver {
    // memory trimming.
    // memory trimming.
    public int CUR_TRIM_CACHED_PROCESSES;
    public int CUR_TRIM_CACHED_PROCESSES;


    @SuppressWarnings("unused")
    private static final int OOMADJ_UPDATE_POLICY_SLOW = 0;
    private static final int OOMADJ_UPDATE_POLICY_QUICK = 1;
    private static final int DEFAULT_OOMADJ_UPDATE_POLICY = OOMADJ_UPDATE_POLICY_QUICK;

    private static final String KEY_OOMADJ_UPDATE_POLICY = "oomadj_update_policy";

    // Indicate if the oom adjuster should take the quick path to update the oom adj scores,
    // in which no futher actions will be performed if there are no significant adj/proc state
    // changes for the specific process; otherwise, use the traditonal slow path which would
    // keep updating all processes in the LRU list.
    public boolean OOMADJ_UPDATE_QUICK = DEFAULT_OOMADJ_UPDATE_POLICY == OOMADJ_UPDATE_POLICY_QUICK;

    private static final long MIN_AUTOMATIC_HEAP_DUMP_PSS_THRESHOLD_BYTES = 100 * 1024; // 100 KB
    private static final long MIN_AUTOMATIC_HEAP_DUMP_PSS_THRESHOLD_BYTES = 100 * 1024; // 100 KB


    private final boolean mSystemServerAutomaticHeapDumpEnabled;
    private final boolean mSystemServerAutomaticHeapDumpEnabled;
@@ -316,6 +329,9 @@ final class ActivityManagerConstants extends ContentObserver {
                            case KEY_DEFAULT_BACKGROUND_ACTIVITY_STARTS_ENABLED:
                            case KEY_DEFAULT_BACKGROUND_ACTIVITY_STARTS_ENABLED:
                                updateBackgroundActivityStarts();
                                updateBackgroundActivityStarts();
                                break;
                                break;
                            case KEY_OOMADJ_UPDATE_POLICY:
                                updateOomAdjUpdatePolicy();
                                break;
                            default:
                            default:
                                break;
                                break;
                        }
                        }
@@ -354,6 +370,7 @@ final class ActivityManagerConstants extends ContentObserver {
        updateMaxCachedProcesses();
        updateMaxCachedProcesses();
        updateActivityStartsLoggingEnabled();
        updateActivityStartsLoggingEnabled();
        updateBackgroundActivityStarts();
        updateBackgroundActivityStarts();
        updateOomAdjUpdatePolicy();
    }
    }


    public void setOverrideMaxCachedProcesses(int value) {
    public void setOverrideMaxCachedProcesses(int value) {
@@ -472,6 +489,14 @@ final class ActivityManagerConstants extends ContentObserver {
                /*defaultValue*/ false);
                /*defaultValue*/ false);
    }
    }


    private void updateOomAdjUpdatePolicy() {
        OOMADJ_UPDATE_QUICK = DeviceConfig.getInt(
                DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                KEY_OOMADJ_UPDATE_POLICY,
                /* defaultValue */ DEFAULT_OOMADJ_UPDATE_POLICY)
                == OOMADJ_UPDATE_POLICY_QUICK;
    }

    private void updateEnableAutomaticSystemServerHeapDumps() {
    private void updateEnableAutomaticSystemServerHeapDumps() {
        if (!mSystemServerAutomaticHeapDumpEnabled) {
        if (!mSystemServerAutomaticHeapDumpEnabled) {
            Slog.wtf(TAG,
            Slog.wtf(TAG,
@@ -587,5 +612,6 @@ final class ActivityManagerConstants extends ContentObserver {
        pw.print("  CUR_MAX_EMPTY_PROCESSES="); pw.println(CUR_MAX_EMPTY_PROCESSES);
        pw.print("  CUR_MAX_EMPTY_PROCESSES="); pw.println(CUR_MAX_EMPTY_PROCESSES);
        pw.print("  CUR_TRIM_EMPTY_PROCESSES="); pw.println(CUR_TRIM_EMPTY_PROCESSES);
        pw.print("  CUR_TRIM_EMPTY_PROCESSES="); pw.println(CUR_TRIM_EMPTY_PROCESSES);
        pw.print("  CUR_TRIM_CACHED_PROCESSES="); pw.println(CUR_TRIM_CACHED_PROCESSES);
        pw.print("  CUR_TRIM_CACHED_PROCESSES="); pw.println(CUR_TRIM_CACHED_PROCESSES);
        pw.print("  OOMADJ_UPDATE_QUICK="); pw.println(OOMADJ_UPDATE_QUICK);
    }
    }
}
}
+21 −138
Original line number Original line Diff line number Diff line
@@ -42,8 +42,6 @@ import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_UNAWARE;
import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES;
import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.net.NetworkPolicyManager.isProcStateAllowedWhileIdleOrPowerSaveMode;
import static android.net.NetworkPolicyManager.isProcStateAllowedWhileOnRestrictBackground;
import static android.os.FactoryTest.FACTORY_TEST_OFF;
import static android.os.FactoryTest.FACTORY_TEST_OFF;
import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_CRITICAL;
import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_CRITICAL;
import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_HIGH;
import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_HIGH;
@@ -422,7 +420,7 @@ public class ActivityManagerService extends IActivityManager.Stub
    private static final String TAG_LOCKTASK = TAG + POSTFIX_LOCKTASK;
    private static final String TAG_LOCKTASK = TAG + POSTFIX_LOCKTASK;
    static final String TAG_LRU = TAG + POSTFIX_LRU;
    static final String TAG_LRU = TAG + POSTFIX_LRU;
    private static final String TAG_MU = TAG + POSTFIX_MU;
    private static final String TAG_MU = TAG + POSTFIX_MU;
    private static final String TAG_NETWORK = TAG + POSTFIX_NETWORK;
    static final String TAG_NETWORK = TAG + POSTFIX_NETWORK;
    static final String TAG_OOM_ADJ = TAG + POSTFIX_OOM_ADJ;
    static final String TAG_OOM_ADJ = TAG + POSTFIX_OOM_ADJ;
    private static final String TAG_POWER = TAG + POSTFIX_POWER;
    private static final String TAG_POWER = TAG + POSTFIX_POWER;
    static final String TAG_PROCESS_OBSERVERS = TAG + POSTFIX_PROCESS_OBSERVERS;
    static final String TAG_PROCESS_OBSERVERS = TAG + POSTFIX_PROCESS_OBSERVERS;
@@ -532,24 +530,6 @@ public class ActivityManagerService extends IActivityManager.Stub
     */
     */
    private static final int BINDER_PROXY_LOW_WATERMARK = 5500;
    private static final int BINDER_PROXY_LOW_WATERMARK = 5500;
    /**
     * State indicating that there is no need for any blocking for network.
     */
    @VisibleForTesting
    static final int NETWORK_STATE_NO_CHANGE = 0;
    /**
     * State indicating that the main thread needs to be informed about the network wait.
     */
    @VisibleForTesting
    static final int NETWORK_STATE_BLOCK = 1;
    /**
     * State indicating that any threads waiting for network state to get updated can be unblocked.
     */
    @VisibleForTesting
    static final int NETWORK_STATE_UNBLOCK = 2;
    // Max character limit for a notification title. If the notification title is larger than this
    // Max character limit for a notification title. If the notification title is larger than this
    // the notification will not be legible to the user.
    // the notification will not be legible to the user.
    private static final int MAX_BUGREPORT_TITLE_SIZE = 50;
    private static final int MAX_BUGREPORT_TITLE_SIZE = 50;
@@ -1363,7 +1343,7 @@ public class ActivityManagerService extends IActivityManager.Stub
    String mTrackAllocationApp = null;
    String mTrackAllocationApp = null;
    String mNativeDebuggingApp = null;
    String mNativeDebuggingApp = null;
    private final Injector mInjector;
    final Injector mInjector;
    static final class ProcessChangeItem {
    static final class ProcessChangeItem {
        static final int CHANGE_ACTIVITIES = 1<<0;
        static final int CHANGE_ACTIVITIES = 1<<0;
@@ -5174,7 +5154,7 @@ public class ActivityManagerService extends IActivityManager.Stub
        }
        }
        if (!didSomething) {
        if (!didSomething) {
            updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_PROCESS_BEGIN);
            updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_PROCESS_BEGIN);
            checkTime(startTime, "attachApplicationLocked: after updateOomAdjLocked");
            checkTime(startTime, "attachApplicationLocked: after updateOomAdjLocked");
        }
        }
@@ -5689,6 +5669,7 @@ public class ActivityManagerService extends IActivityManager.Stub
    void importanceTokenDied(ImportanceToken token) {
    void importanceTokenDied(ImportanceToken token) {
        synchronized (ActivityManagerService.this) {
        synchronized (ActivityManagerService.this) {
            ProcessRecord pr = null;
            synchronized (mPidsSelfLocked) {
            synchronized (mPidsSelfLocked) {
                ImportanceToken cur
                ImportanceToken cur
                    = mImportantProcesses.get(token.pid);
                    = mImportantProcesses.get(token.pid);
@@ -5696,14 +5677,14 @@ public class ActivityManagerService extends IActivityManager.Stub
                    return;
                    return;
                }
                }
                mImportantProcesses.remove(token.pid);
                mImportantProcesses.remove(token.pid);
                ProcessRecord pr = mPidsSelfLocked.get(token.pid);
                pr = mPidsSelfLocked.get(token.pid);
                if (pr == null) {
                if (pr == null) {
                    return;
                    return;
                }
                }
                pr.forcingToImportant = null;
                pr.forcingToImportant = null;
                updateProcessForegroundLocked(pr, false, 0, false);
                updateProcessForegroundLocked(pr, false, 0, false);
            }
            }
            updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_UI_VISIBILITY);
            updateOomAdjLocked(pr, OomAdjuster.OOM_ADJ_REASON_UI_VISIBILITY);
        }
        }
    }
    }
@@ -5714,8 +5695,9 @@ public class ActivityManagerService extends IActivityManager.Stub
        synchronized(this) {
        synchronized(this) {
            boolean changed = false;
            boolean changed = false;
            ProcessRecord pr = null;
            synchronized (mPidsSelfLocked) {
            synchronized (mPidsSelfLocked) {
                ProcessRecord pr = mPidsSelfLocked.get(pid);
                pr = mPidsSelfLocked.get(pid);
                if (pr == null && isForeground) {
                if (pr == null && isForeground) {
                    Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
                    Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
                    return;
                    return;
@@ -5749,7 +5731,7 @@ public class ActivityManagerService extends IActivityManager.Stub
            }
            }
            if (changed) {
            if (changed) {
                updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_UI_VISIBILITY);
                updateOomAdjLocked(pr, OomAdjuster.OOM_ADJ_REASON_UI_VISIBILITY);
            }
            }
        }
        }
    }
    }
@@ -7893,7 +7875,7 @@ public class ActivityManagerService extends IActivityManager.Stub
                    new HostingRecord("added application",
                    new HostingRecord("added application",
                            customProcess != null ? customProcess : info.processName));
                            customProcess != null ? customProcess : info.processName));
            mProcessList.updateLruProcessLocked(app, false, null);
            mProcessList.updateLruProcessLocked(app, false, null);
            updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_PROCESS_BEGIN);
            updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_PROCESS_BEGIN);
        }
        }
        // This package really, really can not be stopped.
        // This package really, really can not be stopped.
@@ -17010,7 +16992,7 @@ public class ActivityManagerService extends IActivityManager.Stub
            item.foregroundServiceTypes = fgServiceTypes;
            item.foregroundServiceTypes = fgServiceTypes;
            if (oomAdj) {
            if (oomAdj) {
                updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_UI_VISIBILITY);
                updateOomAdjLocked(proc, OomAdjuster.OOM_ADJ_REASON_UI_VISIBILITY);
            }
            }
        }
        }
    }
    }
@@ -17265,6 +17247,16 @@ public class ActivityManagerService extends IActivityManager.Stub
        mOomAdjuster.updateOomAdjLocked(oomAdjReason);
        mOomAdjuster.updateOomAdjLocked(oomAdjReason);
    }
    }
    /*
     * Update OomAdj for a specific process and its reachable processes.
     * @param app The process to update
     * @param oomAdjReason
     */
    @GuardedBy("this")
    final void updateOomAdjLocked(ProcessRecord app, String oomAdjReason) {
        mOomAdjuster.updateOomAdjLocked(app, oomAdjReason);
    }
    @Override
    @Override
    public void makePackageIdle(String packageName, int userId) {
    public void makePackageIdle(String packageName, int userId) {
        if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
        if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
@@ -17331,115 +17323,6 @@ public class ActivityManagerService extends IActivityManager.Stub
        }
        }
    }
    }
    /**
     * Checks if any uid is coming from background to foreground or vice versa and if so, increments
     * the {@link UidRecord#curProcStateSeq} corresponding to that uid using global seq counter
     * {@link ProcessList#mProcStateSeqCounter} and notifies the app if it needs to block.
     */
    @VisibleForTesting
    @GuardedBy("this")
    void incrementProcStateSeqAndNotifyAppsLocked() {
        if (mWaitForNetworkTimeoutMs <= 0) {
            return;
        }
        // Used for identifying which uids need to block for network.
        ArrayList<Integer> blockingUids = null;
        for (int i = mProcessList.mActiveUids.size() - 1; i >= 0; --i) {
            final UidRecord uidRec = mProcessList.mActiveUids.valueAt(i);
            // If the network is not restricted for uid, then nothing to do here.
            if (!mInjector.isNetworkRestrictedForUid(uidRec.uid)) {
                continue;
            }
            if (!UserHandle.isApp(uidRec.uid) || !uidRec.hasInternetPermission) {
                continue;
            }
            // If process state is not changed, then there's nothing to do.
            if (uidRec.setProcState == uidRec.getCurProcState()) {
                continue;
            }
            final int blockState = getBlockStateForUid(uidRec);
            // No need to inform the app when the blockState is NETWORK_STATE_NO_CHANGE as
            // there's nothing the app needs to do in this scenario.
            if (blockState == NETWORK_STATE_NO_CHANGE) {
                continue;
            }
            synchronized (uidRec.networkStateLock) {
                uidRec.curProcStateSeq = ++mProcessList.mProcStateSeqCounter; // TODO: use method
                if (blockState == NETWORK_STATE_BLOCK) {
                    if (blockingUids == null) {
                        blockingUids = new ArrayList<>();
                    }
                    blockingUids.add(uidRec.uid);
                } else {
                    if (DEBUG_NETWORK) {
                        Slog.d(TAG_NETWORK, "uid going to background, notifying all blocking"
                                + " threads for uid: " + uidRec);
                    }
                    if (uidRec.waitingForNetwork) {
                        uidRec.networkStateLock.notifyAll();
                    }
                }
            }
        }
        // There are no uids that need to block, so nothing more to do.
        if (blockingUids == null) {
            return;
        }
        for (int i = mProcessList.mLruProcesses.size() - 1; i >= 0; --i) {
            final ProcessRecord app = mProcessList.mLruProcesses.get(i);
            if (!blockingUids.contains(app.uid)) {
                continue;
            }
            if (!app.killedByAm && app.thread != null) {
                final UidRecord uidRec = mProcessList.getUidRecordLocked(app.uid);
                try {
                    if (DEBUG_NETWORK) {
                        Slog.d(TAG_NETWORK, "Informing app thread that it needs to block: "
                                + uidRec);
                    }
                    if (uidRec != null) {
                        app.thread.setNetworkBlockSeq(uidRec.curProcStateSeq);
                    }
                } catch (RemoteException ignored) {
                }
            }
        }
    }
    /**
     * Checks if the uid is coming from background to foreground or vice versa and returns
     * appropriate block state based on this.
     *
     * @return blockState based on whether the uid is coming from background to foreground or
     *         vice versa. If bg->fg or fg->bg, then {@link #NETWORK_STATE_BLOCK} or
     *         {@link #NETWORK_STATE_UNBLOCK} respectively, otherwise
     *         {@link #NETWORK_STATE_NO_CHANGE}.
     */
    @VisibleForTesting
    int getBlockStateForUid(UidRecord uidRec) {
        // Denotes whether uid's process state is currently allowed network access.
        final boolean isAllowed =
                isProcStateAllowedWhileIdleOrPowerSaveMode(uidRec.getCurProcState())
                || isProcStateAllowedWhileOnRestrictBackground(uidRec.getCurProcState());
        // Denotes whether uid's process state was previously allowed network access.
        final boolean wasAllowed = isProcStateAllowedWhileIdleOrPowerSaveMode(uidRec.setProcState)
                || isProcStateAllowedWhileOnRestrictBackground(uidRec.setProcState);
        // When the uid is coming to foreground, AMS should inform the app thread that it should
        // block for the network rules to get updated before launching an activity.
        if (!wasAllowed && isAllowed) {
            return NETWORK_STATE_BLOCK;
        }
        // When the uid is going to background, AMS should inform the app thread that if an
        // activity launch is blocked for the network rules to get updated, it should be unblocked.
        if (wasAllowed && !isAllowed) {
            return NETWORK_STATE_UNBLOCK;
        }
        return NETWORK_STATE_NO_CHANGE;
    }
    final void runInBackgroundDisabled(int uid) {
    final void runInBackgroundDisabled(int uid) {
        synchronized (this) {
        synchronized (this) {
            UidRecord uidRec = mProcessList.getUidRecordLocked(uid);
            UidRecord uidRec = mProcessList.getUidRecordLocked(uid);
+1 −1
Original line number Original line Diff line number Diff line
@@ -309,7 +309,7 @@ public final class BroadcastQueue {
        app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_RECEIVER);
        app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_RECEIVER);
        mService.mProcessList.updateLruProcessLocked(app, false, null);
        mService.mProcessList.updateLruProcessLocked(app, false, null);
        if (!skipOomAdj) {
        if (!skipOomAdj) {
            mService.updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_NONE);
            mService.updateOomAdjLocked(app, OomAdjuster.OOM_ADJ_REASON_NONE);
        }
        }


        // Tell the application to launch this receiver.
        // Tell the application to launch this receiver.
+36 −10
Original line number Original line Diff line number Diff line
@@ -45,7 +45,7 @@ public class OomAdjProfiler {
    private boolean mLastScheduledScreenOff;
    private boolean mLastScheduledScreenOff;


    @GuardedBy("this")
    @GuardedBy("this")
    private long mOomAdjStartTimeMs;
    private long mOomAdjStartTimeUs;
    @GuardedBy("this")
    @GuardedBy("this")
    private boolean mOomAdjStarted;
    private boolean mOomAdjStarted;


@@ -65,6 +65,11 @@ public class OomAdjProfiler {
    @GuardedBy("this")
    @GuardedBy("this")
    final RingBuffer<CpuTimes> mSystemServerCpuTimesHist = new RingBuffer<>(CpuTimes.class, 10);
    final RingBuffer<CpuTimes> mSystemServerCpuTimesHist = new RingBuffer<>(CpuTimes.class, 10);


    @GuardedBy("this")
    private long mTotalOomAdjRunTimeUs;
    @GuardedBy("this")
    private int mTotalOomAdjCalls;

    void batteryPowerChanged(boolean onBattery) {
    void batteryPowerChanged(boolean onBattery) {
        synchronized (this) {
        synchronized (this) {
            scheduleSystemServerCpuTimeUpdate();
            scheduleSystemServerCpuTimeUpdate();
@@ -81,7 +86,7 @@ public class OomAdjProfiler {


    void oomAdjStarted() {
    void oomAdjStarted() {
        synchronized (this) {
        synchronized (this) {
            mOomAdjStartTimeMs = SystemClock.currentThreadTimeMillis();
            mOomAdjStartTimeUs = SystemClock.currentThreadTimeMicro();
            mOomAdjStarted = true;
            mOomAdjStarted = true;
        }
        }
    }
    }
@@ -91,7 +96,10 @@ public class OomAdjProfiler {
            if (!mOomAdjStarted) {
            if (!mOomAdjStarted) {
                return;
                return;
            }
            }
            mOomAdjRunTime.addCpuTimeMs(SystemClock.currentThreadTimeMillis() - mOomAdjStartTimeMs);
            long elapsedUs = SystemClock.currentThreadTimeMicro() - mOomAdjStartTimeUs;
            mOomAdjRunTime.addCpuTimeUs(elapsedUs);
            mTotalOomAdjRunTimeUs += elapsedUs;
            mTotalOomAdjCalls++;
        }
        }
    }
    }


@@ -169,32 +177,50 @@ public class OomAdjProfiler {
                pw.print("oom_adj=");
                pw.print("oom_adj=");
                pw.println(oomAdjRunTimes[i]);
                pw.println(oomAdjRunTimes[i]);
            }
            }
            if (mTotalOomAdjCalls != 0) {
                pw.println("System server total oomAdj runtimes (us) since boot:");
                pw.print("  cpu time spent=");
                pw.print(mTotalOomAdjRunTimeUs);
                pw.print("  number of calls=");
                pw.print(mTotalOomAdjCalls);
                pw.print("  average=");
                pw.println(mTotalOomAdjRunTimeUs / mTotalOomAdjCalls);
            }
        }
        }
    }
    }


    private class CpuTimes {
    private class CpuTimes {
        private long mOnBatteryTimeMs;
        private long mOnBatteryTimeUs;
        private long mOnBatteryScreenOffTimeMs;
        private long mOnBatteryScreenOffTimeUs;


        public void addCpuTimeMs(long cpuTimeMs) {
        public void addCpuTimeMs(long cpuTimeMs) {
            addCpuTimeMs(cpuTimeMs, mOnBattery, mScreenOff);
            addCpuTimeUs(cpuTimeMs * 1000, mOnBattery, mScreenOff);
        }
        }


        public void addCpuTimeMs(long cpuTimeMs, boolean onBattery, boolean screenOff) {
        public void addCpuTimeMs(long cpuTimeMs, boolean onBattery, boolean screenOff) {
            addCpuTimeUs(cpuTimeMs * 1000, onBattery, screenOff);
        }

        public void addCpuTimeUs(long cpuTimeUs) {
            addCpuTimeUs(cpuTimeUs, mOnBattery, mScreenOff);
        }

        public void addCpuTimeUs(long cpuTimeUs, boolean onBattery, boolean screenOff) {
            if (onBattery) {
            if (onBattery) {
                mOnBatteryTimeMs += cpuTimeMs;
                mOnBatteryTimeUs += cpuTimeUs;
                if (screenOff) {
                if (screenOff) {
                    mOnBatteryScreenOffTimeMs += cpuTimeMs;
                    mOnBatteryScreenOffTimeUs += cpuTimeUs;
                }
                }
            }
            }
        }
        }


        public boolean isEmpty() {
        public boolean isEmpty() {
            return mOnBatteryTimeMs == 0 && mOnBatteryScreenOffTimeMs == 0;
            return mOnBatteryTimeUs == 0 && mOnBatteryScreenOffTimeUs == 0;
        }
        }


        public String toString() {
        public String toString() {
            return "[" + mOnBatteryTimeMs + "," + mOnBatteryScreenOffTimeMs + "]";
            return "[" + (mOnBatteryTimeUs / 1000) + ","
                    + (mOnBatteryScreenOffTimeUs / 1000) + "]";
        }
        }
    }
    }
}
}
Loading