Merge "Remove unused instance of setTvMessageEnabled" into udc-dev
diff --git a/core/java/android/service/voice/VoiceInteractionService.java b/core/java/android/service/voice/VoiceInteractionService.java
index 79a4f54..6061a0f 100644
--- a/core/java/android/service/voice/VoiceInteractionService.java
+++ b/core/java/android/service/voice/VoiceInteractionService.java
@@ -913,8 +913,6 @@
      * sandboxed process.
      * @param callback The callback to notify of detection events.
      * @return An instanece of {@link VisualQueryDetector}.
-     * @throws UnsupportedOperationException if only single detector is supported. Multiple detector
-     * is only available for apps targeting {@link Build.VERSION_CODES#TIRAMISU} and above.
      * @throws IllegalStateException when there is an existing {@link VisualQueryDetector}, or when
      * there is a non-trusted hotword detector running.
      *
@@ -935,21 +933,16 @@
             throw new IllegalStateException("Not available until onReady() is called");
         }
         synchronized (mLock) {
-            if (!CompatChanges.isChangeEnabled(MULTIPLE_ACTIVE_HOTWORD_DETECTORS)) {
-                throw new UnsupportedOperationException("VisualQueryDetector is only available if "
-                        + "multiple detectors are allowed");
-            } else {
-                if (mActiveVisualQueryDetector != null) {
+            if (mActiveVisualQueryDetector != null) {
+                throw new IllegalStateException(
+                            "There is already an active VisualQueryDetector. "
+                                    + "It must be destroyed to create a new one.");
+            }
+            for (HotwordDetector detector : mActiveDetectors) {
+                if (!detector.isUsingSandboxedDetectionService()) {
                     throw new IllegalStateException(
-                                "There is already an active VisualQueryDetector. "
-                                        + "It must be destroyed to create a new one.");
-                }
-                for (HotwordDetector detector : mActiveDetectors) {
-                    if (!detector.isUsingSandboxedDetectionService()) {
-                        throw new IllegalStateException(
-                                "It disallows to create trusted and non-trusted detectors "
-                                        + "at the same time.");
-                    }
+                            "It disallows to create trusted and non-trusted detectors "
+                                    + "at the same time.");
                 }
             }
 
diff --git a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/AidlTestUtils.java b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/AidlTestUtils.java
index cce1b2b..6c70192 100644
--- a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/AidlTestUtils.java
+++ b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/AidlTestUtils.java
@@ -80,7 +80,7 @@
                 /* vendorIds= */ null);
     }
 
-    static android.hardware.broadcastradio.ProgramSelector makeHalFmSelector(int freq) {
+    static android.hardware.broadcastradio.ProgramSelector makeHalFmSelector(long freq) {
         ProgramIdentifier halId = makeHalIdentifier(IdentifierType.AMFM_FREQUENCY_KHZ, freq);
         return makeHalSelector(halId, /* secondaryIds= */ new ProgramIdentifier[0]);
     }
diff --git a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/ConversionUtilsResultTest.java b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/ConversionUtilsResultTest.java
index df3ddfd..b54c156 100644
--- a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/ConversionUtilsResultTest.java
+++ b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/ConversionUtilsResultTest.java
@@ -52,6 +52,7 @@
                 {Result.INVALID_STATE, RadioTuner.TUNER_RESULT_INVALID_STATE},
                 {Result.NOT_SUPPORTED, RadioTuner.TUNER_RESULT_NOT_SUPPORTED},
                 {Result.TIMEOUT, RadioTuner.TUNER_RESULT_TIMEOUT},
+                {Result.CANCELED, RadioTuner.TUNER_RESULT_CANCELED},
                 {Result.UNKNOWN_ERROR, RadioTuner.TUNER_RESULT_UNKNOWN_ERROR}
         });
     }
diff --git a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/ConversionUtilsTest.java b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/ConversionUtilsTest.java
index aea0178..2ef923d 100644
--- a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/ConversionUtilsTest.java
+++ b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/ConversionUtilsTest.java
@@ -27,11 +27,13 @@
 import android.hardware.broadcastradio.ProgramInfo;
 import android.hardware.broadcastradio.ProgramListChunk;
 import android.hardware.broadcastradio.Properties;
+import android.hardware.broadcastradio.Result;
 import android.hardware.broadcastradio.VendorKeyValue;
 import android.hardware.radio.Announcement;
 import android.hardware.radio.ProgramList;
 import android.hardware.radio.ProgramSelector;
 import android.hardware.radio.RadioManager;
+import android.os.ServiceSpecificException;
 
 import com.android.dx.mockito.inline.extended.StaticMockitoSessionBuilder;
 import com.android.server.broadcastradio.ExtendedRadioMockitoTestCase;
@@ -153,6 +155,16 @@
     }
 
     @Test
+    public void throwOnError_withCancelException() {
+        ServiceSpecificException halException = new ServiceSpecificException(Result.CANCELED);
+
+        RuntimeException thrown = ConversionUtils.throwOnError(halException, "tune");
+
+        expect.withMessage("Exception thrown for canceling error").that(thrown)
+                .hasMessageThat().contains("tune: CANCELED");
+    }
+
+    @Test
     public void propertiesFromHalProperties_idsMatch() {
         expect.withMessage("Properties id")
                 .that(MODULE_PROPERTIES.getId()).isEqualTo(TEST_ID);
diff --git a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/TunerSessionTest.java b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/TunerSessionTest.java
index f85748c..84aa864 100644
--- a/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/TunerSessionTest.java
+++ b/core/tests/BroadcastRadioTests/src/com/android/server/broadcastradio/aidl/TunerSessionTest.java
@@ -1168,13 +1168,29 @@
         doReturn(USER_ID_2).when(() -> RadioServiceUserController.getCurrentUser());
 
         mHalTunerCallback.onCurrentProgramInfoChanged(AidlTestUtils.makeHalProgramInfo(
-                AidlTestUtils.makeHalFmSelector(/* freq= */ 97300), SIGNAL_QUALITY));
+                AidlTestUtils.makeHalFmSelector(AM_FM_FREQUENCY_LIST[1]), SIGNAL_QUALITY));
 
         verify(mAidlTunerCallbackMocks[0], CALLBACK_TIMEOUT.times(0))
                 .onCurrentProgramInfoChanged(any());
     }
 
     @Test
