blob: 911c4a2f41221b7554e31452cfe566837fc16530 [file] [log] [blame]
/*
* Copyright (C) 2017 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.power;
import static android.os.PowerManagerInternal.WAKEFULNESS_ASLEEP;
import static android.os.PowerManagerInternal.WAKEFULNESS_AWAKE;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import android.app.ActivityManagerInternal;
import android.attention.AttentionManagerInternal;
import android.content.Context;
import android.hardware.display.DisplayManagerInternal;
import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest;
import android.os.BatteryManagerInternal;
import android.os.Binder;
import android.os.Looper;
import android.os.PowerManager;
import android.os.PowerSaveState;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.MediumTest;
import android.test.suitebuilder.annotation.SmallTest;
import com.android.internal.app.IBatteryStats;
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.lights.LightsManager;
import com.android.server.policy.WindowManagerPolicy;
import com.android.server.power.PowerManagerService.Injector;
import com.android.server.power.PowerManagerService.NativeWrapper;
import com.android.server.power.batterysaver.BatterySaverPolicy;
import com.android.server.power.batterysaver.BatterySavingStats;
import org.junit.Rule;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.HashMap;
import java.util.Map;
/**
* Tests for {@link com.android.server.power.PowerManagerService}
*/
public class PowerManagerServiceTest extends AndroidTestCase {
private static final float PRECISION = 0.001f;
private static final float BRIGHTNESS_FACTOR = 0.7f;
private static final boolean BATTERY_SAVER_ENABLED = true;
private static final String TEST_LAST_REBOOT_PROPERTY = "test.sys.boot.reason";
private @Mock BatterySaverPolicy mBatterySaverPolicyMock;
private @Mock LightsManager mLightsManagerMock;
private @Mock DisplayManagerInternal mDisplayManagerInternalMock;
private @Mock BatteryManagerInternal mBatteryManagerInternalMock;
private @Mock ActivityManagerInternal mActivityManagerInternalMock;
private @Mock AttentionManagerInternal mAttentionManagerInternalMock;
private @Mock PowerManagerService.NativeWrapper mNativeWrapperMock;
private @Mock Notifier mNotifierMock;
private PowerManagerService mService;
private PowerSaveState mPowerSaveState;
private DisplayPowerRequest mDisplayPowerRequest;
@Rule
public void setUp() throws Exception {
super.setUp();
MockitoAnnotations.initMocks(this);
mPowerSaveState = new PowerSaveState.Builder()
.setBatterySaverEnabled(BATTERY_SAVER_ENABLED)
.setBrightnessFactor(BRIGHTNESS_FACTOR)
.build();
when(mBatterySaverPolicyMock.getBatterySaverPolicy(
eq(PowerManager.ServiceType.SCREEN_BRIGHTNESS)))
.thenReturn(mPowerSaveState);
mDisplayPowerRequest = new DisplayPowerRequest();
addLocalServiceMock(LightsManager.class, mLightsManagerMock);
addLocalServiceMock(DisplayManagerInternal.class, mDisplayManagerInternalMock);
addLocalServiceMock(BatteryManagerInternal.class, mBatteryManagerInternalMock);
addLocalServiceMock(ActivityManagerInternal.class, mActivityManagerInternalMock);
addLocalServiceMock(AttentionManagerInternal.class, mAttentionManagerInternalMock);
mService = new PowerManagerService(getContext(), new Injector() {
Notifier createNotifier(Looper looper, Context context, IBatteryStats batteryStats,
SuspendBlocker suspendBlocker, WindowManagerPolicy policy) {
return mNotifierMock;
}
SuspendBlocker createSuspendBlocker(PowerManagerService service, String name) {
return mock(SuspendBlocker.class);
}
BatterySaverPolicy createBatterySaverPolicy(
Object lock, Context context, BatterySavingStats batterySavingStats) {
return mBatterySaverPolicyMock;
}
NativeWrapper createNativeWrapper() {
return mNativeWrapperMock;
}
});
}
@Override
public void tearDown() throws Exception {
LocalServices.removeServiceForTest(LightsManager.class);
LocalServices.removeServiceForTest(DisplayManagerInternal.class);
LocalServices.removeServiceForTest(BatteryManagerInternal.class);
LocalServices.removeServiceForTest(ActivityManagerInternal.class);
}
/**
* Creates a mock and registers it to {@link LocalServices}.
*/
private static <T> void addLocalServiceMock(Class<T> clazz, T mock) {
LocalServices.removeServiceForTest(clazz);
LocalServices.addService(clazz, mock);
}
@SmallTest
public void testUpdatePowerScreenPolicy_UpdateDisplayPowerRequest() {
mService.updatePowerRequestFromBatterySaverPolicy(mDisplayPowerRequest);
assertThat(mDisplayPowerRequest.lowPowerMode).isEqualTo(BATTERY_SAVER_ENABLED);
assertThat(mDisplayPowerRequest.screenLowPowerBrightnessFactor)
.isWithin(PRECISION).of(BRIGHTNESS_FACTOR);
}
@SmallTest
public void testGetLastShutdownReasonInternal() {
SystemProperties.set(TEST_LAST_REBOOT_PROPERTY, "shutdown,thermal");
int reason = mService.getLastShutdownReasonInternal(TEST_LAST_REBOOT_PROPERTY);
SystemProperties.set(TEST_LAST_REBOOT_PROPERTY, "");
assertThat(reason).isEqualTo(PowerManager.SHUTDOWN_REASON_THERMAL_SHUTDOWN);
}
@SmallTest
public void testGetDesiredScreenPolicy_WithVR() throws Exception {
// Brighten up the screen
mService.setWakefulnessLocked(WAKEFULNESS_AWAKE, PowerManager.WAKE_REASON_UNKNOWN, 0);
assertThat(mService.getDesiredScreenPolicyLocked()).isEqualTo(
DisplayPowerRequest.POLICY_BRIGHT);
// Move to VR
mService.setVrModeEnabled(true);
assertThat(mService.getDesiredScreenPolicyLocked()).isEqualTo(
DisplayPowerRequest.POLICY_VR);
// Then take a nap
mService.setWakefulnessLocked(WAKEFULNESS_ASLEEP, PowerManager.GO_TO_SLEEP_REASON_TIMEOUT,
0);
assertThat(mService.getDesiredScreenPolicyLocked()).isEqualTo(
DisplayPowerRequest.POLICY_OFF);
// Wake up to VR
mService.setWakefulnessLocked(WAKEFULNESS_AWAKE, PowerManager.WAKE_REASON_UNKNOWN, 0);
assertThat(mService.getDesiredScreenPolicyLocked()).isEqualTo(
DisplayPowerRequest.POLICY_VR);
// And back to normal
mService.setVrModeEnabled(false);
assertThat(mService.getDesiredScreenPolicyLocked()).isEqualTo(
DisplayPowerRequest.POLICY_BRIGHT);
}
@SmallTest
public void testWakefulnessAwake_InitialValue() throws Exception {
assertThat(mService.getWakefulness()).isEqualTo(WAKEFULNESS_AWAKE);
}
@SmallTest
public void testWakefulnessSleep_NoDozeSleepFlag() throws Exception {
// Start with AWAKE state
assertThat(mService.getWakefulness()).isEqualTo(WAKEFULNESS_AWAKE);
mService.systemReady(null);
mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
// Take a nap with a flag.
mService.getBinderServiceInstance().goToSleep(SystemClock.uptimeMillis(),
PowerManager.GO_TO_SLEEP_REASON_APPLICATION, PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
assertThat(mService.getWakefulness()).isEqualTo(WAKEFULNESS_ASLEEP);
}
@MediumTest
public void testWasDeviceIdleFor_true() {
int interval = 1000;
mService.onUserActivity();
SystemClock.sleep(interval);
assertThat(mService.wasDeviceIdleForInternal(interval)).isTrue();
}
@SmallTest
public void testWasDeviceIdleFor_false() {
int interval = 1000;
mService.onUserActivity();
assertThat(mService.wasDeviceIdleForInternal(interval)).isFalse();
}
@SmallTest
public void testForceSuspend_putsDeviceToSleep() {
mService.systemReady(null);
mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
// Verify that we start awake
assertThat(mService.getWakefulness()).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);
return true;
});
boolean retval = mService.getBinderServiceInstance().forceSuspend();
assertThat(retval).isTrue();
// Still asleep when the function returns.
assertThat(mService.getWakefulness()).isEqualTo(WAKEFULNESS_ASLEEP);
}
@SmallTest
public void testForceSuspend_pakeLocksDisabled() {
final String tag = "TestWakelockTag_098213";
final int flags = PowerManager.PARTIAL_WAKE_LOCK;
final String pkg = getContext().getOpPackageName();
// Set up the Notification mock to keep track of the wakelocks that are currently
// active or disabled. We'll use this to verify that wakelocks are disabled when
// they should be.
final Map<String, Integer> wakelockMap = new HashMap<>(1);
doAnswer(inv -> {
wakelockMap.put((String) inv.getArguments()[1], (int) inv.getArguments()[0]);
return null;
}).when(mNotifierMock).onWakeLockAcquired(anyInt(), anyString(), anyString(), anyInt(),
anyInt(), any(), any());
doAnswer(inv -> {
wakelockMap.remove((String) inv.getArguments()[1]);
return null;
}).when(mNotifierMock).onWakeLockReleased(anyInt(), anyString(), anyString(), anyInt(),
anyInt(), any(), any());
//
// TEST STARTS HERE
//
mService.systemReady(null);
mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
// Verify that we start awake
assertThat(mService.getWakefulness()).isEqualTo(WAKEFULNESS_AWAKE);
// Create a wakelock
mService.getBinderServiceInstance().acquireWakeLock(new Binder(), flags, tag, pkg,
null /* workSource */, null /* historyTag */);
assertThat(wakelockMap.get(tag)).isEqualTo(flags); // Verify wakelock is active.
// Confirm that the wakelocks have been disabled when the forceSuspend is in flight.
when(mNativeWrapperMock.nativeForceSuspend()).then(inv -> {
// Verify that the wakelock is disabled by the time we get to the native force
// suspend call.
assertThat(wakelockMap.containsKey(tag)).isFalse();
return true;
});
assertThat(mService.getBinderServiceInstance().forceSuspend()).isTrue();
assertThat(wakelockMap.get(tag)).isEqualTo(flags);
}
@SmallTest
public void testForceSuspend_forceSuspendFailurePropogated() {
when(mNativeWrapperMock.nativeForceSuspend()).thenReturn(false);
assertThat(mService.getBinderServiceInstance().forceSuspend()).isFalse();
}
}