diff options
11 files changed, 649 insertions, 63 deletions
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java index b077e06..12e1963 100644 --- a/core/java/android/hardware/display/DisplayManager.java +++ b/core/java/android/hardware/display/DisplayManager.java @@ -472,7 +472,8 @@ public final class DisplayManager { /** * Creates a virtual display. * - * @see #createVirtualDisplay(String, int, int, int, Surface, int, VirtualDisplay.Callback) + * @see #createVirtualDisplay(String, int, int, int, Surface, int, + * VirtualDisplay.Callback, Handler) */ public VirtualDisplay createVirtualDisplay(@NonNull String name, int width, int height, int densityDpi, @Nullable Surface surface, int flags) { diff --git a/core/java/android/net/INetworkPolicyManager.aidl b/core/java/android/net/INetworkPolicyManager.aidl index 1129c9e..7e92de2 100644 --- a/core/java/android/net/INetworkPolicyManager.aidl +++ b/core/java/android/net/INetworkPolicyManager.aidl @@ -54,7 +54,8 @@ interface INetworkPolicyManager { void setRestrictBackground(boolean restrictBackground); boolean getRestrictBackground(); + void setDeviceIdleMode(boolean enabled); + NetworkQuotaInfo getNetworkQuotaInfo(in NetworkState state); boolean isNetworkMetered(in NetworkState state); - } diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index d96a0e9..cab03da 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -30,7 +30,6 @@ import android.content.pm.ApplicationInfo; import android.telephony.SignalStrength; import android.text.format.DateFormat; import android.util.Printer; -import android.util.Slog; import android.util.SparseArray; import android.util.SparseIntArray; import android.util.TimeUtils; @@ -1044,14 +1043,15 @@ public abstract class BatteryStats implements Parcelable { public static final int STATE2_WIFI_SIGNAL_STRENGTH_MASK = 0x7 << STATE2_WIFI_SIGNAL_STRENGTH_SHIFT; - public static final int STATE2_LOW_POWER_FLAG = 1<<31; + public static final int STATE2_POWER_SAVE_FLAG = 1<<31; public static final int STATE2_VIDEO_ON_FLAG = 1<<30; public static final int STATE2_WIFI_RUNNING_FLAG = 1<<29; public static final int STATE2_WIFI_ON_FLAG = 1<<28; public static final int STATE2_FLASHLIGHT_FLAG = 1<<27; + public static final int STATE2_DEVICE_IDLE_FLAG = 1<<26; public static final int MOST_INTERESTING_STATES2 = - STATE2_LOW_POWER_FLAG | STATE2_WIFI_ON_FLAG; + STATE2_POWER_SAVE_FLAG | STATE2_WIFI_ON_FLAG | STATE2_DEVICE_IDLE_FLAG; public int states2; @@ -1086,10 +1086,18 @@ public abstract class BatteryStats implements Parcelable { public static final int EVENT_USER_RUNNING = 0x0007; // Events for foreground user. public static final int EVENT_USER_FOREGROUND = 0x0008; - // Events for connectivity changed. + // Event for connectivity changed. public static final int EVENT_CONNECTIVITY_CHANGED = 0x0009; + // Event for significant motion taking us out of idle mode. + public static final int EVENT_SIGNIFICANT_MOTION = 0x000a; + // Event for becoming active taking us out of idle mode. + public static final int EVENT_ACTIVE = 0x000b; + // Event for a package being installed. + public static final int EVENT_PACKAGE_INSTALLED = 0x000c; + // Event for a package being uninstalled. + public static final int EVENT_PACKAGE_UNINSTALLED = 0x000d; // Number of event types. - public static final int EVENT_COUNT = 0x000a; + public static final int EVENT_COUNT = 0x000e; // Mask to extract out only the type part of the event. public static final int EVENT_TYPE_MASK = ~(EVENT_FLAG_START|EVENT_FLAG_FINISH); @@ -1486,19 +1494,34 @@ public abstract class BatteryStats implements Parcelable { long elapsedRealtimeUs, int which); /** - * Returns the time in microseconds that low power mode has been enabled while the device was + * Returns the time in microseconds that power save mode has been enabled while the device was * running on battery. * * {@hide} */ - public abstract long getLowPowerModeEnabledTime(long elapsedRealtimeUs, int which); + public abstract long getPowerSaveModeEnabledTime(long elapsedRealtimeUs, int which); /** - * Returns the number of times that low power mode was enabled. + * Returns the number of times that power save mode was enabled. * * {@hide} */ - public abstract int getLowPowerModeEnabledCount(int which); + public abstract int getPowerSaveModeEnabledCount(int which); + + /** + * Returns the time in microseconds that device has been in idle mode while + * running on battery. + * + * {@hide} + */ + public abstract long getDeviceIdleModeEnabledTime(long elapsedRealtimeUs, int which); + + /** + * Returns the number of times that the devie has gone in to idle mode. + * + * {@hide} + */ + public abstract int getDeviceIdleModeEnabledCount(int which); /** * Returns the number of times that connectivity state changed. @@ -1692,11 +1715,12 @@ public abstract class BatteryStats implements Parcelable { public static final BitDescription[] HISTORY_STATE2_DESCRIPTIONS = new BitDescription[] { - new BitDescription(HistoryItem.STATE2_LOW_POWER_FLAG, "low_power", "lp"), + new BitDescription(HistoryItem.STATE2_POWER_SAVE_FLAG, "power_save", "ps"), new BitDescription(HistoryItem.STATE2_VIDEO_ON_FLAG, "video", "v"), new BitDescription(HistoryItem.STATE2_WIFI_RUNNING_FLAG, "wifi_running", "Wr"), new BitDescription(HistoryItem.STATE2_WIFI_ON_FLAG, "wifi", "W"), new BitDescription(HistoryItem.STATE2_FLASHLIGHT_FLAG, "flashlight", "fl"), + new BitDescription(HistoryItem.STATE2_DEVICE_IDLE_FLAG, "device_idle", "di"), new BitDescription(HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_MASK, HistoryItem.STATE2_WIFI_SIGNAL_STRENGTH_SHIFT, "wifi_signal_strength", "Wss", new String[] { "0", "1", "2", "3", "4" }, @@ -1707,11 +1731,13 @@ public abstract class BatteryStats implements Parcelable { }; public static final String[] HISTORY_EVENT_NAMES = new String[] { - "null", "proc", "fg", "top", "sync", "wake_lock_in", "job", "user", "userfg", "conn" + "null", "proc", "fg", "top", "sync", "wake_lock_in", "job", "user", "userfg", "conn", + "motion", "active", "pkginst", "pkgunin" }; public static final String[] HISTORY_EVENT_CHECKIN_NAMES = new String[] { - "Enl", "Epr", "Efg", "Etp", "Esy", "Ewl", "Ejb", "Eur", "Euf", "Ecn" + "Enl", "Epr", "Efg", "Etp", "Esy", "Ewl", "Ejb", "Eur", "Euf", "Ecn", + "Esm", "Eac", "Epi", "Epu" }; /** @@ -2310,7 +2336,8 @@ public abstract class BatteryStats implements Parcelable { final long totalUptime = computeUptime(rawUptime, which); final long screenOnTime = getScreenOnTime(rawRealtime, which); final long interactiveTime = getInteractiveTime(rawRealtime, which); - final long lowPowerModeEnabledTime = getLowPowerModeEnabledTime(rawRealtime, which); + final long powerSaveModeEnabledTime = getPowerSaveModeEnabledTime(rawRealtime, which); + final long deviceIdleModeEnabledTime = getDeviceIdleModeEnabledTime(rawRealtime, which); final int connChanges = getNumConnectivityChange(which); final long phoneOnTime = getPhoneOnTime(rawRealtime, which); final long wifiOnTime = getWifiOnTime(rawRealtime, which); @@ -2382,7 +2409,8 @@ public abstract class BatteryStats implements Parcelable { fullWakeLockTimeTotal / 1000, partialWakeLockTimeTotal / 1000, 0 /*legacy input event count*/, getMobileRadioActiveTime(rawRealtime, which) / 1000, getMobileRadioActiveAdjustedTime(which) / 1000, interactiveTime / 1000, - lowPowerModeEnabledTime / 1000, connChanges); + powerSaveModeEnabledTime / 1000, connChanges, deviceIdleModeEnabledTime / 1000, + getDeviceIdleModeEnabledCount(which)); // Dump screen brightness stats Object[] args = new Object[NUM_SCREEN_BRIGHTNESS_BINS]; @@ -2849,7 +2877,8 @@ public abstract class BatteryStats implements Parcelable { final long screenOnTime = getScreenOnTime(rawRealtime, which); final long interactiveTime = getInteractiveTime(rawRealtime, which); - final long lowPowerModeEnabledTime = getLowPowerModeEnabledTime(rawRealtime, which); + final long powerSaveModeEnabledTime = getPowerSaveModeEnabledTime(rawRealtime, which); + final long deviceIdleModeEnabledTime = getDeviceIdleModeEnabledTime(rawRealtime, which); final long phoneOnTime = getPhoneOnTime(rawRealtime, which); final long wifiRunningTime = getGlobalWifiRunningTime(rawRealtime, which); final long wifiOnTime = getWifiOnTime(rawRealtime, which); @@ -2884,22 +2913,33 @@ public abstract class BatteryStats implements Parcelable { } if (!didOne) sb.append(" (no activity)"); pw.println(sb.toString()); - if (lowPowerModeEnabledTime != 0) { + if (powerSaveModeEnabledTime != 0) { sb.setLength(0); sb.append(prefix); - sb.append(" Low power mode enabled: "); - formatTimeMs(sb, lowPowerModeEnabledTime / 1000); + sb.append(" Power save mode enabled: "); + formatTimeMs(sb, powerSaveModeEnabledTime / 1000); sb.append("("); - sb.append(formatRatioLocked(lowPowerModeEnabledTime, whichBatteryRealtime)); + sb.append(formatRatioLocked(powerSaveModeEnabledTime, whichBatteryRealtime)); sb.append(")"); pw.println(sb.toString()); } + if (deviceIdleModeEnabledTime != 0) { + sb.setLength(0); + sb.append(prefix); + sb.append(" Device idling: "); + formatTimeMs(sb, deviceIdleModeEnabledTime / 1000); + sb.append("("); + sb.append(formatRatioLocked(deviceIdleModeEnabledTime, whichBatteryRealtime)); + sb.append(") "); sb.append(getDeviceIdleModeEnabledCount(which)); + sb.append("x"); + pw.println(sb.toString()); + } if (phoneOnTime != 0) { sb.setLength(0); sb.append(prefix); sb.append(" Active phone call: "); formatTimeMs(sb, phoneOnTime / 1000); sb.append("("); sb.append(formatRatioLocked(phoneOnTime, whichBatteryRealtime)); - sb.append(") "); sb.append(getPhoneOnCount(which)); + sb.append(") "); sb.append(getPhoneOnCount(which)); sb.append("x"); } int connChanges = getNumConnectivityChange(which); if (connChanges != 0) { @@ -4721,7 +4761,7 @@ public abstract class BatteryStats implements Parcelable { prepareForDumpLocked(); dumpLine(pw, 0 /* uid */, "i" /* category */, VERSION_DATA, - "12", getParcelVersion(), getStartPlatformVersion(), getEndPlatformVersion()); + "13", getParcelVersion(), getStartPlatformVersion(), getEndPlatformVersion()); long now = getHistoryBaseTime() + SystemClock.elapsedRealtime(); diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl index 87b6ed7..bea4ece 100644 --- a/core/java/com/android/internal/app/IBatteryStats.aidl +++ b/core/java/com/android/internal/app/IBatteryStats.aidl @@ -111,6 +111,7 @@ interface IBatteryStats { void noteWifiMulticastDisabledFromSource(in WorkSource ws); void noteNetworkInterfaceType(String iface, int type); void noteNetworkStatsEnabled(); + void noteDeviceIdleMode(boolean enabled, boolean fromActive, boolean fromMotion); void setBatteryState(int status, int health, int plugType, int level, int temp, int volt); long getAwakeTimeBattery(); long getAwakeTimePlugged(); diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index f9b1ca1..7d5df46 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -109,7 +109,7 @@ public final class BatteryStatsImpl extends BatteryStats { private static final int MAGIC = 0xBA757475; // 'BATSTATS' // Current on-disk Parcel version - private static final int VERSION = 119 + (USE_OLD_HISTORY ? 1000 : 0); + private static final int VERSION = 120 + (USE_OLD_HISTORY ? 1000 : 0); // Maximum number of items we will record in the history. private static final int MAX_HISTORY_ITEMS = 2000; @@ -307,8 +307,11 @@ public final class BatteryStatsImpl extends BatteryStats { boolean mInteractive; StopwatchTimer mInteractiveTimer; - boolean mLowPowerModeEnabled; - StopwatchTimer mLowPowerModeEnabledTimer; + boolean mPowerSaveModeEnabled; + StopwatchTimer mPowerSaveModeEnabledTimer; + + boolean mDeviceIdleModeEnabled; + StopwatchTimer mDeviceIdleModeEnabledTimer; boolean mPhoneOn; StopwatchTimer mPhoneOnTimer; @@ -1775,17 +1778,18 @@ public final class BatteryStatsImpl extends BatteryStats { private final Map<String, KernelWakelockStats> readKernelWakelockStats() { FileInputStream is; - byte[] buffer = new byte[8192]; + byte[] buffer = new byte[32*1024]; int len; - boolean wakeup_sources = false; + boolean wakeup_sources; try { try { - is = new FileInputStream("/proc/wakelocks"); + is = new FileInputStream("/d/wakeup_sources"); + wakeup_sources = true; } catch (java.io.FileNotFoundException e) { try { - is = new FileInputStream("/d/wakeup_sources"); - wakeup_sources = true; + is = new FileInputStream("/proc/wakelocks"); + wakeup_sources = false; } catch (java.io.FileNotFoundException e2) { return null; } @@ -1798,6 +1802,9 @@ public final class BatteryStatsImpl extends BatteryStats { } if (len > 0) { + if (len >= buffer.length) { + Slog.wtf(TAG, "Kernel wake locks exceeded buffer size " + buffer.length); + } int i; for (i=0; i<len; i++) { if (buffer[i] == '\0') { @@ -3386,29 +3393,73 @@ public final class BatteryStatsImpl extends BatteryStats { } } - public void noteLowPowerMode(boolean enabled) { - if (mLowPowerModeEnabled != enabled) { + public void notePowerSaveMode(boolean enabled) { + if (mPowerSaveModeEnabled != enabled) { int stepState = enabled ? STEP_LEVEL_MODE_POWER_SAVE : 0; mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_POWER_SAVE) ^ stepState; mCurStepMode = (mCurStepMode&~STEP_LEVEL_MODE_POWER_SAVE) | stepState; final long elapsedRealtime = SystemClock.elapsedRealtime(); final long uptime = SystemClock.uptimeMillis(); - mLowPowerModeEnabled = enabled; + mPowerSaveModeEnabled = enabled; + if (enabled) { + mHistoryCur.states2 |= HistoryItem.STATE2_POWER_SAVE_FLAG; + if (DEBUG_HISTORY) Slog.v(TAG, "Power save mode enabled to: " + + Integer.toHexString(mHistoryCur.states2)); + mPowerSaveModeEnabledTimer.startRunningLocked(elapsedRealtime); + } else { + mHistoryCur.states2 &= ~HistoryItem.STATE2_POWER_SAVE_FLAG; + if (DEBUG_HISTORY) Slog.v(TAG, "Power save mode disabled to: " + + Integer.toHexString(mHistoryCur.states2)); + mPowerSaveModeEnabledTimer.stopRunningLocked(elapsedRealtime); + } + addHistoryRecordLocked(elapsedRealtime, uptime); + } + } + + public void noteDeviceIdleModeLocked(boolean enabled, boolean fromActive, boolean fromMotion) { + if (mDeviceIdleModeEnabled != enabled) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + mDeviceIdleModeEnabled = enabled; + if (fromMotion) { + addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_SIGNIFICANT_MOTION, + "", 0); + } + if (fromActive) { + addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_ACTIVE, + "", 0); + } if (enabled) { - mHistoryCur.states2 |= HistoryItem.STATE2_LOW_POWER_FLAG; - if (DEBUG_HISTORY) Slog.v(TAG, "Low power mode enabled to: " + mHistoryCur.states2 |= HistoryItem.STATE2_DEVICE_IDLE_FLAG; + if (DEBUG_HISTORY) Slog.v(TAG, "Device idle mode enabled to: " + Integer.toHexString(mHistoryCur.states2)); - mLowPowerModeEnabledTimer.startRunningLocked(elapsedRealtime); + mDeviceIdleModeEnabledTimer.startRunningLocked(elapsedRealtime); } else { - mHistoryCur.states2 &= ~HistoryItem.STATE2_LOW_POWER_FLAG; - if (DEBUG_HISTORY) Slog.v(TAG, "Low power mode disabled to: " + mHistoryCur.states2 &= ~HistoryItem.STATE2_DEVICE_IDLE_FLAG; + if (DEBUG_HISTORY) Slog.v(TAG, "Device idle mode disabled to: " + Integer.toHexString(mHistoryCur.states2)); - mLowPowerModeEnabledTimer.stopRunningLocked(elapsedRealtime); + mDeviceIdleModeEnabledTimer.stopRunningLocked(elapsedRealtime); } addHistoryRecordLocked(elapsedRealtime, uptime); } } + public void notePackageInstalledLocked(String pkgName, int versionCode) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PACKAGE_INSTALLED, + pkgName, versionCode); + mNumConnectivityChange++; + } + + public void notePackageUninstalledLocked(String pkgName) { + final long elapsedRealtime = SystemClock.elapsedRealtime(); + final long uptime = SystemClock.uptimeMillis(); + addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_PACKAGE_UNINSTALLED, + pkgName, 0); + mNumConnectivityChange++; + } + public void notePhoneOnLocked() { if (!mPhoneOn) { final long elapsedRealtime = SystemClock.elapsedRealtime(); @@ -4195,12 +4246,20 @@ public final class BatteryStatsImpl extends BatteryStats { return mInteractiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which); } - @Override public long getLowPowerModeEnabledTime(long elapsedRealtimeUs, int which) { - return mLowPowerModeEnabledTimer.getTotalTimeLocked(elapsedRealtimeUs, which); + @Override public long getPowerSaveModeEnabledTime(long elapsedRealtimeUs, int which) { + return mPowerSaveModeEnabledTimer.getTotalTimeLocked(elapsedRealtimeUs, which); + } + + @Override public int getPowerSaveModeEnabledCount(int which) { + return mPowerSaveModeEnabledTimer.getCountLocked(which); + } + + @Override public long getDeviceIdleModeEnabledTime(long elapsedRealtimeUs, int which) { + return mDeviceIdleModeEnabledTimer.getTotalTimeLocked(elapsedRealtimeUs, which); } - @Override public int getLowPowerModeEnabledCount(int which) { - return mLowPowerModeEnabledTimer.getCountLocked(which); + @Override public int getDeviceIdleModeEnabledCount(int which) { + return mDeviceIdleModeEnabledTimer.getCountLocked(which); } @Override public int getNumConnectivityChange(int which) { @@ -6662,8 +6721,9 @@ public final class BatteryStatsImpl extends BatteryStats { for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) { mScreenBrightnessTimer[i] = new StopwatchTimer(null, -100-i, null, mOnBatteryTimeBase); } - mInteractiveTimer = new StopwatchTimer(null, -9, null, mOnBatteryTimeBase); - mLowPowerModeEnabledTimer = new StopwatchTimer(null, -2, null, mOnBatteryTimeBase); + mInteractiveTimer = new StopwatchTimer(null, -10, null, mOnBatteryTimeBase); + mPowerSaveModeEnabledTimer = new StopwatchTimer(null, -2, null, mOnBatteryTimeBase); + mDeviceIdleModeEnabledTimer = new StopwatchTimer(null, -11, null, mOnBatteryTimeBase); mPhoneOnTimer = new StopwatchTimer(null, -3, null, mOnBatteryTimeBase); for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) { mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(null, -200-i, null, @@ -7233,7 +7293,8 @@ public final class BatteryStatsImpl extends BatteryStats { mScreenBrightnessTimer[i].reset(false); } mInteractiveTimer.reset(false); - mLowPowerModeEnabledTimer.reset(false); + mPowerSaveModeEnabledTimer.reset(false); + mDeviceIdleModeEnabledTimer.reset(false); mPhoneOnTimer.reset(false); mAudioOnTimer.reset(false); mVideoOnTimer.reset(false); @@ -8534,7 +8595,8 @@ public final class BatteryStatsImpl extends BatteryStats { mInteractive = false; mInteractiveTimer.readSummaryFromParcelLocked(in); mPhoneOn = false; - mLowPowerModeEnabledTimer.readSummaryFromParcelLocked(in); + mPowerSaveModeEnabledTimer.readSummaryFromParcelLocked(in); + mDeviceIdleModeEnabledTimer.readSummaryFromParcelLocked(in); mPhoneOnTimer.readSummaryFromParcelLocked(in); for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) { mPhoneSignalStrengthsTimer[i].readSummaryFromParcelLocked(in); @@ -8835,7 +8897,8 @@ public final class BatteryStatsImpl extends BatteryStats { mScreenBrightnessTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS); } mInteractiveTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS); - mLowPowerModeEnabledTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS); + mPowerSaveModeEnabledTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS); + mDeviceIdleModeEnabledTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS); mPhoneOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS); for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) { mPhoneSignalStrengthsTimer[i].writeSummaryFromParcelLocked(out, NOWREAL_SYS); @@ -9132,9 +9195,10 @@ public final class BatteryStatsImpl extends BatteryStats { in); } mInteractive = false; - mInteractiveTimer = new StopwatchTimer(null, -9, null, mOnBatteryTimeBase, in); + mInteractiveTimer = new StopwatchTimer(null, -10, null, mOnBatteryTimeBase, in); mPhoneOn = false; - mLowPowerModeEnabledTimer = new StopwatchTimer(null, -2, null, mOnBatteryTimeBase, in); + mPowerSaveModeEnabledTimer = new StopwatchTimer(null, -2, null, mOnBatteryTimeBase, in); + mDeviceIdleModeEnabledTimer = new StopwatchTimer(null, -11, null, mOnBatteryTimeBase, in); mPhoneOnTimer = new StopwatchTimer(null, -3, null, mOnBatteryTimeBase, in); for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) { mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(null, -200-i, @@ -9299,7 +9363,8 @@ public final class BatteryStatsImpl extends BatteryStats { mScreenBrightnessTimer[i].writeToParcel(out, uSecRealtime); } mInteractiveTimer.writeToParcel(out, uSecRealtime); - mLowPowerModeEnabledTimer.writeToParcel(out, uSecRealtime); + mPowerSaveModeEnabledTimer.writeToParcel(out, uSecRealtime); + mDeviceIdleModeEnabledTimer.writeToParcel(out, uSecRealtime); mPhoneOnTimer.writeToParcel(out, uSecRealtime); for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) { mPhoneSignalStrengthsTimer[i].writeToParcel(out, uSecRealtime); @@ -9436,8 +9501,10 @@ public final class BatteryStatsImpl extends BatteryStats { } pr.println("*** Interactive timer:"); mInteractiveTimer.logState(pr, " "); - pr.println("*** Low power mode timer:"); - mLowPowerModeEnabledTimer.logState(pr, " "); + pr.println("*** Power save mode timer:"); + mPowerSaveModeEnabledTimer.logState(pr, " "); + pr.println("*** Device idle mode timer:"); + mDeviceIdleModeEnabledTimer.logState(pr, " "); pr.println("*** Phone timer:"); mPhoneOnTimer.logState(pr, " "); for (int i=0; i<SignalStrength.NUM_SIGNAL_STRENGTH_BINS; i++) { diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java new file mode 100644 index 0000000..062992d --- /dev/null +++ b/services/core/java/com/android/server/DeviceIdleController.java @@ -0,0 +1,424 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server; + +import android.app.AlarmManager; +import android.app.PendingIntent; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.pm.PackageManager; +import android.hardware.Sensor; +import android.hardware.SensorManager; +import android.hardware.TriggerEvent; +import android.hardware.TriggerEventListener; +import android.hardware.display.DisplayManager; +import android.net.INetworkPolicyManager; +import android.os.Binder; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.os.SystemClock; +import android.util.TimeUtils; +import android.view.Display; +import com.android.internal.app.IBatteryStats; +import com.android.server.am.BatteryStatsService; + +import java.io.FileDescriptor; +import java.io.PrintWriter; + +/** + * Keeps track of device idleness and drives low power mode based on that. + */ +public class DeviceIdleController extends SystemService { + private static final String TAG = "DeviceIdleController"; + + private static final String ACTION_STEP_IDLE_STATE = + "com.android.server.device_idle.STEP_IDLE_STATE"; + + // TODO: These need to be moved to system settings. + + /** + * This is the time, after becoming inactive, at which we start looking at the + * motion sensor to determine if the device is being left alone. We don't do this + * immediately after going inactive just because we don't want to be continually running + * the significant motion sensor whenever the screen is off. + */ + private static final long DEFAULT_INACTIVE_TIMEOUT = 30*60*1000L; + /** + * This is the time, after the inactive timeout elapses, that we will wait looking + * for significant motion until we truly consider the device to be idle. + */ + private static final long DEFAULT_IDLE_AFTER_INACTIVE_TIMEOUT = 30*60*1000L; + /** + * This is the initial time, after being idle, that we will allow ourself to be back + * in the IDLE_PENDING state allowing the system to run normally until we return to idle. + */ + private static final long DEFAULT_IDLE_PENDING_TIMEOUT = 5*60*1000L; + /** + * Maximum pending idle timeout (time spent running) we will be allowed to use. + */ + private static final long DEFAULT_MAX_IDLE_PENDING_TIMEOUT = 10*60*1000L; + /** + * Scaling factor to apply to current pending idle timeout each time we cycle through + * that state. + */ + private static final float DEFAULT_IDLE_PENDING_FACTOR = 2f; + /** + * This is the initial time that we want to sit in the idle state before waking up + * again to return to pending idle and allowing normal work to run. + */ + private static final long DEFAULT_IDLE_TIMEOUT = 60*60*1000L; + /** + * Maximum idle duration we will be allowed to use. + */ + private static final long DEFAULT_MAX_IDLE_TIMEOUT = 6*60*60*1000L; + /** + * Scaling factor to apply to current idle timeout each time we cycle through that state. + */ + private static final float DEFAULT_IDLE_FACTOR = 2f; + + private AlarmManager mAlarmManager; + private IBatteryStats mBatteryStats; + private INetworkPolicyManager mNetworkPolicyManager; + private DisplayManager mDisplayManager; + private SensorManager mSensorManager; + private Sensor mSigMotionSensor; + private PendingIntent mAlarmIntent; + private Display mCurDisplay; + private boolean mScreenOn; + private boolean mCharging; + private boolean mSigMotionActive; + + /** Device is currently active. */ + private static final int STATE_ACTIVE = 0; + /** Device is inactve (screen off, no motion) and we are waiting to for idle. */ + private static final int STATE_INACTIVE = 1; + /** Device is past the initial inactive period, and waiting for the next idle period. */ + private static final int STATE_IDLE_PENDING = 2; + /** Device is in the idle state, trying to stay asleep as much as possible. */ + private static final int STATE_IDLE = 3; + private static String stateToString(int state) { + switch (state) { + case STATE_ACTIVE: return "ACTIVE"; + case STATE_INACTIVE: return "INACTIVE"; + case STATE_IDLE_PENDING: return "IDLE_PENDING"; + case STATE_IDLE: return "IDLE"; + default: return Integer.toString(state); + } + } + + private int mState; + + private long mNextAlarmTime; + private long mNextIdlePendingDelay; + private long mNextIdleDelay; + + private final Binder mBinder = new Binder() { + @Override protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + DeviceIdleController.this.dump(fd, pw, args); + } + }; + + private final BroadcastReceiver mReceiver = new BroadcastReceiver() { + @Override public void onReceive(Context context, Intent intent) { + if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) { + int plugged = intent.getIntExtra("plugged", 0); + updateChargingLocked(plugged != 0); + } else if (ACTION_STEP_IDLE_STATE.equals(intent.getAction())) { + synchronized (DeviceIdleController.this) { + stepIdleStateLocked(); + } + } + } + }; + + private final DisplayManager.DisplayListener mDisplayListener + = new DisplayManager.DisplayListener() { + @Override public void onDisplayAdded(int displayId) { + } + + @Override public void onDisplayRemoved(int displayId) { + } + + @Override public void onDisplayChanged(int displayId) { + if (displayId == Display.DEFAULT_DISPLAY) { + synchronized (DeviceIdleController.this) { + updateDisplayLocked(); + } + } + } + }; + + private final TriggerEventListener mSigMotionListener = new TriggerEventListener() { + @Override public void onTrigger(TriggerEvent event) { + synchronized (DeviceIdleController.this) { + significantMotionLocked(); + } + } + }; + + public DeviceIdleController(Context context) { + super(context); + } + + @Override + public void onStart() { + synchronized (this) { + mAlarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE); + mBatteryStats = BatteryStatsService.getService(); + mNetworkPolicyManager = INetworkPolicyManager.Stub.asInterface( + ServiceManager.getService(Context.NETWORK_POLICY_SERVICE)); + mDisplayManager = (DisplayManager) getContext().getSystemService( + Context.DISPLAY_SERVICE); + mSensorManager = (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE); + mSigMotionSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION); + + Intent intent = new Intent(ACTION_STEP_IDLE_STATE) + .setPackage("android") + .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); + mAlarmIntent = PendingIntent.getBroadcast(getContext(), 0, intent, 0); + + IntentFilter filter = new IntentFilter(); + filter.addAction(Intent.ACTION_BATTERY_CHANGED); + filter.addAction(ACTION_STEP_IDLE_STATE); + getContext().registerReceiver(mReceiver, filter); + + mDisplayManager.registerDisplayListener(mDisplayListener, null); + + mScreenOn = true; + // Start out assuming we are charging. If we aren't, we will at least get + // a battery update the next time the level drops. + mCharging = true; + mState = STATE_ACTIVE; + updateDisplayLocked(); + } + + publishBinderService("deviceidle", mBinder); + } + + void updateDisplayLocked() { + mCurDisplay = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY); + // We consider any situation where the display is showing something to be it on, + // because if there is anything shown we are going to be updating it at some + // frequency so can't be allowed to go into deep sleeps. + boolean screenOn = mCurDisplay.getState() != Display.STATE_OFF;; + if (!screenOn && mScreenOn) { + mScreenOn = false; + becomeInactiveIfAppropriateLocked(); + } else if (screenOn) { + mScreenOn = true; + becomeActiveLocked(); + } + } + + void updateChargingLocked(boolean charging) { + if (!charging && mCharging) { + mCharging = false; + becomeInactiveIfAppropriateLocked(); + } else if (charging) { + mCharging = charging; + becomeActiveLocked(); + } + } + + void becomeActiveLocked() { + if (mState != STATE_ACTIVE) { + try { + mNetworkPolicyManager.setDeviceIdleMode(false); + mBatteryStats.noteDeviceIdleMode(false, true, false); + } catch (RemoteException e) { + } + mState = STATE_ACTIVE; + mNextIdlePendingDelay = 0; + mNextIdleDelay = 0; + cancelAlarmLocked(); + stopMonitoringSignificantMotion(); + } + } + + void becomeInactiveIfAppropriateLocked() { + if (!mScreenOn && !mCharging && mState == STATE_ACTIVE) { + // Screen has turned off; we are now going to become inactive and start + // waiting to see if we will ultimately go idle. + mState = STATE_INACTIVE; + scheduleAlarmLocked(DEFAULT_INACTIVE_TIMEOUT, false); + } + } + + void stepIdleStateLocked() { + switch (mState) { + case STATE_INACTIVE: + // We have now been inactive long enough, it is time to start looking + // for significant motion and sleep some more while doing so. + startMonitoringSignificantMotion(); + scheduleAlarmLocked(DEFAULT_IDLE_AFTER_INACTIVE_TIMEOUT, false); + // Reset the upcoming idle delays. + mNextIdlePendingDelay = DEFAULT_IDLE_PENDING_TIMEOUT; + mNextIdleDelay = DEFAULT_IDLE_TIMEOUT; + mState = STATE_IDLE_PENDING; + break; + case STATE_IDLE_PENDING: + // We have been waiting to become idle, and now it is time! This is the + // only case where we want to use a wakeup alarm, because we do want to + // drag the device out of its sleep state in this case to do the next + // scheduled work. + scheduleAlarmLocked(mNextIdleDelay, true); + mNextIdleDelay = (long)(mNextIdleDelay*DEFAULT_IDLE_FACTOR); + if (mNextIdleDelay > DEFAULT_MAX_IDLE_TIMEOUT) { + mNextIdleDelay = DEFAULT_MAX_IDLE_TIMEOUT; + } + mState = STATE_IDLE; + try { + mNetworkPolicyManager.setDeviceIdleMode(true); + mBatteryStats.noteDeviceIdleMode(true, false, false); + } catch (RemoteException e) { + } + break; + case STATE_IDLE: + // We have been idling long enough, now it is time to do some work. + scheduleAlarmLocked(mNextIdlePendingDelay, false); + mNextIdlePendingDelay = (long)(mNextIdlePendingDelay*DEFAULT_IDLE_PENDING_FACTOR); + if (mNextIdlePendingDelay > DEFAULT_MAX_IDLE_PENDING_TIMEOUT) { + mNextIdlePendingDelay = DEFAULT_MAX_IDLE_PENDING_TIMEOUT; + } + mState = STATE_IDLE_PENDING; + try { + mNetworkPolicyManager.setDeviceIdleMode(false); + mBatteryStats.noteDeviceIdleMode(false, false, false); + } catch (RemoteException e) { + } + break; + } + } + + void significantMotionLocked() { + // When the sensor goes off, its trigger is automatically removed. + mSigMotionActive = false; + // The device is not yet active, so we want to go back to the pending idle + // state to wait again for no motion. Note that we only monitor for significant + // motion after moving out of the inactive state, so no need to worry about that. + if (mState != STATE_ACTIVE) { + mState = STATE_INACTIVE; + try { + mNetworkPolicyManager.setDeviceIdleMode(false); + mBatteryStats.noteDeviceIdleMode(false, false, true); + } catch (RemoteException e) { + } + stepIdleStateLocked(); + } + } + + void startMonitoringSignificantMotion() { + if (mSigMotionSensor != null && !mSigMotionActive) { + mSensorManager.requestTriggerSensor(mSigMotionListener, mSigMotionSensor); + mSigMotionActive = true; + } + } + + void stopMonitoringSignificantMotion() { + if (mSigMotionActive) { + mSensorManager.cancelTriggerSensor(mSigMotionListener, mSigMotionSensor); + mSigMotionActive = false; + } + } + + void cancelAlarmLocked() { + if (mNextAlarmTime != 0) { + mNextAlarmTime = 0; + mAlarmManager.cancel(mAlarmIntent); + } + } + + void scheduleAlarmLocked(long delay, boolean wakeup) { + if (mSigMotionSensor == null) { + // If there is no significant motion sensor on this device, then we won't schedule + // alarms, because we can't determine if the device is not moving. This effectively + // turns off normal exeuction of device idling, although it is still possible to + // manually poke it by pretending like the alarm is going off. + return; + } + mNextAlarmTime = SystemClock.elapsedRealtime() + delay; + mAlarmManager.set(wakeup ? AlarmManager.ELAPSED_REALTIME_WAKEUP + : AlarmManager.ELAPSED_REALTIME, mNextAlarmTime, mAlarmIntent); + } + + private void dumpHelp(PrintWriter pw) { + pw.println("Device idle controller (deviceidle) dump options:"); + pw.println(" [-h] [CMD]"); + pw.println(" -h: print this help text."); + pw.println("Commands:"); + pw.println(" step"); + pw.println(" Immediately step to next state, without waiting for alarm."); + } + + void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP) + != PackageManager.PERMISSION_GRANTED) { + pw.println("Permission Denial: can't dump DeviceIdleController from from pid=" + + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid() + + " without permission " + android.Manifest.permission.DUMP); + return; + } + + if (args != null) { + for (int i=0; i<args.length; i++) { + String arg = args[i]; + if ("-h".equals(arg)) { + dumpHelp(pw); + return; + } else if ("step".equals(arg)) { + synchronized (this) { + stepIdleStateLocked(); + pw.print("Stepped to: "); pw.println(stateToString(mState)); + } + return; + } else if (arg.length() > 0 && arg.charAt(0) == '-'){ + pw.println("Unknown option: " + arg); + dumpHelp(pw); + return; + } else { + pw.println("Unknown command: " + arg); + dumpHelp(pw); + return; + } + } + } + + pw.print(" mSigMotionSensor="); pw.println(mSigMotionSensor); + pw.print(" mCurDisplay="); pw.println(mCurDisplay); + pw.print(" mScreenOn="); pw.println(mScreenOn); + pw.print(" mCharging="); pw.println(mCharging); + pw.print(" mSigMotionActive="); pw.println(mSigMotionActive); + pw.print(" mState="); pw.println(stateToString(mState)); + if (mNextAlarmTime != 0) { + pw.print(" mNextAlarmTime="); + TimeUtils.formatDuration(mNextAlarmTime, SystemClock.elapsedRealtime(), pw); + pw.println(); + } + if (mNextIdlePendingDelay != 0) { + pw.print(" mNextIdlePendingDelay="); + TimeUtils.formatDuration(mNextIdlePendingDelay, pw); + pw.println(); + } + if (mNextIdleDelay != 0) { + pw.print(" mNextIdleDelay="); + TimeUtils.formatDuration(mNextIdleDelay, pw); + pw.println(); + } + } +} diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index dcee96a..7f4ccb7 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -15798,6 +15798,7 @@ public final class ActivityManagerService extends ActivityManagerNative if (userId == UserHandle.USER_OWNER) { mTaskPersister.removeFromPackageCache(ssp); } + mBatteryStatsService.notePackageUninstalled(ssp); } } else { removeTasksByRemovedPackageComponentsLocked(ssp, userId); @@ -15824,6 +15825,13 @@ public final class ActivityManagerService extends ActivityManagerNative if (userId == UserHandle.USER_OWNER) { mTaskPersister.addOtherDeviceTasksToRecentsLocked(ssp); } + try { + ApplicationInfo ai = AppGlobals.getPackageManager(). + getApplicationInfo(ssp, 0, 0); + mBatteryStatsService.notePackageInstalled(ssp, + ai != null ? ai.versionCode : 0); + } catch (RemoteException e) { + } } break; case Intent.ACTION_TIMEZONE_CHANGED: diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java index 6eacfa9..197b51d 100644 --- a/services/core/java/com/android/server/am/BatteryStatsService.java +++ b/services/core/java/com/android/server/am/BatteryStatsService.java @@ -86,7 +86,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub public void initPowerManagement() { mPowerManagerInternal = LocalServices.getService(PowerManagerInternal.class); mPowerManagerInternal.registerLowPowerModeObserver(this); - mStats.noteLowPowerMode(mPowerManagerInternal.getLowPowerModeEnabled()); + mStats.notePowerSaveMode(mPowerManagerInternal.getLowPowerModeEnabled()); (new WakeupReasonThread()).start(); } @@ -109,7 +109,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub @Override public void onLowPowerModeChanged(boolean enabled) { synchronized (mStats) { - mStats.noteLowPowerMode(enabled); + mStats.notePowerSaveMode(enabled); } } @@ -686,6 +686,28 @@ public final class BatteryStatsService extends IBatteryStats.Stub } } + @Override + public void noteDeviceIdleMode(boolean enabled, boolean fromActive, boolean fromMotion) { + enforceCallingPermission(); + synchronized (mStats) { + mStats.noteDeviceIdleModeLocked(enabled, fromActive, fromMotion); + } + } + + public void notePackageInstalled(String pkgName, int versionCode) { + enforceCallingPermission(); + synchronized (mStats) { + mStats.notePackageInstalledLocked(pkgName, versionCode); + } + } + + public void notePackageUninstalled(String pkgName) { + enforceCallingPermission(); + synchronized (mStats) { + mStats.notePackageUninstalledLocked(pkgName); + } + } + public boolean isOnBattery() { return mStats.isOnBattery(); } diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java index 83d6986..fe1260d 100644 --- a/services/core/java/com/android/server/job/JobSchedulerService.java +++ b/services/core/java/com/android/server/job/JobSchedulerService.java @@ -22,6 +22,7 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; +import android.app.ActivityManager; import android.app.AppGlobals; import android.app.job.JobInfo; import android.app.job.JobScheduler; @@ -72,7 +73,8 @@ public class JobSchedulerService extends com.android.server.SystemService implements StateChangedListener, JobCompletedListener { static final boolean DEBUG = false; /** The number of concurrent jobs we run at one time. */ - private static final int MAX_JOB_CONTEXTS_COUNT = 3; + private static final int MAX_JOB_CONTEXTS_COUNT + = ActivityManager.isLowRamDeviceStatic() ? 1 : 3; static final String TAG = "JobSchedulerService"; /** Master list of jobs. */ final JobStore mJobs; diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java index cc0fcf5..a69a95f 100644 --- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java +++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java @@ -243,9 +243,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { final Object mRulesLock = new Object(); + volatile boolean mSystemReady; volatile boolean mScreenOn; volatile boolean mRestrictBackground; volatile boolean mRestrictPower; + volatile boolean mDeviceIdleMode; private final boolean mSuppressDefaultPolicy; @@ -367,11 +369,12 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } }); mRestrictPower = mPowerManagerInternal.getLowPowerModeEnabled(); + mSystemReady = true; // read policy from disk readPolicyLocked(); - if (mRestrictBackground || mRestrictPower) { + if (mRestrictBackground || mRestrictPower || mDeviceIdleMode) { updateRulesForGlobalChangeLocked(true); updateNotificationsLocked(); } @@ -1031,7 +1034,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { // will not have a bandwidth limit. Also only do this if restrict // background data use is *not* enabled, since that takes precendence // use over those networks can have a cost associated with it). - final boolean powerSave = mRestrictPower && !mRestrictBackground; + final boolean powerSave = (mRestrictPower || mDeviceIdleMode) && !mRestrictBackground; // First, generate identities of all connected networks so we can // quickly compare them against all defined policies below. @@ -1696,6 +1699,20 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } } + @Override + public void setDeviceIdleMode(boolean enabled) { + mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG); + + synchronized (mRulesLock) { + if (mDeviceIdleMode != enabled) { + mDeviceIdleMode = enabled; + if (mSystemReady) { + updateRulesForGlobalChangeLocked(true); + } + } + } + } + private NetworkPolicy findPolicyForNetworkLocked(NetworkIdentity ident) { for (int i = mNetworkPolicy.size()-1; i >= 0; i--) { NetworkPolicy policy = mNetworkPolicy.valueAt(i); @@ -1801,8 +1818,10 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { return; } + fout.print("System ready: "); fout.println(mSystemReady); fout.print("Restrict background: "); fout.println(mRestrictBackground); fout.print("Restrict power: "); fout.println(mRestrictPower); + fout.print("Device idle: "); fout.println(mDeviceIdleMode); fout.print("Current foreground state: "); fout.println(mCurForegroundState); fout.println("Network policies:"); fout.increaseIndent(); @@ -1952,8 +1971,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { } /** - * Update rules that might be changed by {@link #mRestrictBackground} - * or {@link #mRestrictPower} value. + * Update rules that might be changed by {@link #mRestrictBackground}, + * {@link #mRestrictPower}, or {@link #mDeviceIdleMode} value. */ void updateRulesForGlobalChangeLocked(boolean restrictedNetworksChanged) { final PackageManager pm = mContext.getPackageManager(); @@ -1962,7 +1981,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { // If we are in restrict power mode, we allow all important apps // to have data access. Otherwise, we restrict data access to only // the top apps. - mCurForegroundState = (!mRestrictBackground && mRestrictPower) + mCurForegroundState = (!mRestrictBackground && (mRestrictPower || mDeviceIdleMode)) ? ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND : ActivityManager.PROCESS_STATE_TOP; @@ -2015,7 +2034,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub { // uid in background, and global background disabled uidRules = RULE_REJECT_METERED; } - } else if (mRestrictPower) { + } else if (mRestrictPower || mDeviceIdleMode) { final boolean whitelisted = mPowerSaveWhitelistAppIds.get(UserHandle.getAppId(uid)); if (!whitelisted && !uidForeground && (uidPolicy & POLICY_ALLOW_BACKGROUND_BATTERY_SAVE) == 0) { diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java index a0c7f86..ed55c56 100644 --- a/services/java/com/android/server/SystemServer.java +++ b/services/java/com/android/server/SystemServer.java @@ -960,6 +960,7 @@ public final class SystemServer { if (!disableNonCoreServices) { mSystemServiceManager.startService(MediaProjectionManagerService.class); + mSystemServiceManager.startService(DeviceIdleController.class); } // Before things start rolling, be sure we have decided whether |