+    public void onTuneFailed_forTunerCallback() throws Exception {
+        int numSessions = 3;
+        openAidlClients(numSessions);
+        android.hardware.broadcastradio.ProgramSelector halSel = AidlTestUtils.makeHalFmSelector(
+                AM_FM_FREQUENCY_LIST[1]);
+        ProgramSelector sel = AidlTestUtils.makeFmSelector(AM_FM_FREQUENCY_LIST[1]);
+
+        mHalTunerCallback.onTuneFailed(Result.CANCELED, halSel);
+
+        for (int index = 0; index < numSessions; index++) {
+            verify(mAidlTunerCallbackMocks[index], CALLBACK_TIMEOUT)
+                    .onTuneFailed(RadioTuner.TUNER_RESULT_CANCELED, sel);
+        }
+    }
+
+    @Test
     public void onAntennaStateChange_forTunerCallback() throws Exception {
         int numSessions = 3;
         openAidlClients(numSessions);
diff --git a/libs/WindowManager/Shell/res/values/config.xml b/libs/WindowManager/Shell/res/values/config.xml
index 76eb094..a3916b7 100644
--- a/libs/WindowManager/Shell/res/values/config.xml
+++ b/libs/WindowManager/Shell/res/values/config.xml
@@ -125,4 +125,7 @@
 
     <!-- Whether the additional education about reachability is enabled -->
     <bool name="config_letterboxIsReachabilityEducationEnabled">false</bool>
+
+    <!-- Whether DragAndDrop capability is enabled -->
+    <bool name="config_enableShellDragDrop">true</bool>
 </resources>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
index 21f02b1..3eb9fa2 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java
@@ -260,7 +260,7 @@
     /** One handed mode controller to register transition listener. */
     private Optional<OneHandedController> mOneHandedOptional;
     /** Drag and drop controller to register listener for onDragStarted. */
-    private DragAndDropController mDragAndDropController;
+    private Optional<DragAndDropController> mDragAndDropController;
     /** Used to send bubble events to launcher. */
     private Bubbles.BubbleStateListener mBubbleStateListener;
 
@@ -286,7 +286,7 @@
             BubblePositioner positioner,
             DisplayController displayController,
             Optional<OneHandedController> oneHandedOptional,
-            DragAndDropController dragAndDropController,
+            Optional<DragAndDropController> dragAndDropController,
             @ShellMainThread ShellExecutor mainExecutor,
             @ShellMainThread Handler mainHandler,
             @ShellBackgroundThread ShellExecutor bgExecutor,
@@ -469,7 +469,7 @@
                 });
 
         mOneHandedOptional.ifPresent(this::registerOneHandedState);
-        mDragAndDropController.addListener(this::collapseStack);
+        mDragAndDropController.ifPresent(controller -> controller.addListener(this::collapseStack));
 
         // Clear out any persisted bubbles on disk that no longer have a valid user.
         List<UserInfo> users = mUserManager.getAliveUsers();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvWMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvWMShellModule.java
index e9957fd..12d51f5 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvWMShellModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/TvWMShellModule.java
@@ -41,11 +41,11 @@
 import com.android.wm.shell.sysui.ShellInit;
 import com.android.wm.shell.transition.Transitions;
 
-import java.util.Optional;
-
 import dagger.Module;
 import dagger.Provides;
 
