diff options
7 files changed, 342 insertions, 137 deletions
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 247a5c02452e..375f53be43b5 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -1004,7 +1004,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { return; } - final boolean interactive = Display.isOnState(mDefaultDisplay.getState()); + final boolean interactive = mDefaultDisplayPolicy.isAwake(); Slog.d(TAG, "powerPress: eventTime=" + eventTime + " interactive=" + interactive + " count=" + count + " beganFromNonInteractive=" + beganFromNonInteractive @@ -2201,8 +2201,10 @@ public class PhoneWindowManager implements WindowManagerPolicy { // Match current screen state. if (!mPowerManager.isInteractive()) { - startedGoingToSleep(PowerManager.GO_TO_SLEEP_REASON_TIMEOUT); - finishedGoingToSleep(PowerManager.GO_TO_SLEEP_REASON_TIMEOUT); + startedGoingToSleep(Display.DEFAULT_DISPLAY_GROUP, + PowerManager.GO_TO_SLEEP_REASON_TIMEOUT); + finishedGoingToSleep(Display.DEFAULT_DISPLAY_GROUP, + PowerManager.GO_TO_SLEEP_REASON_TIMEOUT); } mWindowManagerInternal.registerAppTransitionListener(new AppTransitionListener() { @@ -4095,7 +4097,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { // This could prevent some wrong state in multi-displays environment, // the default display may turned off but interactive is true. - final boolean isDefaultDisplayOn = Display.isOnState(mDefaultDisplay.getState()); + final boolean isDefaultDisplayOn = mDefaultDisplayPolicy.isAwake(); final boolean interactiveAndOn = interactive && isDefaultDisplayOn; if ((event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) { handleKeyGesture(event, interactiveAndOn); @@ -4795,17 +4797,40 @@ public class PhoneWindowManager implements WindowManagerPolicy { } }; + @Override + public void startedWakingUpGlobal(@WakeReason int reason) { + + } + + @Override + public void finishedWakingUpGlobal(@WakeReason int reason) { + + } + + @Override + public void startedGoingToSleepGlobal(@PowerManager.GoToSleepReason int reason) { + mDeviceGoingToSleep = true; + } + + @Override + public void finishedGoingToSleepGlobal(@PowerManager.GoToSleepReason int reason) { + mDeviceGoingToSleep = false; + } + // Called on the PowerManager's Notifier thread. @Override - public void startedGoingToSleep(@PowerManager.GoToSleepReason int pmSleepReason) { + public void startedGoingToSleep(int displayGroupId, + @PowerManager.GoToSleepReason int pmSleepReason) { if (DEBUG_WAKEUP) { - Slog.i(TAG, "Started going to sleep... (why=" + Slog.i(TAG, "Started going to sleep... (groupId=" + displayGroupId + " why=" + WindowManagerPolicyConstants.offReasonToString( WindowManagerPolicyConstants.translateSleepReasonToOffReason( pmSleepReason)) + ")"); } + if (displayGroupId != Display.DEFAULT_DISPLAY_GROUP) { + return; + } - mDeviceGoingToSleep = true; mRequestedOrSleepingDefaultDisplay = true; if (mKeyguardDelegate != null) { @@ -4815,17 +4840,20 @@ public class PhoneWindowManager implements WindowManagerPolicy { // Called on the PowerManager's Notifier thread. @Override - public void finishedGoingToSleep(@PowerManager.GoToSleepReason int pmSleepReason) { + public void finishedGoingToSleep(int displayGroupId, + @PowerManager.GoToSleepReason int pmSleepReason) { + if (displayGroupId != Display.DEFAULT_DISPLAY_GROUP) { + return; + } EventLogTags.writeScreenToggled(0); if (DEBUG_WAKEUP) { - Slog.i(TAG, "Finished going to sleep... (why=" + Slog.i(TAG, "Finished going to sleep... (groupId=" + displayGroupId + " why=" + WindowManagerPolicyConstants.offReasonToString( WindowManagerPolicyConstants.translateSleepReasonToOffReason( pmSleepReason)) + ")"); } MetricsLogger.histogram(mContext, "screen_timeout", mLockScreenTimeout / 1000); - mDeviceGoingToSleep = false; mRequestedOrSleepingDefaultDisplay = false; mDefaultDisplayPolicy.setAwake(false); @@ -4850,26 +4878,18 @@ public class PhoneWindowManager implements WindowManagerPolicy { // Called on the PowerManager's Notifier thread. @Override - public void onPowerGroupWakefulnessChanged(int groupId, int wakefulness, - @PowerManager.GoToSleepReason int pmSleepReason, int globalWakefulness) { - if (wakefulness != globalWakefulness - && wakefulness != PowerManagerInternal.WAKEFULNESS_AWAKE - && groupId == Display.DEFAULT_DISPLAY_GROUP - && mKeyguardDelegate != null) { - mKeyguardDelegate.doKeyguardTimeout(null); - } - } - - // Called on the PowerManager's Notifier thread. - @Override - public void startedWakingUp(@PowerManager.WakeReason int pmWakeReason) { - EventLogTags.writeScreenToggled(1); + public void startedWakingUp(int displayGroupId, @WakeReason int pmWakeReason) { if (DEBUG_WAKEUP) { - Slog.i(TAG, "Started waking up... (why=" + Slog.i(TAG, "Started waking up... (groupId=" + displayGroupId + " why=" + WindowManagerPolicyConstants.onReasonToString( - WindowManagerPolicyConstants.translateWakeReasonToOnReason( - pmWakeReason)) + ")"); + WindowManagerPolicyConstants.translateWakeReasonToOnReason( + pmWakeReason)) + ")"); + } + if (displayGroupId != Display.DEFAULT_DISPLAY_GROUP) { + return; } + EventLogTags.writeScreenToggled(1); + mDefaultDisplayPolicy.setAwake(true); @@ -4892,13 +4912,16 @@ public class PhoneWindowManager implements WindowManagerPolicy { // Called on the PowerManager's Notifier thread. @Override - public void finishedWakingUp(@PowerManager.WakeReason int pmWakeReason) { + public void finishedWakingUp(int displayGroupId, @WakeReason int pmWakeReason) { if (DEBUG_WAKEUP) { - Slog.i(TAG, "Finished waking up... (why=" + Slog.i(TAG, "Finished waking up... (groupId=" + displayGroupId + " why=" + WindowManagerPolicyConstants.onReasonToString( WindowManagerPolicyConstants.translateWakeReasonToOnReason( pmWakeReason)) + ")"); } + if (displayGroupId != Display.DEFAULT_DISPLAY_GROUP) { + return; + } if (mKeyguardDelegate != null) { mKeyguardDelegate.onFinishedWakingUp(); @@ -5378,8 +5401,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { } } mSideFpsEventHandler.onFingerprintSensorReady(); - startedWakingUp(PowerManager.WAKE_REASON_UNKNOWN); - finishedWakingUp(PowerManager.WAKE_REASON_UNKNOWN); + startedWakingUp(Display.DEFAULT_DISPLAY_GROUP, PowerManager.WAKE_REASON_UNKNOWN); + finishedWakingUp(Display.DEFAULT_DISPLAY_GROUP, PowerManager.WAKE_REASON_UNKNOWN); int defaultDisplayState = mDisplayManager.getDisplay(DEFAULT_DISPLAY).getState(); boolean defaultDisplayOn = defaultDisplayState == Display.STATE_ON; diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java index 5d558e9c1e2f..909d0195e0be 100644 --- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java +++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java @@ -67,10 +67,12 @@ import static java.lang.annotation.RetentionPolicy.SOURCE; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; +import android.companion.virtual.VirtualDevice; import android.content.ComponentName; import android.content.Context; import android.content.res.Configuration; import android.graphics.Rect; +import android.hardware.display.VirtualDisplay; import android.os.Bundle; import android.os.IBinder; import android.os.PowerManager; @@ -762,50 +764,84 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants { void setAllowLockscreenWhenOn(int displayId, boolean allow); /** + * Called when the global wakefulness is becoming awake. + * + * @param reason One of PowerManager.WAKE_REASON_*, detailing the reason for the change. + */ + void startedWakingUpGlobal(@PowerManager.WakeReason int reason); + + /** + * Called when the global wakefulness has finished becoming awake. + * + * @param reason One of PowerManager.WAKE_REASON_*, detailing the reason for the change. + */ + void finishedWakingUpGlobal(@PowerManager.WakeReason int reason); + + /** + * Called when the global wakefulness has started going to sleep. + * + * @param reason One of PowerManager.WAKE_REASON_*, detailing the reason for the change. + */ + void startedGoingToSleepGlobal(@PowerManager.GoToSleepReason int reason); + + /** + * Called when the global wakefulness has finished going to sleep. + * + * @param reason One of PowerManager.WAKE_REASON_*, detailing the reason for the change. + */ + void finishedGoingToSleepGlobal(@PowerManager.GoToSleepReason int reason); + + /** * Called when the device has started waking up. * - * @param pmWakeReason One of PowerManager.WAKE_REASON_*, detailing the specific reason we're - * waking up, such as WAKE_REASON_POWER_BUTTON or WAKE_REASON_GESTURE. + * @param displayGroupId The id of the display group that has started waking up. This will often + * be {@link Display#DEFAULT_DISPLAY_GROUP}, but it is possible for other + * display groups to exist, for example when there is a + * {@link VirtualDevice} with one or more {@link VirtualDisplay}s. + * @param pmWakeReason One of PowerManager.WAKE_REASON_*, detailing the specific reason this + * display group is waking up, such as WAKE_REASON_POWER_BUTTON or + * WAKE_REASON_GESTURE. */ - void startedWakingUp(@PowerManager.WakeReason int pmWakeReason); + void startedWakingUp(int displayGroupId, @PowerManager.WakeReason int pmWakeReason); /** * Called when the device has finished waking up. * - * @param pmWakeReason One of PowerManager.WAKE_REASON_*, detailing the specific reason we're - * waking up, such as WAKE_REASON_POWER_BUTTON or WAKE_REASON_GESTURE. + * @param displayGroupId The id of the display group that has finished waking. This will often + * be {@link Display#DEFAULT_DISPLAY_GROUP}, but it is possible for other + * display groups to exist, for example when there is a + * {@link VirtualDevice} with one or more {@link VirtualDisplay}s. + * @param pmWakeReason One of PowerManager.WAKE_REASON_*, detailing the specific reason this + * display group is waking up, such as WAKE_REASON_POWER_BUTTON or + * WAKE_REASON_GESTURE. */ - void finishedWakingUp(@PowerManager.WakeReason int pmWakeReason); + void finishedWakingUp(int displayGroupId, @PowerManager.WakeReason int pmWakeReason); /** * Called when the device has started going to sleep. * + * @param displayGroupId The id of the display group that has started going to sleep. This + * will often be {@link Display#DEFAULT_DISPLAY_GROUP}, but it is + * possible for other display groups to exist, for example when there is a + * {@link VirtualDevice} with one or more {@link VirtualDisplay}s. * @param pmSleepReason One of PowerManager.GO_TO_SLEEP_REASON_*, detailing the specific reason - * we're going to sleep, such as GO_TO_SLEEP_REASON_POWER_BUTTON or GO_TO_SLEEP_REASON_TIMEOUT. + * this display group is going to sleep, such as + * GO_TO_SLEEP_REASON_POWER_BUTTON or GO_TO_SLEEP_REASON_TIMEOUT. */ - public void startedGoingToSleep(@PowerManager.GoToSleepReason int pmSleepReason); + void startedGoingToSleep(int displayGroupId, @PowerManager.GoToSleepReason int pmSleepReason); /** * Called when the device has finished going to sleep. * + * @param displayGroupId The id of the display group that has finished going to sleep. This + * will often be {@link Display#DEFAULT_DISPLAY_GROUP}, but it is + * possible for other display groups to exist, for example when there is a + * {@link VirtualDevice} with one or more {@link VirtualDisplay}s. * @param pmSleepReason One of PowerManager.GO_TO_SLEEP_REASON_*, detailing the specific reason - * we're going to sleep, such as GO_TO_SLEEP_REASON_POWER_BUTTON or GO_TO_SLEEP_REASON_TIMEOUT. + * we're going to sleep, such as GO_TO_SLEEP_REASON_POWER_BUTTON or + * GO_TO_SLEEP_REASON_TIMEOUT. */ - public void finishedGoingToSleep(@PowerManager.GoToSleepReason int pmSleepReason); - - /** - * Called when a particular PowerGroup has changed wakefulness. - * - * @param groupId The id of the PowerGroup. - * @param wakefulness One of PowerManagerInternal.WAKEFULNESS_* indicating the wake state for - * the group - * @param pmSleepReason One of PowerManager.GO_TO_SLEEP_REASON_*, detailing the reason this - * group is going to sleep. - * @param globalWakefulness The global wakefulness, which may or may not match that of this - * group. One of PowerManagerInternal.WAKEFULNESS_* - */ - void onPowerGroupWakefulnessChanged(int groupId, int wakefulness, - @PowerManager.GoToSleepReason int pmSleepReason, int globalWakefulness); + void finishedGoingToSleep(int displayGroupId, @PowerManager.GoToSleepReason int pmSleepReason); /** * Called when the display is about to turn on to show content. diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java index d0ed9bfbb285..9bc0ee224ce0 100644 --- a/services/core/java/com/android/server/power/Notifier.java +++ b/services/core/java/com/android/server/power/Notifier.java @@ -51,6 +51,7 @@ import android.provider.Settings; import android.telephony.TelephonyManager; import android.util.EventLog; import android.util.Slog; +import android.util.SparseArray; import android.view.WindowManagerPolicyConstants; import com.android.internal.annotations.VisibleForTesting; @@ -87,7 +88,7 @@ import java.util.concurrent.atomic.AtomicBoolean; * tell the system when we go to sleep so that it can lock the keyguard if needed. * </p> */ -@VisibleForTesting +@VisibleForTesting(visibility = VisibleForTesting.Visibility.PROTECTED) public class Notifier { private static final String TAG = "PowerManagerNotifier"; @@ -150,14 +151,21 @@ public class Notifier { // begins charging wirelessly private final boolean mShowWirelessChargingAnimationConfig; - // The current interactive state. This is set as soon as an interactive state + // Encapsulates interactivity information about a particular display group. + private static class Interactivity { + public boolean isInteractive = true; + public int changeReason; + public long changeStartTime; // In SystemClock.uptimeMillis() + public boolean isChanging; + } + + private final SparseArray<Interactivity> mInteractivityByGroupId = new SparseArray<>(); + + // The current global interactive state. This is set as soon as an interactive state // transition begins so as to capture the reason that it happened. At some point // this state will propagate to the pending state then eventually to the // broadcasted state over the course of reporting the transition asynchronously. - private boolean mInteractive = true; - private int mInteractiveChangeReason; - private long mInteractiveChangeStartTime; // In SystemClock.uptimeMillis() - private boolean mInteractiveChanging; + private Interactivity mGlobalInteractivity = new Interactivity(); // The pending interactive state that we will eventually want to broadcast. // This is designed so that we can collapse redundant sequences of awake/sleep @@ -438,7 +446,8 @@ public class Notifier { * which case it will assume that the state did not fully converge before the * next transition began and will recover accordingly. */ - public void onWakefulnessChangeStarted(final int wakefulness, int reason, long eventTime) { + public void onGlobalWakefulnessChangeStarted(final int wakefulness, int reason, + long eventTime) { final boolean interactive = PowerManagerInternal.isInteractive(wakefulness); if (DEBUG) { Slog.d(TAG, "onWakefulnessChangeStarted: wakefulness=" + wakefulness @@ -456,10 +465,10 @@ public class Notifier { // Handle any early interactive state changes. // Finish pending incomplete ones from a previous cycle. - if (mInteractive != interactive) { + if (mGlobalInteractivity.isInteractive != interactive) { // Finish up late behaviors if needed. - if (mInteractiveChanging) { - handleLateInteractiveChange(); + if (mGlobalInteractivity.isChanging) { + handleLateGlobalInteractiveChange(); } // Start input as soon as we start waking up or going to sleep. @@ -475,11 +484,11 @@ public class Notifier { FrameworkStatsLog.INTERACTIVE_STATE_CHANGED__STATE__OFF); // Handle early behaviors. - mInteractive = interactive; - mInteractiveChangeReason = reason; - mInteractiveChangeStartTime = eventTime; - mInteractiveChanging = true; - handleEarlyInteractiveChange(); + mGlobalInteractivity.isInteractive = interactive; + mGlobalInteractivity.isChanging = true; + mGlobalInteractivity.changeReason = reason; + mGlobalInteractivity.changeStartTime = eventTime; + handleEarlyGlobalInteractiveChange(); } } @@ -490,10 +499,34 @@ public class Notifier { if (DEBUG) { Slog.d(TAG, "onWakefulnessChangeFinished"); } + for (int i = 0; i < mInteractivityByGroupId.size(); i++) { + int groupId = mInteractivityByGroupId.keyAt(i); + Interactivity interactivity = mInteractivityByGroupId.valueAt(i); + if (interactivity.isChanging) { + interactivity.isChanging = false; + handleLateInteractiveChange(groupId); + } + } + if (mGlobalInteractivity.isChanging) { + mGlobalInteractivity.isChanging = false; + handleLateGlobalInteractiveChange(); + } + } + - if (mInteractiveChanging) { - mInteractiveChanging = false; - handleLateInteractiveChange(); + private void handleEarlyInteractiveChange(int groupId) { + synchronized (mLock) { + Interactivity interactivity = mInteractivityByGroupId.get(groupId); + if (interactivity == null) { + Slog.e(TAG, "no Interactivity entry for groupId:" + groupId); + return; + } + final int changeReason = interactivity.changeReason; + if (interactivity.isInteractive) { + mHandler.post(() -> mPolicy.startedWakingUp(groupId, changeReason)); + } else { + mHandler.post(() -> mPolicy.startedGoingToSleep(groupId, changeReason)); + } } } @@ -501,13 +534,13 @@ public class Notifier { * Handle early interactive state changes such as getting applications or the lock * screen running and ready for the user to see (such as when turning on the screen). */ - private void handleEarlyInteractiveChange() { + private void handleEarlyGlobalInteractiveChange() { synchronized (mLock) { - if (mInteractive) { + if (mGlobalInteractivity.isInteractive) { // Waking up... mHandler.post(() -> { - mPolicy.startedWakingUp(mInteractiveChangeReason); mDisplayManagerInternal.onEarlyInteractivityChange(true /*isInteractive*/); + mPolicy.startedWakingUpGlobal(mGlobalInteractivity.changeReason); }); // Send interactive broadcast. @@ -516,37 +549,36 @@ public class Notifier { updatePendingBroadcastLocked(); } else { // Going to sleep... - // Tell the policy that we started going to sleep. mHandler.post(() -> { - mPolicy.startedGoingToSleep(mInteractiveChangeReason); mDisplayManagerInternal.onEarlyInteractivityChange(false /*isInteractive*/); + mPolicy.startedGoingToSleepGlobal(mGlobalInteractivity.changeReason); }); } } } /** - * Handle late interactive state changes once they are finished so that the system can - * finish pending transitions (such as turning the screen off) before causing - * applications to change state visibly. + * Handle late global interactive state changes. Also see + * {@link #handleLateInteractiveChange(int)}. */ - private void handleLateInteractiveChange() { + private void handleLateGlobalInteractiveChange() { synchronized (mLock) { final int interactiveChangeLatency = - (int) (SystemClock.uptimeMillis() - mInteractiveChangeStartTime); - if (mInteractive) { + (int) (SystemClock.uptimeMillis() - mGlobalInteractivity.changeStartTime); + if (mGlobalInteractivity.isInteractive) { // Finished waking up... mHandler.post(() -> { LogMaker log = new LogMaker(MetricsEvent.SCREEN); log.setType(MetricsEvent.TYPE_OPEN); log.setSubtype(WindowManagerPolicyConstants.translateWakeReasonToOnReason( - mInteractiveChangeReason)); + mGlobalInteractivity.changeReason)); log.setLatency(interactiveChangeLatency); - log.addTaggedData( - MetricsEvent.FIELD_SCREEN_WAKE_REASON, mInteractiveChangeReason); + log.addTaggedData(MetricsEvent.FIELD_SCREEN_WAKE_REASON, + mGlobalInteractivity.changeReason); MetricsLogger.action(log); EventLogTags.writePowerScreenState(1, 0, 0, 0, interactiveChangeLatency); - mPolicy.finishedWakingUp(mInteractiveChangeReason); + + mPolicy.finishedWakingUpGlobal(mGlobalInteractivity.changeReason); }); } else { // Finished going to sleep... @@ -563,18 +595,19 @@ public class Notifier { // Tell the policy we finished going to sleep. final int offReason = WindowManagerPolicyConstants.translateSleepReasonToOffReason( - mInteractiveChangeReason); + mGlobalInteractivity.changeReason); mHandler.post(() -> { LogMaker log = new LogMaker(MetricsEvent.SCREEN); log.setType(MetricsEvent.TYPE_CLOSE); log.setSubtype(offReason); log.setLatency(interactiveChangeLatency); - log.addTaggedData( - MetricsEvent.FIELD_SCREEN_SLEEP_REASON, mInteractiveChangeReason); + log.addTaggedData(MetricsEvent.FIELD_SCREEN_SLEEP_REASON, + mGlobalInteractivity.changeReason); MetricsLogger.action(log); EventLogTags.writePowerScreenState( 0, offReason, 0, 0, interactiveChangeLatency); - mPolicy.finishedGoingToSleep(mInteractiveChangeReason); + + mPolicy.finishedGoingToSleepGlobal(mGlobalInteractivity.changeReason); }); // Send non-interactive broadcast. @@ -586,12 +619,62 @@ public class Notifier { } /** + * Handle late interactive state changes once they are finished so that the system can + * finish pending transitions (such as turning the screen off) before causing + * applications to change state visibly. + */ + private void handleLateInteractiveChange(int groupId) { + synchronized (mLock) { + Interactivity interactivity = mInteractivityByGroupId.get(groupId); + if (interactivity == null) { + Slog.e(TAG, "no Interactivity entry for groupId:" + groupId); + return; + } + final int changeReason = interactivity.changeReason; + if (interactivity.isInteractive) { + mHandler.post(() -> mPolicy.finishedWakingUp(groupId, changeReason)); + } else { + mHandler.post(() -> mPolicy.finishedGoingToSleep(groupId, changeReason)); + } + } + } + + /** * Called when an individual PowerGroup changes wakefulness. */ - public void onPowerGroupWakefulnessChanged(int groupId, int groupWakefulness, int changeReason, - int globalWakefulness) { - mHandler.post(() -> mPolicy.onPowerGroupWakefulnessChanged(groupId, groupWakefulness, - changeReason, globalWakefulness)); + public void onGroupWakefulnessChangeStarted(int groupId, int wakefulness, int changeReason, + long eventTime) { + final boolean isInteractive = PowerManagerInternal.isInteractive(wakefulness); + + boolean isNewGroup = false; + Interactivity interactivity = mInteractivityByGroupId.get(groupId); + if (interactivity == null) { + isNewGroup = true; + interactivity = new Interactivity(); + mInteractivityByGroupId.put(groupId, interactivity); + } + if (isNewGroup || interactivity.isInteractive != isInteractive) { + // Finish up late behaviors if needed. + if (interactivity.isChanging) { + handleLateInteractiveChange(groupId); + } + + // Handle early behaviors. + interactivity.isInteractive = isInteractive; + interactivity.changeReason = changeReason; + interactivity.changeStartTime = eventTime; + interactivity.isChanging = true; + handleEarlyInteractiveChange(groupId); + } + } + + /** + * Called when a PowerGroup has been removed. + * + * @param groupId which group was removed + */ + public void onGroupRemoved(int groupId) { + mInteractivityByGroupId.remove(groupId); } /** diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index e392c24026a7..9ff98be6f5cd 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -686,6 +686,8 @@ public final class PowerManagerService extends SystemService @Override public void onWakefulnessChangedLocked(int groupId, int wakefulness, long eventTime, int reason, int uid, int opUid, String opPackageName, String details) { + mWakefulnessChanging = true; + mDirty |= DIRTY_WAKEFULNESS; if (wakefulness == WAKEFULNESS_AWAKE) { // Kick user activity to prevent newly awake group from timing out instantly. // The dream may end without user activity if the dream app crashes / is updated, @@ -696,9 +698,8 @@ public final class PowerManagerService extends SystemService PowerManager.USER_ACTIVITY_EVENT_OTHER, flags, uid); } mDirty |= DIRTY_DISPLAY_GROUP_WAKEFULNESS; + mNotifier.onGroupWakefulnessChangeStarted(groupId, wakefulness, reason, eventTime); updateGlobalWakefulnessLocked(eventTime, reason, uid, opUid, opPackageName, details); - mNotifier.onPowerGroupWakefulnessChanged(groupId, wakefulness, reason, - getGlobalWakefulnessLocked()); updatePowerStateLocked(); } } @@ -2152,7 +2153,7 @@ public final class PowerManagerService extends SystemService mDozeStartInProgress &= (newWakefulness == WAKEFULNESS_DOZING); if (mNotifier != null) { - mNotifier.onWakefulnessChangeStarted(newWakefulness, reason, eventTime); + mNotifier.onGlobalWakefulnessChangeStarted(newWakefulness, reason, eventTime); } mAttentionDetector.onWakefulnessChangeStarted(newWakefulness); @@ -2163,15 +2164,6 @@ public final class PowerManagerService extends SystemService if (sQuiescent) { mDirty |= DIRTY_QUIESCENT; } - PowerGroup defaultGroup = mPowerGroups.get(Display.DEFAULT_DISPLAY_GROUP); - if (defaultGroup.getWakefulnessLocked() == WAKEFULNESS_DOZING) { - // Workaround for b/187231320 where the AOD can get stuck in a "half on / - // half off" state when a non-default-group VirtualDisplay causes the global - // wakefulness to change to awake, even though the default display is - // dozing. We set sandman summoned to restart dreaming to get it unstuck. - // TODO(b/255688811) - fix this so that AOD never gets interrupted at all. - defaultGroup.setSandmanSummonedLocked(true); - } break; case WAKEFULNESS_ASLEEP: @@ -2248,6 +2240,8 @@ public final class PowerManagerService extends SystemService @GuardedBy("mLock") void onPowerGroupEventLocked(int event, PowerGroup powerGroup) { + mWakefulnessChanging = true; + mDirty |= DIRTY_WAKEFULNESS; final int groupId = powerGroup.getGroupId(); if (event == DisplayGroupPowerChangeListener.DISPLAY_GROUP_REMOVED) { mPowerGroups.delete(groupId); @@ -2260,6 +2254,11 @@ public final class PowerManagerService extends SystemService // Kick user activity to prevent newly added group from timing out instantly. userActivityNoUpdateLocked(powerGroup, mClock.uptimeMillis(), PowerManager.USER_ACTIVITY_EVENT_OTHER, /* flags= */ 0, Process.SYSTEM_UID); + mNotifier.onGroupWakefulnessChangeStarted(groupId, + powerGroup.getWakefulnessLocked(), WAKE_REASON_DISPLAY_GROUP_ADDED, + mClock.uptimeMillis()); + } else if (event == DisplayGroupPowerChangeListener.DISPLAY_GROUP_REMOVED) { + mNotifier.onGroupRemoved(groupId); } if (oldWakefulness != newWakefulness) { diff --git a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java index 21a11bc0e49e..52bf244e99fb 100644 --- a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java @@ -40,6 +40,7 @@ import static org.mockito.ArgumentMatchers.isA; import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.ArgumentMatchers.same; import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.atMost; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.never; import static org.mockito.Mockito.spy; @@ -1611,7 +1612,8 @@ public class PowerManagerServiceTest { startSystem(); assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); - verify(mNotifierMock, never()).onWakefulnessChangeStarted(anyInt(), anyInt(), anyLong()); + verify(mNotifierMock, never()).onGlobalWakefulnessChangeStarted(anyInt(), anyInt(), + anyLong()); } @Test @@ -1630,7 +1632,7 @@ public class PowerManagerServiceTest { startSystem(); assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP); - verify(mNotifierMock).onWakefulnessChangeStarted(eq(WAKEFULNESS_ASLEEP), anyInt(), + verify(mNotifierMock).onGlobalWakefulnessChangeStarted(eq(WAKEFULNESS_ASLEEP), anyInt(), anyLong()); } @@ -2112,7 +2114,7 @@ public class PowerManagerServiceTest { } @Test - public void testMultiDisplay_defaultDozing_addNewDisplayDefaultGoesBackToDoze() { + public void testMultiDisplay_addNewDisplay_becomeGloballyAwakeButDefaultRemainsDozing() { final int nonDefaultDisplayGroupId = Display.DEFAULT_DISPLAY_GROUP + 1; final int nonDefaultDisplay = Display.DEFAULT_DISPLAY + 1; final AtomicReference<DisplayManagerInternal.DisplayGroupListener> listener = @@ -2142,6 +2144,7 @@ public class PowerManagerServiceTest { assertThat(mService.getWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP)).isEqualTo( WAKEFULNESS_DOZING); assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_DOZING); + verify(mDreamManagerInternalMock).stopDream(anyBoolean(), anyString()); verify(mDreamManagerInternalMock).startDream(eq(true), anyString()); listener.get().onDisplayGroupAdded(nonDefaultDisplayGroupId); @@ -2152,7 +2155,10 @@ public class PowerManagerServiceTest { WAKEFULNESS_AWAKE); assertThat(mService.getWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP)).isEqualTo( WAKEFULNESS_DOZING); - verify(mDreamManagerInternalMock, times(2)).startDream(eq(true), anyString()); + + // Make sure there were no additional calls to stopDream or startDream + verify(mDreamManagerInternalMock, atMost(1)).stopDream(anyBoolean(), anyString()); + verify(mDreamManagerInternalMock, atMost(1)).startDream(eq(true), anyString()); } @Test @@ -2169,7 +2175,7 @@ public class PowerManagerServiceTest { } @Test - public void testMultiDisplay_onlyOneDisplaySleeps_onWakefulnessChangedEventFires() { + public void testMultiDisplay_onlyOneDisplaySleeps_onWakefulnessChangedEventsFire() { createService(); startSystem(); assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); @@ -2177,12 +2183,14 @@ public class PowerManagerServiceTest { assertThat(mService.getWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP)).isEqualTo( WAKEFULNESS_ASLEEP); - verify(mNotifierMock).onPowerGroupWakefulnessChanged(eq(Display.DEFAULT_DISPLAY_GROUP), - eq(WAKEFULNESS_ASLEEP), anyInt(), eq(WAKEFULNESS_ASLEEP)); + verify(mNotifierMock).onGroupWakefulnessChangeStarted(eq(Display.DEFAULT_DISPLAY_GROUP), + eq(WAKEFULNESS_ASLEEP), eq(PowerManager.GO_TO_SLEEP_REASON_APPLICATION), anyLong()); + verify(mNotifierMock).onGlobalWakefulnessChangeStarted(eq(WAKEFULNESS_ASLEEP), + eq(PowerManager.GO_TO_SLEEP_REASON_APPLICATION), anyLong()); } @Test - public void testMultiDisplay_bothDisplaysSleep_onWakefulnessChangedEventFiresCorrectly() { + public void testMultiDisplay_bothDisplaysSleep_onWakefulnessChangedEventsFireCorrectly() { final int nonDefaultDisplayGroupId = Display.DEFAULT_DISPLAY_GROUP + 1; final int nonDefaultDisplay = Display.DEFAULT_DISPLAY + 1; final AtomicReference<DisplayManagerInternal.DisplayGroupListener> listener = @@ -2201,10 +2209,10 @@ public class PowerManagerServiceTest { assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); listener.get().onDisplayGroupAdded(nonDefaultDisplayGroupId); - mService.setWakefulnessLocked(nonDefaultDisplayGroupId, WAKEFULNESS_ASLEEP, 0, 0, 0, 0, - null, null); - mService.setWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP, WAKEFULNESS_ASLEEP, 0, 0, 0, 0, - null, null); + mService.setWakefulnessLocked(nonDefaultDisplayGroupId, WAKEFULNESS_ASLEEP, 0, 0, + PowerManager.GO_TO_SLEEP_REASON_APPLICATION, 0, null, null); + mService.setWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP, WAKEFULNESS_ASLEEP, 0, 0, + PowerManager.GO_TO_SLEEP_REASON_APPLICATION, 0, null, null); assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP); assertThat(mService.getWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP)).isEqualTo( @@ -2212,14 +2220,16 @@ public class PowerManagerServiceTest { assertThat(mService.getWakefulnessLocked(nonDefaultDisplayGroupId)).isEqualTo( WAKEFULNESS_ASLEEP); - verify(mNotifierMock).onPowerGroupWakefulnessChanged(eq(nonDefaultDisplayGroupId), - eq(WAKEFULNESS_ASLEEP), anyInt(), eq(WAKEFULNESS_AWAKE)); - verify(mNotifierMock).onPowerGroupWakefulnessChanged(eq(Display.DEFAULT_DISPLAY_GROUP), - eq(WAKEFULNESS_ASLEEP), anyInt(), eq(WAKEFULNESS_ASLEEP)); + verify(mNotifierMock).onGroupWakefulnessChangeStarted(eq(nonDefaultDisplayGroupId), + eq(WAKEFULNESS_ASLEEP), eq(PowerManager.GO_TO_SLEEP_REASON_APPLICATION), anyLong()); + verify(mNotifierMock).onGroupWakefulnessChangeStarted(eq(Display.DEFAULT_DISPLAY_GROUP), + eq(WAKEFULNESS_ASLEEP), eq(PowerManager.GO_TO_SLEEP_REASON_APPLICATION), anyLong()); + verify(mNotifierMock).onGlobalWakefulnessChangeStarted(eq(WAKEFULNESS_ASLEEP), + eq(PowerManager.GO_TO_SLEEP_REASON_APPLICATION), anyLong()); } @Test - public void testMultiDisplay_separateWakeStates_onWakefulnessChangedEventFiresCorrectly() { + public void testMultiDisplay_separateWakeStates_onWakefulnessChangedEventsFireCorrectly() { final int nonDefaultDisplayGroupId = Display.DEFAULT_DISPLAY_GROUP + 1; final int nonDefaultDisplay = Display.DEFAULT_DISPLAY + 1; final AtomicReference<DisplayManagerInternal.DisplayGroupListener> listener = @@ -2255,10 +2265,53 @@ public class PowerManagerServiceTest { WAKEFULNESS_ASLEEP); assertThat(mService.getWakefulnessLocked(nonDefaultDisplayGroupId)).isEqualTo( WAKEFULNESS_AWAKE); - verify(mNotifierMock).onPowerGroupWakefulnessChanged(eq(Display.DEFAULT_DISPLAY_GROUP), - eq(WAKEFULNESS_ASLEEP), anyInt(), eq(WAKEFULNESS_AWAKE)); - verify(mNotifierMock, never()).onPowerGroupWakefulnessChanged( - eq(nonDefaultDisplayGroupId), anyInt(), anyInt(), anyInt()); + verify(mNotifierMock).onGroupWakefulnessChangeStarted(eq(nonDefaultDisplayGroupId), + eq(WAKEFULNESS_AWAKE), eq(PowerManager.WAKE_REASON_DISPLAY_GROUP_ADDED), anyLong()); + verify(mNotifierMock).onGroupWakefulnessChangeStarted(eq(Display.DEFAULT_DISPLAY_GROUP), + eq(WAKEFULNESS_ASLEEP), eq(PowerManager.GO_TO_SLEEP_REASON_APPLICATION), anyLong()); + verify(mNotifierMock, never()).onGlobalWakefulnessChangeStarted(eq(WAKEFULNESS_ASLEEP), + anyInt(), anyLong()); + } + + @Test + public void testMultiDisplay_oneDisplayGroupChanges_globalDoesNotChange() { + final int nonDefaultDisplayGroupId = Display.DEFAULT_DISPLAY_GROUP + 1; + final int nonDefaultDisplay = Display.DEFAULT_DISPLAY + 1; + final AtomicReference<DisplayManagerInternal.DisplayGroupListener> listener = + new AtomicReference<>(); + doAnswer((Answer<Void>) invocation -> { + listener.set(invocation.getArgument(0)); + return null; + }).when(mDisplayManagerInternalMock).registerDisplayGroupListener(any()); + final DisplayInfo info = new DisplayInfo(); + info.displayGroupId = nonDefaultDisplayGroupId; + when(mDisplayManagerInternalMock.getDisplayInfo(nonDefaultDisplay)).thenReturn(info); + + createService(); + startSystem(); + + listener.get().onDisplayGroupAdded(nonDefaultDisplayGroupId); + + assertThat(mService.getWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP)).isEqualTo( + WAKEFULNESS_AWAKE); + assertThat(mService.getWakefulnessLocked(nonDefaultDisplayGroupId)).isEqualTo( + WAKEFULNESS_AWAKE); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); + + long eventTime = mClock.now(); + mService.setWakefulnessLocked(nonDefaultDisplayGroupId, WAKEFULNESS_ASLEEP, eventTime, 0, + PowerManager.GO_TO_SLEEP_REASON_APPLICATION, 0, null, null); + + assertThat(mService.getWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP)).isEqualTo( + WAKEFULNESS_AWAKE); + assertThat(mService.getWakefulnessLocked(nonDefaultDisplayGroupId)).isEqualTo( + WAKEFULNESS_ASLEEP); + assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE); + verify(mNotifierMock, never()).onGlobalWakefulnessChangeStarted(anyInt(), anyInt(), + anyLong()); + verify(mNotifierMock, atMost(1)).onGroupWakefulnessChangeStarted( + eq(nonDefaultDisplayGroupId), eq(WAKEFULNESS_ASLEEP), + eq(PowerManager.GO_TO_SLEEP_REASON_APPLICATION), eq(eventTime)); } @Test diff --git a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java index 2665e197f91f..5636795520e9 100644 --- a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java +++ b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java @@ -233,8 +233,8 @@ class TestPhoneWindowManager { doNothing().when(mPhoneWindowManager).updateSettings(); doNothing().when(mPhoneWindowManager).screenTurningOn(anyInt(), any()); doNothing().when(mPhoneWindowManager).screenTurnedOn(anyInt()); - doNothing().when(mPhoneWindowManager).startedWakingUp(anyInt()); - doNothing().when(mPhoneWindowManager).finishedWakingUp(anyInt()); + doNothing().when(mPhoneWindowManager).startedWakingUp(anyInt(), anyInt()); + doNothing().when(mPhoneWindowManager).finishedWakingUp(anyInt(), anyInt()); mPhoneWindowManager.init(new TestInjector(mContext, mWindowManagerFuncsImpl)); mPhoneWindowManager.systemReady(); diff --git a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java index 2a2641edb637..1f7e3d9546eb 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java +++ b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java @@ -114,24 +114,35 @@ class TestWindowManagerPolicy implements WindowManagerPolicy { } @Override - public void startedWakingUp(@WakeReason int wakeReason) { + public void startedWakingUpGlobal(@WakeReason int reason) { } @Override - public void finishedWakingUp(@WakeReason int wakeReason) { + public void finishedWakingUpGlobal(@WakeReason int reason) { } @Override - public void startedGoingToSleep(@GoToSleepReason int sleepReason) { + public void startedGoingToSleepGlobal(@GoToSleepReason int reason) { } @Override - public void finishedGoingToSleep(@GoToSleepReason int sleepReason) { + public void finishedGoingToSleepGlobal(@GoToSleepReason int reason) { } @Override - public void onPowerGroupWakefulnessChanged(int groupId, int wakefulness, - @GoToSleepReason int pmSleepReason, int globalWakefulness) { + public void startedWakingUp(int displayGroupId, @WakeReason int wakeReason) { + } + + @Override + public void finishedWakingUp(int displayGroupId, @WakeReason int wakeReason) { + } + + @Override + public void startedGoingToSleep(int displayGroupId, @GoToSleepReason int sleepReason) { + } + + @Override + public void finishedGoingToSleep(int displayGroupId, @GoToSleepReason int sleepReason) { } @Override |