Cache PowerManager binder calls

Use PropertyInvalidatedCache to save on redundant
binder calls for isPowerSaveMode and isInteractive.

Bug: 140788621
Test: atest BatterySaverTest
Test: atest PowerManagerTest
Change-Id: I849a48eb7c901d3178097d33dce01630dbb78267
This commit is contained in:
Collin Fijalkovich
2019-11-13 18:47:27 +00:00
parent e9a33feb4e
commit 24d1336f17
7 changed files with 268 additions and 116 deletions

View File

@@ -26,6 +26,7 @@ import android.annotation.SdkConstant;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
import android.app.PropertyInvalidatedCache;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.service.dreams.Sandman;
@@ -877,6 +878,39 @@ public final class PowerManager {
}
}
private static final String CACHE_KEY_IS_POWER_SAVE_MODE_PROPERTY =
"cache_key.is_power_save_mode";
private static final String CACHE_KEY_IS_INTERACTIVE_PROPERTY = "cache_key.is_interactive";
private static final int MAX_CACHE_ENTRIES = 1;
private PropertyInvalidatedCache<Void, Boolean> mPowerSaveModeCache =
new PropertyInvalidatedCache<Void, Boolean>(MAX_CACHE_ENTRIES,
CACHE_KEY_IS_POWER_SAVE_MODE_PROPERTY) {
@Override
protected Boolean recompute(Void query) {
try {
return mService.isPowerSaveMode();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
};
private PropertyInvalidatedCache<Void, Boolean> mInteractiveCache =
new PropertyInvalidatedCache<Void, Boolean>(MAX_CACHE_ENTRIES,
CACHE_KEY_IS_INTERACTIVE_PROPERTY) {
@Override
protected Boolean recompute(Void query) {
try {
return mService.isInteractive();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
};
final Context mContext;
@UnsupportedAppUsage
final IPowerManager mService;
@@ -1440,11 +1474,7 @@ public final class PowerManager {
* @see android.content.Intent#ACTION_SCREEN_OFF
*/
public boolean isInteractive() {
try {
return mService.isInteractive();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
return mInteractiveCache.query(null);
}
/**
@@ -1504,11 +1534,7 @@ public final class PowerManager {
* @return Returns true if currently in low power mode, else false.
*/
public boolean isPowerSaveMode() {
try {
return mService.isPowerSaveMode();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
return mPowerSaveModeCache.query(null);
}
/**
@@ -2508,4 +2534,18 @@ public final class PowerManager {
};
}
}
/**
* @hide
*/
public static void invalidatePowerSaveModeCaches() {
PropertyInvalidatedCache.invalidateCache(CACHE_KEY_IS_POWER_SAVE_MODE_PROPERTY);
}
/**
* @hide
*/
public static void invalidateIsInteractiveCaches() {
PropertyInvalidatedCache.invalidateCache(CACHE_KEY_IS_INTERACTIVE_PROPERTY);
}
}

View File

@@ -242,8 +242,8 @@ public final class PowerManagerService extends SystemService
private final ServiceThread mHandlerThread;
private final PowerManagerHandler mHandler;
private final AmbientDisplayConfiguration mAmbientDisplayConfiguration;
private final BatterySaverPolicy mBatterySaverPolicy;
private final BatterySaverController mBatterySaverController;
private final BatterySaverPolicy mBatterySaverPolicy;
private final BatterySaverStateMachine mBatterySaverStateMachine;
private final BatterySavingStats mBatterySavingStats;
private final AttentionDetector mAttentionDetector;
@@ -275,7 +275,8 @@ public final class PowerManagerService extends SystemService
// Indicates whether the device is awake or asleep or somewhere in between.
// This is distinct from the screen power state, which is managed separately.
private int mWakefulness;
// Do not access directly; always use {@link #setWakefulness} and {@link getWakefulness}.
private int mWakefulnessRaw;
private boolean mWakefulnessChanging;
// True if the sandman has just been summoned for the first time since entering the
@@ -764,6 +765,13 @@ public final class PowerManagerService extends SystemService
return new BatterySaverPolicy(lock, context, batterySavingStats);
}
BatterySaverController createBatterySaverController(
Object lock, Context context, BatterySaverPolicy batterySaverPolicy,
BatterySavingStats batterySavingStats) {
return new BatterySaverController(lock, context, BackgroundThread.get().getLooper(),
batterySaverPolicy, batterySavingStats);
}
NativeWrapper createNativeWrapper() {
return new NativeWrapper();
}
@@ -794,6 +802,10 @@ public final class PowerManagerService extends SystemService
}
};
}
void invalidateIsInteractiveCaches() {
PowerManager.invalidateIsInteractiveCaches();
}
}
final Constants mConstants;
@@ -833,9 +845,8 @@ public final class PowerManagerService extends SystemService
mBatterySavingStats = new BatterySavingStats(mLock);
mBatterySaverPolicy =
mInjector.createBatterySaverPolicy(mLock, mContext, mBatterySavingStats);
mBatterySaverController = new BatterySaverController(mLock, mContext,
BackgroundThread.get().getLooper(), mBatterySaverPolicy,
mBatterySavingStats);
mBatterySaverController = mInjector.createBatterySaverController(mLock, mContext,
mBatterySaverPolicy, mBatterySavingStats);
mBatterySaverStateMachine = new BatterySaverStateMachine(
mLock, mContext, mBatterySaverController);
@@ -939,13 +950,14 @@ public final class PowerManagerService extends SystemService
mHalAutoSuspendModeEnabled = false;
mHalInteractiveModeEnabled = true;
mWakefulness = WAKEFULNESS_AWAKE;
mWakefulnessRaw = WAKEFULNESS_AWAKE;
sQuiescent = mSystemProperties.get(SYSTEM_PROPERTY_QUIESCENT, "0").equals("1");
mNativeWrapper.nativeInit(this);
mNativeWrapper.nativeSetAutoSuspend(false);
mNativeWrapper.nativeSetInteractive(true);
mNativeWrapper.nativeSetFeature(POWER_FEATURE_DOUBLE_TAP_TO_WAKE, 0);
mInjector.invalidateIsInteractiveCaches();
}
}
@@ -1567,8 +1579,8 @@ public final class PowerManagerService extends SystemService
mOverriddenTimeout = -1;
}
if (mWakefulness == WAKEFULNESS_ASLEEP
|| mWakefulness == WAKEFULNESS_DOZING
if (getWakefulnessLocked() == WAKEFULNESS_ASLEEP
|| getWakefulnessLocked() == WAKEFULNESS_DOZING
|| (flags & PowerManager.USER_ACTIVITY_FLAG_INDIRECT) != 0) {
return false;
}
@@ -1624,7 +1636,7 @@ public final class PowerManagerService extends SystemService
Slog.d(TAG, "wakeUpNoUpdateLocked: eventTime=" + eventTime + ", uid=" + reasonUid);
}
if (eventTime < mLastSleepTime || mWakefulness == WAKEFULNESS_AWAKE
if (eventTime < mLastSleepTime || getWakefulnessLocked() == WAKEFULNESS_AWAKE
|| mForceSuspendActive || !mSystemReady) {
return false;
}
@@ -1634,7 +1646,7 @@ public final class PowerManagerService extends SystemService
Trace.traceBegin(Trace.TRACE_TAG_POWER, "wakeUp");
try {
Slog.i(TAG, "Waking up from "
+ PowerManagerInternal.wakefulnessToString(mWakefulness)
+ PowerManagerInternal.wakefulnessToString(getWakefulnessLocked())
+ " (uid=" + reasonUid
+ ", reason=" + PowerManager.wakeReasonToString(reason)
+ ", details=" + details
@@ -1680,8 +1692,8 @@ public final class PowerManagerService extends SystemService
}
if (eventTime < mLastWakeTime
|| mWakefulness == WAKEFULNESS_ASLEEP
|| mWakefulness == WAKEFULNESS_DOZING
|| getWakefulnessLocked() == WAKEFULNESS_ASLEEP
|| getWakefulnessLocked() == WAKEFULNESS_DOZING
|| !mSystemReady
|| !mBootCompleted) {
return false;
@@ -1738,7 +1750,7 @@ public final class PowerManagerService extends SystemService
Slog.d(TAG, "napNoUpdateLocked: eventTime=" + eventTime + ", uid=" + uid);
}
if (eventTime < mLastWakeTime || mWakefulness != WAKEFULNESS_AWAKE
if (eventTime < mLastWakeTime || getWakefulnessLocked() != WAKEFULNESS_AWAKE
|| !mBootCompleted || !mSystemReady) {
return false;
}
@@ -1762,7 +1774,7 @@ public final class PowerManagerService extends SystemService
+ ", uid=" + uid);
}
if (eventTime < mLastWakeTime || mWakefulness == WAKEFULNESS_ASLEEP
if (eventTime < mLastWakeTime || getWakefulnessLocked() == WAKEFULNESS_ASLEEP
|| !mBootCompleted || !mSystemReady) {
return false;
}
@@ -1781,13 +1793,15 @@ public final class PowerManagerService extends SystemService
@VisibleForTesting
void setWakefulnessLocked(int wakefulness, int reason, long eventTime) {
if (mWakefulness != wakefulness) {
mWakefulness = wakefulness;
if (getWakefulnessLocked() != wakefulness) {
// Under lock, invalidate before set ensures caches won't return stale values.
mInjector.invalidateIsInteractiveCaches();
mWakefulnessRaw = wakefulness;
mWakefulnessChanging = true;
mDirty |= DIRTY_WAKEFULNESS;
// This is only valid while we are in wakefulness dozing. Set to false otherwise.
mDozeStartInProgress &= (mWakefulness == WAKEFULNESS_DOZING);
mDozeStartInProgress &= (getWakefulnessLocked() == WAKEFULNESS_DOZING);
if (mNotifier != null) {
mNotifier.onWakefulnessChangeStarted(wakefulness, reason, eventTime);
@@ -1797,8 +1811,8 @@ public final class PowerManagerService extends SystemService
}
@VisibleForTesting
int getWakefulness() {
return mWakefulness;
int getWakefulnessLocked() {
return mWakefulnessRaw;
}
/**
@@ -1816,17 +1830,18 @@ public final class PowerManagerService extends SystemService
private void finishWakefulnessChangeIfNeededLocked() {
if (mWakefulnessChanging && mDisplayReady) {
if (mWakefulness == WAKEFULNESS_DOZING
if (getWakefulnessLocked() == WAKEFULNESS_DOZING
&& (mWakeLockSummary & WAKE_LOCK_DOZE) == 0) {
return; // wait until dream has enabled dozing
} else {
// Doze wakelock acquired (doze started) or device is no longer dozing.
mDozeStartInProgress = false;
}
if (mWakefulness == WAKEFULNESS_DOZING || mWakefulness == WAKEFULNESS_ASLEEP) {
if (getWakefulnessLocked() == WAKEFULNESS_DOZING
|| getWakefulnessLocked() == WAKEFULNESS_ASLEEP) {
logSleepTimeoutRecapturedLocked();
}
if (mWakefulness == WAKEFULNESS_AWAKE) {
if (getWakefulnessLocked() == WAKEFULNESS_AWAKE) {
Trace.asyncTraceEnd(Trace.TRACE_TAG_POWER, TRACE_SCREEN_ON, 0);
final int latencyMs = (int) (SystemClock.uptimeMillis() - mLastWakeTime);
if (latencyMs >= SCREEN_ON_LATENCY_WARNING_MS) {
@@ -2006,7 +2021,7 @@ public final class PowerManagerService extends SystemService
}
// If already dreaming and becoming powered, then don't wake.
if (mIsPowered && mWakefulness == WAKEFULNESS_DREAMING) {
if (mIsPowered && getWakefulnessLocked() == WAKEFULNESS_DREAMING) {
return false;
}
@@ -2016,7 +2031,7 @@ public final class PowerManagerService extends SystemService
}
// On Always On Display, SystemUI shows the charging indicator
if (mAlwaysOnEnabled && mWakefulness == WAKEFULNESS_DOZING) {
if (mAlwaysOnEnabled && getWakefulnessLocked() == WAKEFULNESS_DOZING) {
return false;
}
@@ -2081,7 +2096,7 @@ public final class PowerManagerService extends SystemService
if (DEBUG_SPEW) {
Slog.d(TAG, "updateWakeLockSummaryLocked: mWakefulness="
+ PowerManagerInternal.wakefulnessToString(mWakefulness)
+ PowerManagerInternal.wakefulnessToString(getWakefulnessLocked())
+ ", mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary));
}
}
@@ -2089,23 +2104,23 @@ public final class PowerManagerService extends SystemService
private int adjustWakeLockSummaryLocked(int wakeLockSummary) {
// Cancel wake locks that make no sense based on the current state.
if (mWakefulness != WAKEFULNESS_DOZING) {
if (getWakefulnessLocked() != WAKEFULNESS_DOZING) {
wakeLockSummary &= ~(WAKE_LOCK_DOZE | WAKE_LOCK_DRAW);
}
if (mWakefulness == WAKEFULNESS_ASLEEP
if (getWakefulnessLocked() == WAKEFULNESS_ASLEEP
|| (wakeLockSummary & WAKE_LOCK_DOZE) != 0) {
wakeLockSummary &= ~(WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_SCREEN_DIM
| WAKE_LOCK_BUTTON_BRIGHT);
if (mWakefulness == WAKEFULNESS_ASLEEP) {
if (getWakefulnessLocked() == WAKEFULNESS_ASLEEP) {
wakeLockSummary &= ~WAKE_LOCK_PROXIMITY_SCREEN_OFF;
}
}
// Infer implied wake locks where necessary based on the current state.
if ((wakeLockSummary & (WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_SCREEN_DIM)) != 0) {
if (mWakefulness == WAKEFULNESS_AWAKE) {
if (getWakefulnessLocked() == WAKEFULNESS_AWAKE) {
wakeLockSummary |= WAKE_LOCK_CPU | WAKE_LOCK_STAY_AWAKE;
} else if (mWakefulness == WAKEFULNESS_DREAMING) {
} else if (getWakefulnessLocked() == WAKEFULNESS_DREAMING) {
wakeLockSummary |= WAKE_LOCK_CPU;
}
}
@@ -2213,9 +2228,9 @@ public final class PowerManagerService extends SystemService
mHandler.removeMessages(MSG_USER_ACTIVITY_TIMEOUT);
long nextTimeout = 0;
if (mWakefulness == WAKEFULNESS_AWAKE
|| mWakefulness == WAKEFULNESS_DREAMING
|| mWakefulness == WAKEFULNESS_DOZING) {
if (getWakefulnessLocked() == WAKEFULNESS_AWAKE
|| getWakefulnessLocked() == WAKEFULNESS_DREAMING
|| getWakefulnessLocked() == WAKEFULNESS_DOZING) {
final long attentiveTimeout = getAttentiveTimeoutLocked();
final long sleepTimeout = getSleepTimeoutLocked(attentiveTimeout);
final long screenOffTimeout = getScreenOffTimeoutLocked(sleepTimeout,
@@ -2299,7 +2314,7 @@ public final class PowerManagerService extends SystemService
if (DEBUG_SPEW) {
Slog.d(TAG, "updateUserActivitySummaryLocked: mWakefulness="
+ PowerManagerInternal.wakefulnessToString(mWakefulness)
+ PowerManagerInternal.wakefulnessToString(getWakefulnessLocked())
+ ", mUserActivitySummary=0x" + Integer.toHexString(mUserActivitySummary)
+ ", nextTimeout=" + TimeUtils.formatUptime(nextTimeout));
}
@@ -2368,7 +2383,7 @@ public final class PowerManagerService extends SystemService
mInattentiveSleepWarningOverlayController.show();
nextTimeout = goToSleepTime;
} else {
if (DEBUG && mWakefulness != WAKEFULNESS_ASLEEP) {
if (DEBUG && getWakefulnessLocked() != WAKEFULNESS_ASLEEP) {
Slog.i(TAG, "Going to sleep now due to long user inactivity");
}
}
@@ -2386,7 +2401,7 @@ public final class PowerManagerService extends SystemService
return false;
}
if (mWakefulness != WAKEFULNESS_AWAKE) {
if (getWakefulnessLocked() != WAKEFULNESS_AWAKE) {
mInattentiveSleepWarningOverlayController.dismiss(false);
return true;
} else if (attentiveTimeout < 0 || isBeingKeptFromShowingInattentiveSleepWarningLocked()
@@ -2490,7 +2505,7 @@ public final class PowerManagerService extends SystemService
| DIRTY_WAKEFULNESS | DIRTY_STAY_ON | DIRTY_PROXIMITY_POSITIVE
| DIRTY_DOCK_STATE | DIRTY_ATTENTIVE | DIRTY_SETTINGS
| DIRTY_SCREEN_BRIGHTNESS_BOOST)) != 0) {
if (mWakefulness == WAKEFULNESS_AWAKE && isItBedTimeYetLocked()) {
if (getWakefulnessLocked() == WAKEFULNESS_AWAKE && isItBedTimeYetLocked()) {
if (DEBUG_SPEW) {
Slog.d(TAG, "updateWakefulnessLocked: Bed time...");
}
@@ -2613,7 +2628,7 @@ public final class PowerManagerService extends SystemService
final int wakefulness;
synchronized (mLock) {
mSandmanScheduled = false;
wakefulness = mWakefulness;
wakefulness = getWakefulnessLocked();
if (mSandmanSummoned && mDisplayReady) {
startDreaming = canDreamLocked() || canDozeLocked();
mSandmanSummoned = false;
@@ -2655,7 +2670,7 @@ public final class PowerManagerService extends SystemService
// If preconditions changed, wait for the next iteration to determine
// whether the dream should continue (or be restarted).
if (mSandmanSummoned || mWakefulness != wakefulness) {
if (mSandmanSummoned || getWakefulnessLocked() != wakefulness) {
return; // wait for next cycle
}
@@ -2717,7 +2732,7 @@ public final class PowerManagerService extends SystemService
* Returns true if the device is allowed to dream in its current state.
*/
private boolean canDreamLocked() {
if (mWakefulness != WAKEFULNESS_DREAMING
if (getWakefulnessLocked() != WAKEFULNESS_DREAMING
|| !mDreamsSupportedConfig
|| !mDreamsEnabledSetting
|| !mDisplayPowerRequest.isBrightOrDim()
@@ -2749,7 +2764,7 @@ public final class PowerManagerService extends SystemService
* Returns true if the device is allowed to doze in its current state.
*/
private boolean canDozeLocked() {
return mWakefulness == WAKEFULNESS_DOZING;
return getWakefulnessLocked() == WAKEFULNESS_DOZING;
}
/**
@@ -2825,7 +2840,7 @@ public final class PowerManagerService extends SystemService
if (DEBUG_SPEW) {
Slog.d(TAG, "updateDisplayPowerStateLocked: mDisplayReady=" + mDisplayReady
+ ", policy=" + mDisplayPowerRequest.policy
+ ", mWakefulness=" + mWakefulness
+ ", mWakefulness=" + getWakefulnessLocked()
+ ", mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary)
+ ", mUserActivitySummary=0x" + Integer.toHexString(mUserActivitySummary)
+ ", mBootCompleted=" + mBootCompleted
@@ -2871,11 +2886,11 @@ public final class PowerManagerService extends SystemService
@VisibleForTesting
int getDesiredScreenPolicyLocked() {
if (mWakefulness == WAKEFULNESS_ASLEEP || sQuiescent) {
if (getWakefulnessLocked() == WAKEFULNESS_ASLEEP || sQuiescent) {
return DisplayPowerRequest.POLICY_OFF;
}
if (mWakefulness == WAKEFULNESS_DOZING) {
if (getWakefulnessLocked() == WAKEFULNESS_DOZING) {
if ((mWakeLockSummary & WAKE_LOCK_DOZE) != 0) {
return DisplayPowerRequest.POLICY_DOZE;
}
@@ -3079,7 +3094,7 @@ public final class PowerManagerService extends SystemService
// Here we wait for mWakefulnessChanging to become false since the wakefulness
// transition to DOZING isn't considered "changed" until the doze wake lock is
// acquired.
if (mWakefulness == WAKEFULNESS_DOZING && mDozeStartInProgress) {
if (getWakefulnessLocked() == WAKEFULNESS_DOZING && mDozeStartInProgress) {
return true;
}
@@ -3119,7 +3134,7 @@ public final class PowerManagerService extends SystemService
private boolean isInteractiveInternal() {
synchronized (mLock) {
return PowerManagerInternal.isInteractive(mWakefulness);
return PowerManagerInternal.isInteractive(getWakefulnessLocked());
}
}
@@ -3495,7 +3510,7 @@ public final class PowerManagerService extends SystemService
private void boostScreenBrightnessInternal(long eventTime, int uid) {
synchronized (mLock) {
if (!mSystemReady || mWakefulness == WAKEFULNESS_ASLEEP
if (!mSystemReady || getWakefulnessLocked() == WAKEFULNESS_ASLEEP
|| eventTime < mLastScreenBrightnessBoostTime) {
return;
}
@@ -3725,7 +3740,8 @@ public final class PowerManagerService extends SystemService
pw.println("Power Manager State:");
mConstants.dump(pw);
pw.println(" mDirty=0x" + Integer.toHexString(mDirty));
pw.println(" mWakefulness=" + PowerManagerInternal.wakefulnessToString(mWakefulness));
pw.println(" mWakefulness="
+ PowerManagerInternal.wakefulnessToString(getWakefulnessLocked()));
pw.println(" mWakefulnessChanging=" + mWakefulnessChanging);
pw.println(" mIsPowered=" + mIsPowered);
pw.println(" mPlugType=" + mPlugType);
@@ -3936,7 +3952,7 @@ public final class PowerManagerService extends SystemService
synchronized (mLock) {
mConstants.dumpProto(proto);
proto.write(PowerManagerServiceDumpProto.DIRTY, mDirty);
proto.write(PowerManagerServiceDumpProto.WAKEFULNESS, mWakefulness);
proto.write(PowerManagerServiceDumpProto.WAKEFULNESS, getWakefulnessLocked());
proto.write(PowerManagerServiceDumpProto.IS_WAKEFULNESS_CHANGING, mWakefulnessChanging);
proto.write(PowerManagerServiceDumpProto.IS_POWERED, mIsPowered);
proto.write(PowerManagerServiceDumpProto.PLUG_TYPE, mPlugType);

View File

@@ -38,7 +38,6 @@ import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.Preconditions;
import com.android.server.EventLogTags;
import com.android.server.LocalServices;
import com.android.server.power.PowerManagerService;
@@ -76,11 +75,19 @@ public class BatterySaverController implements BatterySaverPolicyListener {
@GuardedBy("mLock")
private final ArrayList<LowPowerModeListener> mListeners = new ArrayList<>();
/**
* Do not access directly; always use {@link #setFullEnabledLocked}
* and {@link #getFullEnabledLocked}
*/
@GuardedBy("mLock")
private boolean mFullEnabled;
private boolean mFullEnabledRaw;
/**
* Do not access directly; always use {@link #setAdaptiveEnabledLocked} and
* {@link #getAdaptiveEnabledLocked}.
*/
@GuardedBy("mLock")
private boolean mAdaptiveEnabled;
private boolean mAdaptiveEnabledRaw;
@GuardedBy("mLock")
private boolean mIsPluggedIn;
@@ -208,6 +215,7 @@ public class BatterySaverController implements BatterySaverPolicyListener {
mPlugins = new Plugin[] {
new BatterySaverLocationPlugin(mContext)
};
PowerManager.invalidatePowerSaveModeCaches();
}
/**
@@ -294,10 +302,10 @@ public class BatterySaverController implements BatterySaverPolicyListener {
@VisibleForTesting
public void enableBatterySaver(boolean enable, int reason) {
synchronized (mLock) {
if (mFullEnabled == enable) {
if (getFullEnabledLocked() == enable) {
return;
}
mFullEnabled = enable;
setFullEnabledLocked(enable);
if (updatePolicyLevelLocked()) {
mHandler.postStateChanged(/*sendBroadcast=*/ true, reason);
@@ -306,9 +314,9 @@ public class BatterySaverController implements BatterySaverPolicyListener {
}
private boolean updatePolicyLevelLocked() {
if (mFullEnabled) {
if (getFullEnabledLocked()) {
return mBatterySaverPolicy.setPolicyLevel(BatterySaverPolicy.POLICY_LEVEL_FULL);
} else if (mAdaptiveEnabled) {
} else if (getAdaptiveEnabledLocked()) {
return mBatterySaverPolicy.setPolicyLevel(BatterySaverPolicy.POLICY_LEVEL_ADAPTIVE);
} else {
return mBatterySaverPolicy.setPolicyLevel(BatterySaverPolicy.POLICY_LEVEL_OFF);
@@ -321,8 +329,8 @@ public class BatterySaverController implements BatterySaverPolicyListener {
*/
public boolean isEnabled() {
synchronized (mLock) {
return mFullEnabled
|| (mAdaptiveEnabled && mBatterySaverPolicy.shouldAdvertiseIsEnabled());
return getFullEnabledLocked() || (getAdaptiveEnabledLocked()
&& mBatterySaverPolicy.shouldAdvertiseIsEnabled());
}
}
@@ -332,19 +340,19 @@ public class BatterySaverController implements BatterySaverPolicyListener {
*/
private boolean isPolicyEnabled() {
synchronized (mLock) {
return mFullEnabled || mAdaptiveEnabled;
return getFullEnabledLocked() || getAdaptiveEnabledLocked();
}
}
boolean isFullEnabled() {
synchronized (mLock) {
return mFullEnabled;
return getFullEnabledLocked();
}
}
boolean isAdaptiveEnabled() {
synchronized (mLock) {
return mAdaptiveEnabled;
return getAdaptiveEnabledLocked();
}
}
@@ -375,10 +383,10 @@ public class BatterySaverController implements BatterySaverPolicyListener {
}
boolean setAdaptivePolicyEnabledLocked(boolean enabled, int reason) {
if (mAdaptiveEnabled == enabled) {
if (getAdaptiveEnabledLocked() == enabled) {
return false;
}
mAdaptiveEnabled = enabled;
setAdaptiveEnabledLocked(enabled);
if (updatePolicyLevelLocked()) {
mHandler.postStateChanged(/*sendBroadcast=*/ true, reason);
return true;
@@ -427,19 +435,19 @@ public class BatterySaverController implements BatterySaverPolicyListener {
final ArrayMap<String, String> fileValues;
synchronized (mLock) {
enabled = mFullEnabled || mAdaptiveEnabled;
enabled = getFullEnabledLocked() || getAdaptiveEnabledLocked();
EventLogTags.writeBatterySaverMode(
mFullPreviouslyEnabled ? 1 : 0, // Previously off or on.
mAdaptivePreviouslyEnabled ? 1 : 0, // Previously off or on.
mFullEnabled ? 1 : 0, // Now off or on.
mAdaptiveEnabled ? 1 : 0, // Now off or on.
getFullEnabledLocked() ? 1 : 0, // Now off or on.
getAdaptiveEnabledLocked() ? 1 : 0, // Now off or on.
isInteractive ? 1 : 0, // Device interactive state.
enabled ? mBatterySaverPolicy.toEventLogString() : "",
reason);
mFullPreviouslyEnabled = mFullEnabled;
mAdaptivePreviouslyEnabled = mAdaptiveEnabled;
mFullPreviouslyEnabled = getFullEnabledLocked();
mAdaptivePreviouslyEnabled = getAdaptiveEnabledLocked();
listeners = mListeners.toArray(new LowPowerModeListener[0]);
@@ -518,10 +526,40 @@ public class BatterySaverController implements BatterySaverPolicyListener {
return;
}
mBatterySavingStats.transitionState(
mFullEnabled ? BatterySaverState.ON :
(mAdaptiveEnabled ? BatterySaverState.ADAPTIVE : BatterySaverState.OFF),
isInteractive ? InteractiveState.INTERACTIVE : InteractiveState.NON_INTERACTIVE,
dozeMode);
getFullEnabledLocked() ? BatterySaverState.ON :
(getAdaptiveEnabledLocked() ? BatterySaverState.ADAPTIVE :
BatterySaverState.OFF),
isInteractive ? InteractiveState.INTERACTIVE :
InteractiveState.NON_INTERACTIVE,
dozeMode);
}
}
@GuardedBy("mLock")
private void setFullEnabledLocked(boolean value) {
if (mFullEnabledRaw == value) {
return;
}
PowerManager.invalidatePowerSaveModeCaches();
mFullEnabledRaw = value;
}
/** Non-blocking getter exists as a reminder not to directly modify the cached field */
private boolean getFullEnabledLocked() {
return mFullEnabledRaw;
}
@GuardedBy("mLock")
private void setAdaptiveEnabledLocked(boolean value) {
if (mAdaptiveEnabledRaw == value) {
return;
}
PowerManager.invalidatePowerSaveModeCaches();
mAdaptiveEnabledRaw = value;
}
/** Non-blocking getter exists as a reminder not to directly modify the cached field */
private boolean getAdaptiveEnabledLocked() {
return mAdaptiveEnabledRaw;
}
}

View File

@@ -219,8 +219,12 @@ public class BatterySaverPolicy extends ContentObserver {
static final int POLICY_LEVEL_ADAPTIVE = 1;
static final int POLICY_LEVEL_FULL = 2;
/**
* Do not access directly; always use {@link #setPolicyLevel}
* and {@link #getPolicyLevelLocked}
*/
@GuardedBy("mLock")
private int mPolicyLevel = POLICY_LEVEL_OFF;
private int mPolicyLevelRaw = POLICY_LEVEL_OFF;
private final Context mContext;
private final ContentResolver mContentResolver;
@@ -290,6 +294,11 @@ public class BatterySaverPolicy extends ContentObserver {
return R.string.config_batterySaverDeviceSpecificConfig;
}
@VisibleForTesting
void invalidatePowerSaveModeCaches() {
PowerManager.invalidatePowerSaveModeCaches();
}
@Override
public void onChange(boolean selfChange, Uri uri) {
refreshSettings();
@@ -373,14 +382,14 @@ public class BatterySaverPolicy extends ContentObserver {
boolean changed = false;
Policy newFullPolicy = Policy.fromSettings(setting, deviceSpecificSetting,
DEFAULT_FULL_POLICY);
if (mPolicyLevel == POLICY_LEVEL_FULL && !mFullPolicy.equals(newFullPolicy)) {
if (getPolicyLevelLocked() == POLICY_LEVEL_FULL && !mFullPolicy.equals(newFullPolicy)) {
changed = true;
}
mFullPolicy = newFullPolicy;
mDefaultAdaptivePolicy = Policy.fromSettings(adaptiveSetting, adaptiveDeviceSpecificSetting,
DEFAULT_ADAPTIVE_POLICY);
if (mPolicyLevel == POLICY_LEVEL_ADAPTIVE
if (getPolicyLevelLocked() == POLICY_LEVEL_ADAPTIVE
&& !mAdaptivePolicy.equals(mDefaultAdaptivePolicy)) {
changed = true;
}
@@ -882,14 +891,14 @@ public class BatterySaverPolicy extends ContentObserver {
*/
boolean setPolicyLevel(@PolicyLevel int level) {
synchronized (mLock) {
if (mPolicyLevel == level) {
if (getPolicyLevelLocked() == level) {
return false;
}
switch (level) {
case POLICY_LEVEL_FULL:
case POLICY_LEVEL_ADAPTIVE:
case POLICY_LEVEL_OFF:
mPolicyLevel = level;
setPolicyLevelLocked(level);
break;
default:
Slog.wtf(TAG, "setPolicyLevel invalid level given: " + level);
@@ -911,7 +920,7 @@ public class BatterySaverPolicy extends ContentObserver {
}
mAdaptivePolicy = p;
if (mPolicyLevel == POLICY_LEVEL_ADAPTIVE) {
if (getPolicyLevelLocked() == POLICY_LEVEL_ADAPTIVE) {
updatePolicyDependenciesLocked();
return true;
}
@@ -924,7 +933,7 @@ public class BatterySaverPolicy extends ContentObserver {
}
private Policy getCurrentPolicyLocked() {
switch (mPolicyLevel) {
switch (getPolicyLevelLocked()) {
case POLICY_LEVEL_FULL:
return mFullPolicy;
case POLICY_LEVEL_ADAPTIVE:
@@ -985,7 +994,7 @@ public class BatterySaverPolicy extends ContentObserver {
pw.println(" value: " + mAdaptiveDeviceSpecificSettings);
pw.println(" mAccessibilityEnabled=" + mAccessibilityEnabled);
pw.println(" mPolicyLevel=" + mPolicyLevel);
pw.println(" mPolicyLevel=" + getPolicyLevelLocked());
dumpPolicyLocked(pw, " ", "full", mFullPolicy);
dumpPolicyLocked(pw, " ", "default adaptive", mDefaultAdaptivePolicy);
@@ -1067,4 +1076,20 @@ public class BatterySaverPolicy extends ContentObserver {
updatePolicyDependenciesLocked();
}
}
/** Non-blocking getter exists as a reminder not to modify cached fields directly */
@GuardedBy("mLock")
private int getPolicyLevelLocked() {
return mPolicyLevelRaw;
}
@GuardedBy("mLock")
private void setPolicyLevelLocked(int level) {
if (mPolicyLevelRaw == level) {
return;
}
// Under lock, invalidate before set ensures caches won't return stale values.
invalidatePowerSaveModeCaches();
mPolicyLevelRaw = level;
}
}

View File

@@ -45,6 +45,7 @@ import com.android.internal.app.IBatteryStats;
import com.android.internal.os.BatteryStatsImpl;
import com.android.server.LocalServices;
import com.android.server.policy.WindowManagerPolicy;
import com.android.server.power.batterysaver.BatterySaverController;
import com.android.server.power.batterysaver.BatterySaverPolicy;
import com.android.server.power.batterysaver.BatterySavingStats;
import com.android.server.statusbar.StatusBarManagerInternal;
@@ -61,6 +62,7 @@ public class NotifierTest {
private static final String SYSTEM_PROPERTY_QUIESCENT = "ro.boot.quiescent";
private static final int USER_ID = 0;
@Mock private BatterySaverController mBatterySaverControllerMock;
@Mock private BatterySaverPolicy mBatterySaverPolicyMock;
@Mock private PowerManagerService.NativeWrapper mNativeWrapperMock;
@Mock private Notifier mNotifierMock;
@@ -222,6 +224,13 @@ public class NotifierTest {
return mBatterySaverPolicyMock;
}
@Override
BatterySaverController createBatterySaverController(
Object lock, Context context, BatterySaverPolicy batterySaverPolicy,
BatterySavingStats batterySavingStats) {
return mBatterySaverControllerMock;
}
@Override
PowerManagerService.NativeWrapper createNativeWrapper() {
return mNativeWrapperMock;
@@ -247,6 +256,11 @@ public class NotifierTest {
public SystemPropertiesWrapper createSystemPropertiesWrapper() {
return mSystemPropertiesMock;
}
@Override
void invalidateIsInteractiveCaches() {
// Avoids an SELinux denial.
}
};
private void enableChargingFeedback(boolean chargingFeedbackEnabled, boolean dndOn) {

View File

@@ -81,6 +81,7 @@ import com.android.server.power.PowerManagerService.BatteryReceiver;
import com.android.server.power.PowerManagerService.Injector;
import com.android.server.power.PowerManagerService.NativeWrapper;
import com.android.server.power.PowerManagerService.UserSwitchedReceiver;
import com.android.server.power.batterysaver.BatterySaverController;
import com.android.server.power.batterysaver.BatterySaverPolicy;
import com.android.server.power.batterysaver.BatterySavingStats;
@@ -106,6 +107,7 @@ public class PowerManagerServiceTest {
private static final float BRIGHTNESS_FACTOR = 0.7f;
private static final boolean BATTERY_SAVER_ENABLED = true;
@Mock private BatterySaverController mBatterySaverControllerMock;
@Mock private BatterySaverPolicy mBatterySaverPolicyMock;
@Mock private LightsManager mLightsManagerMock;
@Mock private DisplayManagerInternal mDisplayManagerInternalMock;
@@ -206,6 +208,13 @@ public class PowerManagerServiceTest {
return mBatterySaverPolicyMock;
}
@Override
BatterySaverController createBatterySaverController(
Object lock, Context context, BatterySaverPolicy batterySaverPolicy,
BatterySavingStats batterySavingStats) {
return mBatterySaverControllerMock;
}
@Override
NativeWrapper createNativeWrapper() {
return mNativeWrapperMock;
@@ -231,6 +240,11 @@ public class PowerManagerServiceTest {
public SystemPropertiesWrapper createSystemPropertiesWrapper() {
return mSystemPropertiesMock;
}
@Override
void invalidateIsInteractiveCaches() {
// Avoids an SELinux failure.
}
});
return mService;
}
@@ -369,7 +383,7 @@ public class PowerManagerServiceTest {
@Test
public void testWakefulnessAwake_InitialValue() throws Exception {
createService();
assertThat(mService.getWakefulness()).isEqualTo(WAKEFULNESS_AWAKE);
assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
}
@Test
@@ -377,12 +391,12 @@ public class PowerManagerServiceTest {
createService();
// Start with AWAKE state
startSystem();
assertThat(mService.getWakefulness()).isEqualTo(WAKEFULNESS_AWAKE);
assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
// Take a nap and verify.
mService.getBinderServiceInstance().goToSleep(SystemClock.uptimeMillis(),
PowerManager.GO_TO_SLEEP_REASON_APPLICATION, PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
assertThat(mService.getWakefulness()).isEqualTo(WAKEFULNESS_ASLEEP);
assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
}
@Test
@@ -399,21 +413,21 @@ public class PowerManagerServiceTest {
int flags = PowerManager.FULL_WAKE_LOCK;
mService.getBinderServiceInstance().acquireWakeLock(token, flags, tag, packageName,
null /* workSource */, null /* historyTag */);
assertThat(mService.getWakefulness()).isEqualTo(WAKEFULNESS_ASLEEP);
assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
mService.getBinderServiceInstance().releaseWakeLock(token, 0 /* flags */);
// Ensure that the flag does *NOT* work with a partial wake lock.
flags = PowerManager.PARTIAL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP;
mService.getBinderServiceInstance().acquireWakeLock(token, flags, tag, packageName,
null /* workSource */, null /* historyTag */);
assertThat(mService.getWakefulness()).isEqualTo(WAKEFULNESS_ASLEEP);
assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
mService.getBinderServiceInstance().releaseWakeLock(token, 0 /* flags */);
// Verify that flag forces a wakeup when paired to a FULL_WAKE_LOCK
flags = PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP;
mService.getBinderServiceInstance().acquireWakeLock(token, flags, tag, packageName,
null /* workSource */, null /* historyTag */);
assertThat(mService.getWakefulness()).isEqualTo(WAKEFULNESS_AWAKE);
assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
mService.getBinderServiceInstance().releaseWakeLock(token, 0 /* flags */);
}
@@ -424,7 +438,7 @@ public class PowerManagerServiceTest {
forceSleep();
mService.getBinderServiceInstance().wakeUp(SystemClock.uptimeMillis(),
PowerManager.WAKE_REASON_UNKNOWN, "testing IPowerManager.wakeUp()", "pkg.name");
assertThat(mService.getWakefulness()).isEqualTo(WAKEFULNESS_AWAKE);
assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
}
/**
@@ -445,7 +459,7 @@ public class PowerManagerServiceTest {
.thenReturn(false);
mService.readConfigurationLocked();
setPluggedIn(true);
assertThat(mService.getWakefulness()).isEqualTo(WAKEFULNESS_ASLEEP);
assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
when(mResourcesSpy.getBoolean(com.android.internal.R.bool.config_unplugTurnsOnScreen))
.thenReturn(true);
mService.readConfigurationLocked();
@@ -460,20 +474,20 @@ public class PowerManagerServiceTest {
when(mWirelessChargerDetectorMock.update(true /* isPowered */,
BatteryManager.BATTERY_PLUGGED_WIRELESS)).thenReturn(false);
setPluggedIn(true);
assertThat(mService.getWakefulness()).isEqualTo(WAKEFULNESS_ASLEEP);
assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
// Test 3:
// Do not wake up if the phone is being REMOVED from a wireless charger
when(mBatteryManagerInternalMock.getPlugType()).thenReturn(0);
setPluggedIn(false);
assertThat(mService.getWakefulness()).isEqualTo(WAKEFULNESS_ASLEEP);
assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
// Test 4:
// Do not wake if we are dreaming.
forceAwake(); // Needs to be awake first before it can dream.
forceDream();
setPluggedIn(true);
assertThat(mService.getWakefulness()).isEqualTo(WAKEFULNESS_DREAMING);
assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_DREAMING);
forceSleep();
// Test 5:
@@ -486,7 +500,7 @@ public class PowerManagerServiceTest {
com.android.internal.R.bool.config_allowTheaterModeWakeFromUnplug))
.thenReturn(false);
setPluggedIn(false);
assertThat(mService.getWakefulness()).isEqualTo(WAKEFULNESS_ASLEEP);
assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
Settings.Global.putInt(
mContextSpy.getContentResolver(), Settings.Global.THEATER_MODE_ON, 0);
mUserSwitchedReceiver.onReceive(mContextSpy, new Intent(Intent.ACTION_USER_SWITCHED));
@@ -499,14 +513,14 @@ public class PowerManagerServiceTest {
forceAwake();
forceDozing();
setPluggedIn(true);
assertThat(mService.getWakefulness()).isEqualTo(WAKEFULNESS_DOZING);
assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_DOZING);
// Test 7:
// Finally, take away all the factors above and ensure the device wakes up!
forceAwake();
forceSleep();
setPluggedIn(false);
assertThat(mService.getWakefulness()).isEqualTo(WAKEFULNESS_AWAKE);
assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
}
@Test
@@ -514,12 +528,12 @@ public class PowerManagerServiceTest {
createService();
// Start with AWAKE state
startSystem();
assertThat(mService.getWakefulness()).isEqualTo(WAKEFULNESS_AWAKE);
assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
// Take a nap and verify.
mService.getBinderServiceInstance().goToSleep(SystemClock.uptimeMillis(),
PowerManager.GO_TO_SLEEP_REASON_APPLICATION, 0);
assertThat(mService.getWakefulness()).isEqualTo(WAKEFULNESS_DOZING);
assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_DOZING);
}
@Test
@@ -546,12 +560,12 @@ public class PowerManagerServiceTest {
mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
// Verify that we start awake
assertThat(mService.getWakefulness()).isEqualTo(WAKEFULNESS_AWAKE);
assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
// Grab the wakefulness value when PowerManager finally calls into the
// native component to actually perform the suspend.
when(mNativeWrapperMock.nativeForceSuspend()).then(inv -> {
assertThat(mService.getWakefulness()).isEqualTo(WAKEFULNESS_ASLEEP);
assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
return true;
});
@@ -559,7 +573,7 @@ public class PowerManagerServiceTest {
assertThat(retval).isTrue();
// Still asleep when the function returns.
assertThat(mService.getWakefulness()).isEqualTo(WAKEFULNESS_ASLEEP);
assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
}
@Test
@@ -592,7 +606,7 @@ public class PowerManagerServiceTest {
mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
// Verify that we start awake
assertThat(mService.getWakefulness()).isEqualTo(WAKEFULNESS_AWAKE);
assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
// Create a wakelock
mService.getBinderServiceInstance().acquireWakeLock(new Binder(), flags, tag, pkg,
@@ -647,7 +661,7 @@ public class PowerManagerServiceTest {
// Start with AWAKE state
startSystem();
assertThat(mService.getWakefulness()).isEqualTo(WAKEFULNESS_AWAKE);
assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
assertTrue(isAcquired[0]);
// Take a nap and verify we no longer hold the blocker
@@ -657,7 +671,7 @@ public class PowerManagerServiceTest {
when(mDreamManagerInternalMock.isDreaming()).thenReturn(true);
mService.getBinderServiceInstance().goToSleep(SystemClock.uptimeMillis(),
PowerManager.GO_TO_SLEEP_REASON_APPLICATION, 0);
assertThat(mService.getWakefulness()).isEqualTo(WAKEFULNESS_DOZING);
assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_DOZING);
assertFalse(isAcquired[0]);
// Override the display state by DreamManager and verify is reacquires the blocker.
@@ -737,7 +751,7 @@ public class PowerManagerServiceTest {
createService();
startSystem();
SystemClock.sleep(20);
assertThat(mService.getWakefulness()).isEqualTo(WAKEFULNESS_ASLEEP);
assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
}
@FlakyTest
@@ -757,7 +771,7 @@ public class PowerManagerServiceTest {
null /* workSource */, null /* historyTag */);
SystemClock.sleep(11);
assertThat(mService.getWakefulness()).isEqualTo(WAKEFULNESS_ASLEEP);
assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
}
@Test
@@ -765,7 +779,7 @@ public class PowerManagerServiceTest {
createService();
startSystem();
assertThat(mService.getWakefulness()).isEqualTo(WAKEFULNESS_AWAKE);
assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
verify(mNotifierMock, never()).onWakefulnessChangeStarted(anyInt(), anyInt(), anyLong());
}
@@ -784,7 +798,7 @@ public class PowerManagerServiceTest {
createService();
startSystem();
assertThat(mService.getWakefulness()).isEqualTo(WAKEFULNESS_ASLEEP);
assertThat(mService.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
verify(mNotifierMock).onWakefulnessChangeStarted(eq(WAKEFULNESS_ASLEEP), anyInt(),
anyLong());
}

View File

@@ -78,6 +78,11 @@ public class BatterySaverPolicyTest extends AndroidTestCase {
return mDeviceSpecificConfigResId;
}
@Override
void invalidatePowerSaveModeCaches() {
// Avoids an SELinux denial.
}
@VisibleForTesting
void onChange() {
onChange(true, null);