+import java.util.Optional;
+
 /**
  * Provides dependencies from {@link com.android.wm.shell}, these dependencies are only
  * accessible from components within the WM subcomponent (can be explicitly exposed to the
@@ -81,7 +81,7 @@
             DisplayController displayController,
             DisplayImeController displayImeController,
             DisplayInsetsController displayInsetsController,
-            DragAndDropController dragAndDropController,
+            Optional<DragAndDropController> dragAndDropController,
             Transitions transitions,
             TransactionPool transactionPool,
             IconProvider iconProvider,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
index 9808c59..36d941b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
@@ -186,15 +186,15 @@
 
     @WMSingleton
     @Provides
-    static DragAndDropController provideDragAndDropController(Context context,
+    static Optional<DragAndDropController> provideDragAndDropController(Context context,
             ShellInit shellInit,
             ShellController shellController,
             DisplayController displayController,
             UiEventLogger uiEventLogger,
             IconProvider iconProvider,
             @ShellMainThread ShellExecutor mainExecutor) {
-        return new DragAndDropController(context, shellInit, shellController, displayController,
-                uiEventLogger, iconProvider, mainExecutor);
+        return Optional.ofNullable(DragAndDropController.create(context, shellInit, shellController,
+                displayController, uiEventLogger, iconProvider, mainExecutor));
     }
 
     @WMSingleton
@@ -796,7 +796,7 @@
             DisplayController displayController,
             DisplayImeController displayImeController,
             DisplayInsetsController displayInsetsController,
-            DragAndDropController dragAndDropController,
+            Optional<DragAndDropController> dragAndDropControllerOptional,
             ShellTaskOrganizer shellTaskOrganizer,
             Optional<BubbleController> bubblesOptional,
             Optional<SplitScreenController> splitScreenOptional,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
index 2f0f56c..f3130d3 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java
@@ -171,7 +171,7 @@
             BubblePositioner positioner,
             DisplayController displayController,
             @DynamicOverride Optional<OneHandedController> oneHandedOptional,
-            DragAndDropController dragAndDropController,
+            Optional<DragAndDropController> dragAndDropController,
             @ShellMainThread ShellExecutor mainExecutor,
             @ShellMainThread Handler mainHandler,
             @ShellBackgroundThread ShellExecutor bgExecutor,
@@ -320,7 +320,7 @@
             DisplayController displayController,
             DisplayImeController displayImeController,
             DisplayInsetsController displayInsetsController,
-            DragAndDropController dragAndDropController,
+            Optional<DragAndDropController> dragAndDropController,
             Transitions transitions,
             TransactionPool transactionPool,
             IconProvider iconProvider,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java
index 4cfaae6..091de3a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java
@@ -94,7 +94,24 @@
         void onDragStarted();
     }
 
-    public DragAndDropController(Context context,
+    /**
+     * Creates {@link DragAndDropController}. Returns {@code null} if the feature is disabled.
+     */
+    public static DragAndDropController create(Context context,
+            ShellInit shellInit,
+            ShellController shellController,
+            DisplayController displayController,
+            UiEventLogger uiEventLogger,
+            IconProvider iconProvider,
+            ShellExecutor mainExecutor) {
+        if (!context.getResources().getBoolean(R.bool.config_enableShellDragDrop)) {
+            return null;
+        }
+        return new DragAndDropController(context, shellInit, shellController, displayController,
+                uiEventLogger, iconProvider, mainExecutor);
+    }
+
+    DragAndDropController(Context context,
             ShellInit shellInit,
             ShellController shellController,
             DisplayController displayController,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
index 6432459..af52350 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
@@ -165,7 +165,7 @@
     private final DisplayController mDisplayController;
     private final DisplayImeController mDisplayImeController;
     private final DisplayInsetsController mDisplayInsetsController;
-    private final DragAndDropController mDragAndDropController;
+    private final Optional<DragAndDropController> mDragAndDropController;
     private final Transitions mTransitions;
     private final TransactionPool mTransactionPool;
     private final IconProvider mIconProvider;
@@ -191,7 +191,7 @@
             DisplayController displayController,
             DisplayImeController displayImeController,
             DisplayInsetsController displayInsetsController,
-            DragAndDropController dragAndDropController,
+            Optional<DragAndDropController> dragAndDropController,
             Transitions transitions,
             TransactionPool transactionPool,
             IconProvider iconProvider,
@@ -253,7 +253,7 @@
         mDisplayController = displayController;
         mDisplayImeController = displayImeController;
         mDisplayInsetsController = displayInsetsController;
-        mDragAndDropController = dragAndDropController;
+        mDragAndDropController = Optional.of(dragAndDropController);
         mTransitions = transitions;
         mTransactionPool = transactionPool;
         mIconProvider = iconProvider;
@@ -289,7 +289,7 @@
             // TODO: Multi-display
             mStageCoordinator = createStageCoordinator();
         }
-        mDragAndDropController.setSplitScreenController(this);
+        mDragAndDropController.ifPresent(controller -> controller.setSplitScreenController(this));
     }
 
     protected StageCoordinator createStageCoordinator() {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvSplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvSplitScreenController.java
index 46d2a5a..27d520d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvSplitScreenController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvSplitScreenController.java
@@ -72,7 +72,7 @@
             DisplayController displayController,
             DisplayImeController displayImeController,
             DisplayInsetsController displayInsetsController,
-            DragAndDropController dragAndDropController,
+            Optional<DragAndDropController> dragAndDropController,
             Transitions transitions,
             TransactionPool transactionPool,
             IconProvider iconProvider,
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index 78994c4..cd2bf13 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -617,10 +617,12 @@
     val APP_PANELS_REMOVE_APPS_ALLOWED =
         unreleasedFlag(2003, "app_panels_remove_apps_allowed", teamfood = true)
 
-    // 2200 - udfps
+    // 2200 - biometrics (udfps, sfps, BiometricPrompt, etc.)
     // TODO(b/259264861): Tracking Bug
     @JvmField val UDFPS_NEW_TOUCH_DETECTION = releasedFlag(2200, "udfps_new_touch_detection")
     @JvmField val UDFPS_ELLIPSE_DETECTION = releasedFlag(2201, "udfps_ellipse_detection")
+    // TODO(b/278622168): Tracking Bug
+    @JvmField val BIOMETRIC_BP_STRONG = unreleasedFlag(2202, "biometric_bp_strong")
 
     // 2300 - stylus
     @JvmField val TRACK_STYLUS_EVER_USED = releasedFlag(2300, "track_stylus_ever_used")
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
index 1510ee8..47a86b1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java
@@ -380,7 +380,7 @@
                 mPositioner,
                 mock(DisplayController.class),
                 mOneHandedOptional,
-                mock(DragAndDropController.class),
+                Optional.of(mock(DragAndDropController.class)),
                 syncExecutor,
                 mock(Handler.class),
                 mTaskViewTransitions,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/TestableBubbleController.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/TestableBubbleController.java
index c3bb771..14c3f3c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/TestableBubbleController.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/TestableBubbleController.java
@@ -69,7 +69,7 @@
             BubblePositioner positioner,
             DisplayController displayController,
             Optional<OneHandedController> oneHandedOptional,
-            DragAndDropController dragAndDropController,
+            Optional<DragAndDropController> dragAndDropController,
             ShellExecutor shellMainExecutor,
             Handler shellMainHandler,
             TaskViewTransitions taskViewTransitions,
diff --git a/services/core/java/com/android/server/am/AppProfiler.java b/services/core/java/com/android/server/am/AppProfiler.java
index f29a2e1..c687184a 100644
--- a/services/core/java/com/android/server/am/AppProfiler.java
+++ b/services/core/java/com/android/server/am/AppProfiler.java
@@ -1199,6 +1199,9 @@
                     .sendToTarget();
         }
 
