Move logic from PMS#wakePowerGroupLocked() into PowerGroup#wakeUpLocked().

Move quiescent check into PMS#wakeUp. Add tests for
PowerGroup#dreamLocked(), #dozeLocked(), #sleepLocked() and wakeUpLocked().

Test: atest FrameworksServicesTests:PowerManagerServiceTest
Test: atest FrameworksServicesTests:PowerGroupTest
Bug: 200653844
Change-Id: I88782a37be269b9c9d28c22f5add0ecd4f3217af
This commit is contained in:
Philip Junker
2022-02-22 15:15:55 +01:00
parent c840164db8
commit f1f93f2c17
3 changed files with 124 additions and 36 deletions

View File

@@ -22,6 +22,8 @@ import static android.os.PowerManagerInternal.WAKEFULNESS_DOZING;
import static android.os.PowerManagerInternal.WAKEFULNESS_DREAMING;
import static android.os.PowerManagerInternal.isInteractive;
import static com.android.internal.util.LatencyTracker.ACTION_TURN_ON_SCREEN;
import static com.android.server.power.PowerManagerService.TRACE_SCREEN_ON;
import static com.android.server.power.PowerManagerService.USER_ACTIVITY_SCREEN_BRIGHT;
import static com.android.server.power.PowerManagerService.WAKE_LOCK_DOZE;
import static com.android.server.power.PowerManagerService.WAKE_LOCK_DRAW;
@@ -30,12 +32,14 @@ import static com.android.server.power.PowerManagerService.WAKE_LOCK_SCREEN_BRIG
import android.hardware.display.DisplayManagerInternal;
import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest;
import android.os.PowerManager;
import android.os.PowerManagerInternal;
import android.os.PowerSaveState;
import android.os.Trace;
import android.util.Slog;
import android.view.Display;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.LatencyTracker;
/**
* Used to store power related requests to every display in a
@@ -197,6 +201,32 @@ public class PowerGroup {
mIsSandmanSummoned = isSandmanSummoned;
}
void wakeUpLocked(long eventTime, @PowerManager.WakeReason int reason, String details, int uid,
String opPackageName, int opUid, LatencyTracker latencyTracker) {
if (eventTime < mLastSleepTime || mWakefulness == WAKEFULNESS_AWAKE) {
return;
}
Trace.traceBegin(Trace.TRACE_TAG_POWER, "wakePowerGroup" + mGroupId);
try {
Slog.i(TAG, "Waking up power group from "
+ PowerManagerInternal.wakefulnessToString(mWakefulness)
+ " (groupId=" + mGroupId
+ ", uid=" + uid
+ ", reason=" + PowerManager.wakeReasonToString(reason)
+ ", details=" + details
+ ")...");
Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, TRACE_SCREEN_ON, mGroupId);
// The instrument will be timed out automatically after 2 seconds.
latencyTracker.onActionStart(ACTION_TURN_ON_SCREEN, String.valueOf(mGroupId));
setWakefulnessLocked(WAKEFULNESS_AWAKE, eventTime, uid, reason, opUid,
opPackageName, details);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
}
boolean dreamLocked(long eventTime, int uid) {
if (eventTime < mLastWakeTime || mWakefulness != WAKEFULNESS_AWAKE) {
return false;

View File

@@ -246,7 +246,7 @@ public final class PowerManagerService extends SystemService
private static final String REASON_LOW_BATTERY = "shutdown,battery";
private static final String REASON_BATTERY_THERMAL_STATE = "shutdown,thermal,battery";
private static final String TRACE_SCREEN_ON = "Screen turning on";
static final String TRACE_SCREEN_ON = "Screen turning on";
/** If turning screen on takes more than this long, we show a warning on logcat. */
private static final int SCREEN_ON_LATENCY_WARNING_MS = 200;
@@ -1945,45 +1945,15 @@ public final class PowerManagerService extends SystemService
@GuardedBy("mLock")
private void wakePowerGroupLocked(final PowerGroup powerGroup, long eventTime,
@WakeReason int reason, String details, int uid, String opPackageName, int opUid) {
final int groupId = powerGroup.getGroupId();
if (DEBUG_SPEW) {
Slog.d(TAG, "wakePowerGroupLocked: eventTime=" + eventTime
+ ", groupId=" + groupId + ", uid=" + uid);
+ ", groupId=" + powerGroup.getGroupId() + ", uid=" + uid);
}
if (eventTime < powerGroup.getLastSleepTimeLocked() || mForceSuspendActive
|| !mSystemReady) {
if (mForceSuspendActive || !mSystemReady) {
return;
}
final int currentWakefulness = powerGroup.getWakefulnessLocked();
if (currentWakefulness == WAKEFULNESS_AWAKE) {
if (!mBootCompleted && sQuiescent) {
mDirty |= DIRTY_QUIESCENT;
updatePowerStateLocked();
}
return;
}
Trace.traceBegin(Trace.TRACE_TAG_POWER, "powerOnDisplay");
try {
Slog.i(TAG, "Waking up power group from "
+ PowerManagerInternal.wakefulnessToString(currentWakefulness)
+ " (groupId=" + groupId
+ ", uid=" + uid
+ ", reason=" + PowerManager.wakeReasonToString(reason)
+ ", details=" + details
+ ")...");
Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, TRACE_SCREEN_ON, groupId);
// The instrument will be timed out automatically after 2 seconds.
LatencyTracker.getInstance(mContext)
.onActionStart(ACTION_TURN_ON_SCREEN, String.valueOf(groupId));
powerGroup.setWakefulnessLocked(WAKEFULNESS_AWAKE, eventTime, uid, reason, opUid,
opPackageName, details);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_POWER);
}
powerGroup.wakeUpLocked(eventTime, reason, details, uid, opPackageName, opUid,
LatencyTracker.getInstance(mContext));
}
@GuardedBy("mLock")
@@ -5531,6 +5501,11 @@ public final class PowerManagerService extends SystemService
final long ident = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
if (!mBootCompleted && sQuiescent) {
mDirty |= DIRTY_QUIESCENT;
updatePowerStateLocked();
return;
}
wakePowerGroupLocked(mPowerGroups.get(Display.DEFAULT_DISPLAY_GROUP), eventTime,
reason, details, uid, opPackageName, uid);
}

