Loading services/core/java/com/android/server/am/ActiveServices.java +2 −2 Original line number Original line Diff line number Diff line Loading @@ -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 Loading Loading @@ -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 { Loading services/core/java/com/android/server/am/ActivityManagerConstants.java +26 −0 Original line number Original line Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; } } Loading Loading @@ -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) { Loading Loading @@ -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, Loading Loading @@ -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); } } } } services/core/java/com/android/server/am/ActivityManagerService.java +21 −138 Original line number Original line Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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"); } } Loading Loading @@ -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); Loading @@ -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); } } } } Loading @@ -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; Loading Loading @@ -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); } } } } } } Loading Loading @@ -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. Loading Loading @@ -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); } } } } } } Loading Loading @@ -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) Loading Loading @@ -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); services/core/java/com/android/server/am/BroadcastQueue.java +1 −1 Original line number Original line Diff line number Diff line Loading @@ -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. Loading services/core/java/com/android/server/am/OomAdjProfiler.java +36 −10 Original line number Original line Diff line number Diff line Loading @@ -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; Loading @@ -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(); Loading @@ -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; } } } } Loading @@ -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++; } } } } Loading Loading @@ -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
services/core/java/com/android/server/am/ActiveServices.java +2 −2 Original line number Original line Diff line number Diff line Loading @@ -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 Loading Loading @@ -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 { Loading
services/core/java/com/android/server/am/ActivityManagerConstants.java +26 −0 Original line number Original line Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; } } Loading Loading @@ -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) { Loading Loading @@ -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, Loading Loading @@ -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); } } } }
services/core/java/com/android/server/am/ActivityManagerService.java +21 −138 Original line number Original line Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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"); } } Loading Loading @@ -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); Loading @@ -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); } } } } Loading @@ -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; Loading Loading @@ -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); } } } } } } Loading Loading @@ -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. Loading Loading @@ -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); } } } } } } Loading Loading @@ -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) Loading Loading @@ -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);
services/core/java/com/android/server/am/BroadcastQueue.java +1 −1 Original line number Original line Diff line number Diff line Loading @@ -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. Loading
services/core/java/com/android/server/am/OomAdjProfiler.java +36 −10 Original line number Original line Diff line number Diff line Loading @@ -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; Loading @@ -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(); Loading @@ -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; } } } } Loading @@ -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++; } } } } Loading Loading @@ -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) + "]"; } } } } } }