+        mCachedAppsWatermarkData.updateCachedAppsHighWatermarkIfNecessaryLocked(
+                numCached + numEmpty, now);
+
         if (mService.mConstants.USE_MODERN_TRIM) {
             // Modern trim is not sent based on lowmem state
             // Dispatch UI_HIDDEN to processes that need it
@@ -1316,8 +1319,6 @@
                 profile.setTrimMemoryLevel(0);
             });
         }
-        mCachedAppsWatermarkData.updateCachedAppsHighWatermarkIfNecessaryLocked(
-                numCached + numEmpty, now);
         return allChanged;
     }
 
diff --git a/services/core/java/com/android/server/broadcastradio/aidl/ConversionUtils.java b/services/core/java/com/android/server/broadcastradio/aidl/ConversionUtils.java
index aab815c..adea13f 100644
--- a/services/core/java/com/android/server/broadcastradio/aidl/ConversionUtils.java
+++ b/services/core/java/com/android/server/broadcastradio/aidl/ConversionUtils.java
@@ -102,6 +102,8 @@
                 return new UnsupportedOperationException(action + ": NOT_SUPPORTED");
             case Result.TIMEOUT:
                 return new ParcelableException(new RuntimeException(action + ": TIMEOUT"));
+            case Result.CANCELED:
+                return new IllegalStateException(action + ": CANCELED");
             default:
                 return new ParcelableException(new RuntimeException(
                         action + ": unknown error (" + result + ")"));
@@ -123,6 +125,8 @@
                 return RadioTuner.TUNER_RESULT_NOT_SUPPORTED;
             case Result.TIMEOUT:
                 return RadioTuner.TUNER_RESULT_TIMEOUT;
+            case Result.CANCELED:
+                return RadioTuner.TUNER_RESULT_CANCELED;
             case Result.UNKNOWN_ERROR:
             default:
                 return RadioTuner.TUNER_RESULT_UNKNOWN_ERROR;
diff --git a/services/core/java/com/android/server/infra/ServiceNameBaseResolver.java b/services/core/java/com/android/server/infra/ServiceNameBaseResolver.java
index 76ea05e..66ce5c7 100644
--- a/services/core/java/com/android/server/infra/ServiceNameBaseResolver.java
+++ b/services/core/java/com/android/server/infra/ServiceNameBaseResolver.java
@@ -268,7 +268,7 @@
             }
             if (enabled) {
                 Slog.i(TAG, "disabling default service for user " + userId);
-                mDefaultServicesDisabled.removeAt(userId);
+                mDefaultServicesDisabled.delete(userId);
             } else {
                 Slog.i(TAG, "enabling default service for user " + userId);
                 mDefaultServicesDisabled.put(userId, true);
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 8433c47..79eed64 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 @@
             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 @@
 
         // 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 @@
 
         // 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 @@
         }
     };
 
+    @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 @@
 
     // 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 @@
 
     // 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 @@
 
     // 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 @@
             }
         }
         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 7c3f1aa..887f946 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 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 @@
     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 d0ed9bf..9bc0ee22 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.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 @@
  * 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 @@
     // 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 @@
      * 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 @@
 
         // 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 @@
                             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 @@
         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 @@
      * 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 @@
                 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 @@
 
                 // 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 @@
     }
 
     /**
+     * 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 e392c24..9ff98be 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 @@
         @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 @@
                         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 @@
             mDozeStartInProgress &= (newWakefulness == WAKEFULNESS_DOZING);
 
             if (mNotifier != null) {
-                mNotifier.onWakefulnessChangeStarted(newWakefulness, reason, eventTime);
+                mNotifier.onGlobalWakefulnessChangeStarted(newWakefulness, reason, eventTime);
             }
             mAttentionDetector.onWakefulnessChangeStarted(newWakefulness);
 
@@ -2163,15 +2164,6 @@
                     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 @@
 
     @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 @@
             // 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/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 510e675..a5cdd0b 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -3594,8 +3594,11 @@
                 && !mTransitionController.useShellTransitionsRotation()) {
             if (deltaRotation != Surface.ROTATION_0) {
                 updateSurfaceRotation(t, deltaRotation, null /* positionLeash */);
+                t.setFixedTransformHint(mSurfaceControl,
+                        getWindowConfiguration().getDisplayRotation());
             } else if (deltaRotation != mLastDeltaRotation) {
                 t.setMatrix(mSurfaceControl, 1, 0, 0, 1);
+                t.unsetFixedTransformHint(mSurfaceControl);
             }
         }
         mLastDeltaRotation = deltaRotation;
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index da54b15..4c5efef 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -596,6 +596,7 @@
                 .build();
         t.setPosition(leash, mLastSurfacePosition.x, mLastSurfacePosition.y);
         t.reparent(getSurfaceControl(), leash);