View File

@@ -24,8 +24,10 @@ import static android.hardware.display.DisplayManagerInternal.DisplayPowerReques
import static android.hardware.display.DisplayManagerInternal.DisplayPowerRequest.POLICY_VR;
import static android.os.PowerManager.GO_TO_SLEEP_REASON_APPLICATION;
import static android.os.PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN;
import static android.os.PowerManager.GO_TO_SLEEP_REASON_DEVICE_FOLD;
import static android.os.PowerManager.GO_TO_SLEEP_REASON_TIMEOUT;
import static android.os.PowerManager.WAKE_REASON_GESTURE;
import static android.os.PowerManager.WAKE_REASON_PLUGGED_IN;
import static android.os.PowerManagerInternal.WAKEFULNESS_ASLEEP;
import static android.os.PowerManagerInternal.WAKEFULNESS_AWAKE;
import static android.os.PowerManagerInternal.WAKEFULNESS_DOZING;
@@ -37,9 +39,11 @@ import static com.android.server.power.PowerManagerService.WAKE_LOCK_SCREEN_BRIG
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.eq;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import android.hardware.display.DisplayManagerInternal;
@@ -47,6 +51,10 @@ import android.os.PowerManager;
import android.os.PowerSaveState;
import android.view.Display;
import androidx.test.platform.app.InstrumentationRegistry;
import com.android.internal.util.LatencyTracker;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
@@ -89,14 +97,89 @@ public class PowerGroupTest {
}
@Test
public void testDreamPowerGroupTriggersOnWakefulnessChangedCallback() {
public void testWakePowerGroup() {
mPowerGroup.sleepLocked(TIMESTAMP1, UID, GO_TO_SLEEP_REASON_APPLICATION);
verify(mWakefulnessCallbackMock).onWakefulnessChangedLocked(eq(GROUP_ID),
eq(WAKEFULNESS_ASLEEP), eq(TIMESTAMP1), eq(GO_TO_SLEEP_REASON_APPLICATION),
eq(UID), /* opUid= */anyInt(), /* opPackageName= */ isNull(), /* details= */
isNull());
String details = "wake PowerGroup1";
LatencyTracker latencyTracker = LatencyTracker.getInstance(
InstrumentationRegistry.getInstrumentation().getContext());
mPowerGroup.wakeUpLocked(TIMESTAMP2, WAKE_REASON_PLUGGED_IN, details, UID,
/* opPackageName= */ null, /* opUid= */ 0, latencyTracker);
verify(mWakefulnessCallbackMock).onWakefulnessChangedLocked(eq(GROUP_ID),
eq(WAKEFULNESS_AWAKE), eq(TIMESTAMP2), eq(WAKE_REASON_PLUGGED_IN), eq(UID),
/* opUid= */ anyInt(), /* opPackageName= */ isNull(), eq(details));
}
@Test
public void testDreamPowerGroup() {
assertThat(mPowerGroup.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
mPowerGroup.dreamLocked(TIMESTAMP1, UID);
assertThat(mPowerGroup.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_DREAMING);
assertThat(mPowerGroup.isSandmanSummonedLocked()).isTrue();
verify(mWakefulnessCallbackMock).onWakefulnessChangedLocked(eq(GROUP_ID),
eq(WAKEFULNESS_DREAMING), eq(TIMESTAMP1), eq(GO_TO_SLEEP_REASON_APPLICATION),
eq(UID), /* opUid= */anyInt(), /* opPackageName= */ isNull(), /* details= */
isNull());
}
@Test
public void testDozePowerGroup() {
assertThat(mPowerGroup.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
mPowerGroup.dozeLocked(TIMESTAMP1, UID, GO_TO_SLEEP_REASON_TIMEOUT);
assertThat(mPowerGroup.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_DOZING);
assertThat(mPowerGroup.isSandmanSummonedLocked()).isTrue();
verify(mWakefulnessCallbackMock).onWakefulnessChangedLocked(eq(GROUP_ID),
eq(WAKEFULNESS_DOZING), eq(TIMESTAMP1), eq(GO_TO_SLEEP_REASON_TIMEOUT),
eq(UID), /* opUid= */ anyInt(), /* opPackageName= */ isNull(),
/* details= */ isNull());
}
@Test
public void testDozePowerGroupWhenNonInteractiveHasNoEffect() {
mPowerGroup.sleepLocked(TIMESTAMP1, UID, GO_TO_SLEEP_REASON_TIMEOUT);
verify(mWakefulnessCallbackMock).onWakefulnessChangedLocked(eq(GROUP_ID),
eq(WAKEFULNESS_ASLEEP), eq(TIMESTAMP1), eq(GO_TO_SLEEP_REASON_TIMEOUT),
eq(UID), /* opUid= */ anyInt(), /* opPackageName= */ isNull(),
/* details= */ isNull());
assertThat(mPowerGroup.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
assertThat(mPowerGroup.dozeLocked(TIMESTAMP2, UID, GO_TO_SLEEP_REASON_TIMEOUT)).isFalse();
assertThat(mPowerGroup.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
verify(mWakefulnessCallbackMock, never()).onWakefulnessChangedLocked(
eq(GROUP_ID), eq(WAKEFULNESS_DOZING), eq(TIMESTAMP2), /* reason= */ anyInt(),
eq(UID), /* opUid= */ anyInt(), /* opPackageName= */ any(), /* details= */ any());
}
@Test
public void testSleepPowerGroup() {
assertThat(mPowerGroup.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
mPowerGroup.sleepLocked(TIMESTAMP1, UID, GO_TO_SLEEP_REASON_DEVICE_FOLD);
assertThat(mPowerGroup.isSandmanSummonedLocked()).isTrue();
assertThat(mPowerGroup.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
verify(mWakefulnessCallbackMock).onWakefulnessChangedLocked(eq(GROUP_ID),
eq(WAKEFULNESS_ASLEEP), eq(TIMESTAMP1), eq(GO_TO_SLEEP_REASON_DEVICE_FOLD),
eq(UID), /* opUid= */ anyInt(), /* opPackageName= */ isNull(),
/* details= */ isNull());
}
@Test
public void testDreamPowerGroupWhenNotAwakeHasNoEffect() {
mPowerGroup.dozeLocked(TIMESTAMP1, UID, GO_TO_SLEEP_REASON_TIMEOUT);
verify(mWakefulnessCallbackMock).onWakefulnessChangedLocked(eq(GROUP_ID),
eq(WAKEFULNESS_DOZING), eq(TIMESTAMP1), eq(GO_TO_SLEEP_REASON_TIMEOUT),
eq(UID), /* opUid= */ anyInt(), /* opPackageName= */ isNull(),
/* details= */ isNull());
assertThat(mPowerGroup.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_DOZING);
assertThat(mPowerGroup.dreamLocked(TIMESTAMP2, UID)).isFalse();
assertThat(mPowerGroup.getWakefulnessLocked()).isEqualTo(WAKEFULNESS_DOZING);
verify(mWakefulnessCallbackMock, never()).onWakefulnessChangedLocked(
eq(GROUP_ID), /* wakefulness= */ eq(WAKEFULNESS_DREAMING), eq(TIMESTAMP2),
/* reason= */ anyInt(), eq(UID), /* opUid= */ anyInt(), /* opPackageName= */ any(),
/* details= */ any());
}
@Test
public void testLastWakeAndSleepTimeIsUpdated() {
assertThat(mPowerGroup.getLastWakeTimeLocked()).isEqualTo(TIMESTAMP_CREATE);