+        t.setFixedTransformHint(leash, getWindowConfiguration().getDisplayRotation());
         mFixedRotationTransformLeash = leash;
         updateSurfaceRotation(t, rotation, mFixedRotationTransformLeash);
         return mFixedRotationTransformLeash;
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index a35f34d..290b647 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -6041,7 +6041,7 @@
     @Override
     public void lockNow(int flags, String callerPackageName, boolean parent) {
         CallerIdentity caller;
-        if (isPolicyEngineForFinanceFlagEnabled()) {
+        if (isPermissionCheckFlagEnabled()) {
             caller = getCallerIdentity(callerPackageName);
         } else {
             caller = getCallerIdentity();
@@ -6053,7 +6053,7 @@
             ActiveAdmin admin;
             // Make sure the caller has any active admin with the right policy or
             // the required permission.
-            if (isPolicyEngineForFinanceFlagEnabled()) {
+            if (isPermissionCheckFlagEnabled()) {
                 admin = enforcePermissionAndGetEnforcingAdmin(
                         /* admin= */ null,
                         /* permission= */ MANAGE_DEVICE_POLICY_LOCK,
@@ -8907,13 +8907,13 @@
         }
 
         CallerIdentity caller;
-        if (isPolicyEngineForFinanceFlagEnabled()) {
+        if (isPermissionCheckFlagEnabled()) {
             caller = getCallerIdentity(who, callerPackageName);
         } else {
             caller = getCallerIdentity(who);
         }
 
-        if (isPolicyEngineForFinanceFlagEnabled()) {
+        if (isPermissionCheckFlagEnabled()) {
             // The effect of this policy is device-wide.
             enforcePermission(SET_TIME, caller.getPackageName(), UserHandle.USER_ALL);
         } else {
@@ -8941,13 +8941,13 @@
             return false;
         }
         CallerIdentity caller;
-        if (isPolicyEngineForFinanceFlagEnabled()) {
+        if (isPermissionCheckFlagEnabled()) {
             caller = getCallerIdentity(who, callerPackageName);
         } else {
             caller = getCallerIdentity(who);
         }
 
-        if (isPolicyEngineForFinanceFlagEnabled()) {
+        if (isPermissionCheckFlagEnabled()) {
             enforceCanQuery(SET_TIME, caller.getPackageName(), UserHandle.USER_ALL);
         } else {
             Objects.requireNonNull(who, "ComponentName is null");
@@ -8976,7 +8976,7 @@
             caller = getCallerIdentity(who);
         }
 
-        if (isPolicyEngineForFinanceFlagEnabled()) {
+        if (isPermissionCheckFlagEnabled()) {
             // The effect of this policy is device-wide.
             EnforcingAdmin enforcingAdmin = enforcePermissionAndGetEnforcingAdmin(
                     who,
@@ -9016,13 +9016,13 @@
         }
 
         CallerIdentity caller;
-        if (isPolicyEngineForFinanceFlagEnabled()) {
+        if (isPermissionCheckFlagEnabled()) {
             caller = getCallerIdentity(who, callerPackageName);
         } else {
             caller = getCallerIdentity(who);
         }
 
-        if (isPolicyEngineForFinanceFlagEnabled()) {
+        if (isPermissionCheckFlagEnabled()) {
             // The effect of this policy is device-wide.
             enforceCanQuery(SET_TIME_ZONE, caller.getPackageName(), UserHandle.USER_ALL);
         } else {
@@ -9325,7 +9325,7 @@
         }
 
         CallerIdentity caller;
-        if (isPolicyEngineForFinanceFlagEnabled()) {
+        if (isPermissionCheckFlagEnabled()) {
             caller = getCallerIdentity(who, callerPackageName);
         } else {
             caller = getCallerIdentity(who);
@@ -9335,7 +9335,7 @@
         final int userHandle = caller.getUserId();
         int affectedUserId = parent ? getProfileParentId(userHandle) : userHandle;
         synchronized (getLockObject()) {
-            if (isPolicyEngineForFinanceFlagEnabled()) {
+            if (isPermissionCheckFlagEnabled()) {
                 // SUPPORT USES_POLICY_DISABLE_KEYGUARD_FEATURES
                 EnforcingAdmin admin = enforcePermissionAndGetEnforcingAdmin(
                         who, MANAGE_DEVICE_POLICY_KEYGUARD, caller.getPackageName(),
@@ -9414,7 +9414,7 @@
 
         synchronized (getLockObject()) {
             if (who != null) {
-                if (isPolicyEngineForFinanceFlagEnabled()) {
+                if (isPermissionCheckFlagEnabled()) {
                     EnforcingAdmin admin = getEnforcingAdminForCaller(
                             who, who.getPackageName());
                     Integer features = mDevicePolicyEngine.getLocalPolicySetByAdmin(
@@ -9428,7 +9428,7 @@
                 }
             }
 
-            if (isPolicyEngineForFinanceFlagEnabled()) {
+            if (isPermissionCheckFlagEnabled()) {
                 Integer features = mDevicePolicyEngine.getResolvedPolicy(
                         PolicyDefinition.KEYGUARD_DISABLED_FEATURES,
                         affectedUserId);
@@ -11625,7 +11625,7 @@
         final CallerIdentity caller = getCallerIdentity(who, callerPackage);
         checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_APPLICATION_RESTRICTIONS);
 
-        if (isPolicyEngineForFinanceFlagEnabled()) {
+        if (isPermissionCheckFlagEnabled()) {
             EnforcingAdmin enforcingAdmin = enforcePermissionAndGetEnforcingAdmin(
                     who,
                     MANAGE_DEVICE_POLICY_APP_RESTRICTIONS,
@@ -13034,7 +13034,7 @@
             String packageName) {
         final CallerIdentity caller = getCallerIdentity(who, callerPackage);
 
-        if (isPolicyEngineForFinanceFlagEnabled()) {
+        if (isPermissionCheckFlagEnabled()) {
             EnforcingAdmin enforcingAdmin = enforceCanQueryAndGetEnforcingAdmin(
                     who,
                     MANAGE_DEVICE_POLICY_APP_RESTRICTIONS,
@@ -13104,7 +13104,7 @@
         final CallerIdentity caller = getCallerIdentity(who, callerPackage);
         ActiveAdmin admin;
 
-        if (isPolicyEngineForFinanceFlagEnabled()) {
+        if (isPermissionCheckFlagEnabled()) {
             EnforcingAdmin enforcingAdmin = enforcePermissionAndGetEnforcingAdmin(
                     who,
                     MANAGE_DEVICE_POLICY_PACKAGE_STATE,
@@ -13201,7 +13201,7 @@
     public boolean isPackageSuspended(ComponentName who, String callerPackage, String packageName) {
         final CallerIdentity caller = getCallerIdentity(who, callerPackage);
 
-        if (isPolicyEngineForFinanceFlagEnabled()) {
+        if (isPermissionCheckFlagEnabled()) {
             enforcePermission(
                     MANAGE_DEVICE_POLICY_PACKAGE_STATE,
                     caller.getPackageName(),
@@ -13807,7 +13807,7 @@
             boolean hidden, boolean parent) {
         CallerIdentity caller = getCallerIdentity(who, callerPackage);
         final int userId = parent ? getProfileParentId(caller.getUserId()) : caller.getUserId();
-        if (isPolicyEngineForFinanceFlagEnabled()) {
+        if (isPermissionCheckFlagEnabled()) {
             // TODO: We need to ensure the delegate with DELEGATION_PACKAGE_ACCESS can do this
             enforcePermission(MANAGE_DEVICE_POLICY_PACKAGE_STATE, caller.getPackageName(), userId);
         } else {
@@ -13826,7 +13826,7 @@
         boolean result;
         synchronized (getLockObject()) {
             if (parent) {
-                if (!isPolicyEngineForFinanceFlagEnabled()) {
+                if (!isPermissionCheckFlagEnabled()) {
                     Preconditions.checkCallAuthorization(
                             isProfileOwnerOfOrganizationOwnedDevice(
                                     caller.getUserId()) && isManagedProfile(caller.getUserId()));
@@ -13843,7 +13843,7 @@
                 Slogf.v(LOG_TAG, "calling pm.setApplicationHiddenSettingAsUser(%s, %b, %d)",
                         packageName, hidden, userId);
             }
-            if (isPolicyEngineForFinanceFlagEnabled()) {
+            if (isPermissionCheckFlagEnabled()) {
                 EnforcingAdmin admin = getEnforcingAdminForCaller(who, callerPackage);
                 mDevicePolicyEngine.setLocalPolicy(
                         PolicyDefinition.APPLICATION_HIDDEN(packageName),
@@ -13882,7 +13882,7 @@
             String packageName, boolean parent) {
         CallerIdentity caller = getCallerIdentity(who, callerPackage);
         int userId = parent ? getProfileParentId(caller.getUserId()) : caller.getUserId();
-        if (isPolicyEngineForFinanceFlagEnabled()) {
+        if (isPermissionCheckFlagEnabled()) {
             // TODO: Also support DELEGATION_PACKAGE_ACCESS
             enforcePermission(MANAGE_DEVICE_POLICY_PACKAGE_STATE, caller.getPackageName(), userId);
         } else {
@@ -13894,7 +13894,7 @@
 
         synchronized (getLockObject()) {
             if (parent) {
-                if (!isPolicyEngineForFinanceFlagEnabled()) {
+                if (!isPermissionCheckFlagEnabled()) {
                     Preconditions.checkCallAuthorization(
                             isProfileOwnerOfOrganizationOwnedDevice(caller.getUserId())
                                     && isManagedProfile(caller.getUserId()));
@@ -14083,13 +14083,13 @@
             return;
         }
         CallerIdentity caller;
-        if (isPolicyEngineForFinanceFlagEnabled()) {
+        if (isPermissionCheckFlagEnabled()) {
             caller = getCallerIdentity(who, callerPackageName);
         } else {
             caller = getCallerIdentity(who);
         }
         synchronized (getLockObject()) {
-            if (isPolicyEngineForFinanceFlagEnabled()) {
+            if (isPermissionCheckFlagEnabled()) {
                 int affectedUser = getAffectedUser(parent);
                 EnforcingAdmin enforcingAdmin = enforcePermissionAndGetEnforcingAdmin(
                         who,
@@ -14152,7 +14152,7 @@
         CallerIdentity caller;
         Preconditions.checkArgumentNonnegative(userId, "Invalid userId");
         final ArraySet<String> resultSet = new ArraySet<>();
-        if (isPolicyEngineForFinanceFlagEnabled()) {
+        if (isPermissionCheckFlagEnabled()) {
             int affectedUser = parent ? getProfileParentId(userId) : userId;
             caller = getCallerIdentity(callerPackageName);
             if (!hasPermission(MANAGE_DEVICE_POLICY_ACCOUNT_MANAGEMENT,
@@ -15519,12 +15519,12 @@
     public boolean setStatusBarDisabled(ComponentName who, String callerPackageName,
             boolean disabled) {
         CallerIdentity caller;
-        if (isPolicyEngineForFinanceFlagEnabled()) {
+        if (isPermissionCheckFlagEnabled()) {
             caller = getCallerIdentity(who, callerPackageName);
         } else {
             caller = getCallerIdentity(who);
         }
-        if (isPolicyEngineForFinanceFlagEnabled()) {
+        if (isPermissionCheckFlagEnabled()) {
             enforcePermission(MANAGE_DEVICE_POLICY_STATUS_BAR, caller.getPackageName(),
                     UserHandle.USER_ALL);
         } else {
@@ -15535,7 +15535,7 @@
 
         int userId = caller.getUserId();
         synchronized (getLockObject()) {
-            if (!isPolicyEngineForFinanceFlagEnabled()) {
+            if (!isPermissionCheckFlagEnabled()) {
                 Preconditions.checkCallAuthorization(isUserAffiliatedWithDeviceLocked(userId),
                         "Admin " + who + " is neither the device owner or affiliated "
                                 + "user's profile owner.");
@@ -15594,7 +15594,7 @@
     @Override
     public boolean isStatusBarDisabled(String callerPackage) {
         final CallerIdentity caller = getCallerIdentity(callerPackage);
-        if (isPolicyEngineForFinanceFlagEnabled()) {
+        if (isPermissionCheckFlagEnabled()) {
             enforceCanQuery(
                     MANAGE_DEVICE_POLICY_STATUS_BAR, caller.getPackageName(), caller.getUserId());
         } else {
@@ -15604,7 +15604,7 @@
 
         int userId = caller.getUserId();
         synchronized (getLockObject()) {
-            if (!isPolicyEngineForFinanceFlagEnabled()) {
+            if (!isPermissionCheckFlagEnabled()) {
                 Preconditions.checkCallAuthorization(isUserAffiliatedWithDeviceLocked(userId),
                         "Admin " + callerPackage
                                 + " is neither the device owner or affiliated user's profile owner.");
@@ -16764,7 +16764,7 @@
             }
         }
         EnforcingAdmin enforcingAdmin;
-        if (isPolicyEngineForFinanceFlagEnabled()) {
+        if (isPermissionCheckFlagEnabled()) {
             enforcingAdmin = enforcePermissionAndGetEnforcingAdmin(
                     admin,
                     MANAGE_DEVICE_POLICY_RUNTIME_PERMISSIONS,
@@ -16935,7 +16935,7 @@
     public int getPermissionGrantState(ComponentName admin, String callerPackage,
             String packageName, String permission) throws RemoteException {
         final CallerIdentity caller = getCallerIdentity(admin, callerPackage);
-        if (isPolicyEngineForFinanceFlagEnabled()) {
+        if (isPermissionCheckFlagEnabled()) {
             enforceCanQuery(MANAGE_DEVICE_POLICY_RUNTIME_PERMISSIONS, caller.getPackageName(),
                     caller.getUserId());
         } else {
@@ -19067,14 +19067,14 @@
             throw new IllegalArgumentException("token must be at least 32-byte long");
         }
         CallerIdentity caller;
-        if (isPolicyEngineForFinanceFlagEnabled()) {
+        if (isPermissionCheckFlagEnabled()) {
             caller = getCallerIdentity(admin, callerPackageName);
         } else {
             caller = getCallerIdentity(admin);
         }
         final int userId = caller.getUserId();
 
-        if (isPolicyEngineForFinanceFlagEnabled()) {
+        if (isPermissionCheckFlagEnabled()) {
             EnforcingAdmin enforcingAdmin = enforcePermissionAndGetEnforcingAdmin(
                     admin,
                     MANAGE_DEVICE_POLICY_RESET_PASSWORD,
@@ -19130,7 +19130,7 @@
             return false;
         }
         CallerIdentity caller;
-        if (isPolicyEngineForFinanceFlagEnabled()) {
+        if (isPermissionCheckFlagEnabled()) {
             caller = getCallerIdentity(admin, callerPackageName);
         } else {
             caller = getCallerIdentity(admin);
@@ -19138,7 +19138,7 @@
         final int userId = caller.getUserId();
         boolean result = false;
 
-        if (isPolicyEngineForFinanceFlagEnabled()) {
+        if (isPermissionCheckFlagEnabled()) {
             EnforcingAdmin enforcingAdmin = enforcePermissionAndGetEnforcingAdmin(
                     admin,
                     MANAGE_DEVICE_POLICY_RESET_PASSWORD,
@@ -19177,14 +19177,14 @@
             return false;
         }
         CallerIdentity caller;
-        if (isPolicyEngineForFinanceFlagEnabled()) {
+        if (isPermissionCheckFlagEnabled()) {
             caller = getCallerIdentity(admin, callerPackageName);
         } else {
             caller = getCallerIdentity(admin);
         }
         int userId = caller.getUserId();
 
-        if (isPolicyEngineForFinanceFlagEnabled()) {
+        if (isPermissionCheckFlagEnabled()) {
             EnforcingAdmin enforcingAdmin = enforcePermissionAndGetEnforcingAdmin(
                     admin,
                     MANAGE_DEVICE_POLICY_RESET_PASSWORD,
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 34b88b0..d85db64b 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -1511,7 +1511,6 @@
      * Validates that when the device owner is removed, the reset password token is cleared
      */
     @Test
-    @Ignore("b/277916462")
     public void testClearDeviceOwner_clearResetPasswordToken() throws Exception {
         mContext.callerPermissions.add(android.Manifest.permission.MANAGE_DEVICE_ADMINS);
         mContext.callerPermissions.add(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS);
@@ -2602,7 +2601,6 @@
     }
 
     @Test
-    @Ignore("b/277916462")
     public void testSetApplicationHiddenWithDO() throws Exception {
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
         setupDeviceOwner();
@@ -2628,7 +2626,6 @@
     }
 
     @Test
-    @Ignore("b/277916462")
     public void testSetApplicationHiddenWithPOOfOrganizationOwnedDevice() throws Exception {
         final int MANAGED_PROFILE_USER_ID = CALLER_USER_HANDLE;
         final int MANAGED_PROFILE_ADMIN_UID =
@@ -4375,7 +4372,6 @@
     }
 
     @Test
-    @Ignore("b/277916462")
     public void testSetAutoTimeZoneEnabledModifiesSetting() throws Exception {
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
         setupDeviceOwner();
@@ -4387,7 +4383,6 @@
     }
 
     @Test
-    @Ignore("b/277916462")
     public void testSetAutoTimeZoneEnabledWithPOOnUser0() throws Exception {
         mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
         setupProfileOwnerOnUser0();
@@ -4399,7 +4394,6 @@
     }
 
     @Test
-    @Ignore("b/277916462")
     public void testSetAutoTimeZoneEnabledFailWithPONotOnUser0() throws Exception {
         setupProfileOwner();
         assertExpectException(SecurityException.class, null,
@@ -4409,7 +4403,6 @@
     }
 
     @Test
-    @Ignore("b/277916462")
     public void testSetAutoTimeZoneEnabledWithPOOfOrganizationOwnedDevice() throws Exception {
         setupProfileOwner();
         configureProfileOwnerOfOrgOwnedDevice(admin1, CALLER_USER_HANDLE);
@@ -5383,7 +5376,6 @@
     }
 
     @Test
-    @Ignore("b/277916462")
     public void testResetPasswordWithToken() throws Exception {
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
         setupDeviceOwner();
@@ -5418,7 +5410,6 @@
     }
 
     @Test
-    @Ignore("b/277916462")
     public void resetPasswordWithToken_NumericPin() throws Exception {
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
         setupDeviceOwner();
@@ -5439,7 +5430,6 @@
     }
 
     @Test
-    @Ignore("b/277916462")
     public void resetPasswordWithToken_EmptyPassword() throws Exception {
         mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
         setupDeviceOwner();
@@ -7260,7 +7250,6 @@
     }
 
     @Test
-    @Ignore("b/277916462")
     public void testCanProfileOwnerResetPasswordWhenLocked() throws Exception {
         setDeviceEncryptionPerUser();
         setupProfileOwner();
@@ -7324,7 +7313,6 @@
     }
 
     @Test
-    @Ignore("b/277916462")
     public void testSetAccountTypesWithManagementDisabledOnManagedProfile() throws Exception {
         setupProfileOwner();
 
@@ -7344,7 +7332,6 @@
     }
 
     @Test
-    @Ignore("b/277916462")
     public void testSetAccountTypesWithManagementDisabledOnOrgOwnedManagedProfile()
             throws Exception {
         mContext.callerPermissions.add(permission.INTERACT_ACROSS_USERS);
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 21a11bc..52bf244 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.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 @@
         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 @@
         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 @@
     }
 
     @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 @@
         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 @@
                 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 @@
     }
 
     @Test
-    public void testMultiDisplay_onlyOneDisplaySleeps_onWakefulnessChangedEventFires() {
+    public void testMultiDisplay_onlyOneDisplaySleeps_onWakefulnessChangedEventsFire() {
         createService();
         startSystem();
         assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
@@ -2177,12 +2183,14 @@
         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 @@
         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 @@
         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 @@
                 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 2665e19..5636795 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 @@
         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/SurfaceControlTests.java b/services/tests/wmtests/src/com/android/server/wm/SurfaceControlTests.java
index 342ab83..4f45d5c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SurfaceControlTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SurfaceControlTests.java
@@ -125,9 +125,10 @@
     public void testSurfaceChangedOnRotation() {
         final Instrumentation instrumentation = getInstrumentation();
         final Context context = instrumentation.getContext();
-        final Activity activity = instrumentation.startActivitySync(new Intent().setComponent(
+        final Intent intent = new Intent().setComponent(
                 new ComponentName(context, ActivityOptionsTest.MainActivity.class))
-                .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
+                .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
+        final Activity activity = instrumentation.startActivitySync(intent);
         final SurfaceView sv = new SurfaceView(activity);
         final AtomicInteger surfaceChangedCount = new AtomicInteger();
         instrumentation.runOnMainSync(() -> activity.setContentView(sv));
@@ -157,12 +158,27 @@
         instrumentation.waitForIdleSync();
         final int newRotation = activity.getResources().getConfiguration()
                 .windowConfiguration.getRotation();
+        if (rotation == newRotation) {
+            // The device might not support requested orientation.
+            activity.finishAndRemoveTask();
+            return;
+        }
         final int count = surfaceChangedCount.get();
+        activity.moveTaskToBack(true /* nonRoot */);
+        instrumentation.getUiAutomation().syncInputTransactions();
+        context.startActivity(intent);
+        instrumentation.getUiAutomation().syncInputTransactions();
+        final int countAfterToFront = count - surfaceChangedCount.get();
         activity.finishAndRemoveTask();
+
         // The first count is triggered from creation, so the target number is 2.
-        if (rotation != newRotation && count > 2) {
+        if (count > 2) {
             fail("More than once surfaceChanged for rotation change: " + count);
         }
+        if (countAfterToFront > 1) {
+            fail("More than once surfaceChanged for app transition with rotation change: "
+                    + countAfterToFront);
+        }
     }
 
     private SurfaceControl buildTestSurface() {
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 32033fb..adf3f39 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 @@
     }
 
     @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