Merge "Create WindowWakeUpPolicy" into main
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 5b13d3fe..edce3ec 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -473,6 +473,8 @@
 
     private TalkbackShortcutController mTalkbackShortcutController;
 
+    private WindowWakeUpPolicy mWindowWakeUpPolicy;
+
     boolean mSafeMode;
 
     // Whether to allow dock apps with METADATA_DOCK_HOME to temporarily take over the Home key.
@@ -640,15 +642,6 @@
     // Whether to lock the device after the next dreaming transition has finished.
     private boolean mLockAfterDreamingTransitionFinished;
 
-    // Allowed theater mode wake actions
-    private boolean mAllowTheaterModeWakeFromKey;
-    private boolean mAllowTheaterModeWakeFromPowerKey;
-    private boolean mAllowTheaterModeWakeFromMotion;
-    private boolean mAllowTheaterModeWakeFromMotionWhenNotDreaming;
-    private boolean mAllowTheaterModeWakeFromCameraLens;
-    private boolean mAllowTheaterModeWakeFromLidSwitch;
-    private boolean mAllowTheaterModeWakeFromWakeGesture;
-
     // If true, the power button long press behavior will be invoked even if the default display is
     // non-interactive. If false, the power button long press behavior will be skipped if the
     // default display is non-interactive.
@@ -930,8 +923,7 @@
                 if (shouldEnableWakeGestureLp()) {
                     performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY, false,
                             "Wake Up");
-                    wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromWakeGesture,
-                            PowerManager.WAKE_REASON_GESTURE, "android.policy:GESTURE");
+                    mWindowWakeUpPolicy.wakeUpFromWakeGesture();
                 }
             }
         }
@@ -1067,7 +1059,7 @@
                 || handledByPowerManager || mKeyCombinationManager.isPowerKeyIntercepted();
         if (!mPowerKeyHandled) {
             if (!interactive) {
-                wakeUpFromPowerKey(event.getDownTime());
+                wakeUpFromWakeKey(event);
             }
         } else {
             // handled by another power key policy.
@@ -1309,7 +1301,7 @@
                     Settings.Global.putInt(mContext.getContentResolver(),
                             Settings.Global.THEATER_MODE_ON, 0);
                     if (!interactive) {
-                        wakeUpFromPowerKey(eventTime);
+                        wakeUpFromWakeKey(eventTime, KEYCODE_POWER);
                     }
                 } else {
                     Slog.i(TAG, "Toggling theater mode on.");
@@ -1325,7 +1317,7 @@
             case MULTI_PRESS_POWER_BRIGHTNESS_BOOST:
                 Slog.i(TAG, "Starting brightness boost.");
                 if (!interactive) {
-                    wakeUpFromPowerKey(eventTime);
+                    wakeUpFromWakeKey(eventTime, KEYCODE_POWER);
                 }
                 mPowerManager.boostScreenBrightness(eventTime);
                 break;
@@ -2312,22 +2304,6 @@
         mLidNavigationAccessibility = mContext.getResources().getInteger(
                 com.android.internal.R.integer.config_lidNavigationAccessibility);
 
-        mAllowTheaterModeWakeFromKey = mContext.getResources().getBoolean(
-                com.android.internal.R.bool.config_allowTheaterModeWakeFromKey);
-        mAllowTheaterModeWakeFromPowerKey = mAllowTheaterModeWakeFromKey
-                || mContext.getResources().getBoolean(
-                    com.android.internal.R.bool.config_allowTheaterModeWakeFromPowerKey);
-        mAllowTheaterModeWakeFromMotion = mContext.getResources().getBoolean(
-                com.android.internal.R.bool.config_allowTheaterModeWakeFromMotion);
-        mAllowTheaterModeWakeFromMotionWhenNotDreaming = mContext.getResources().getBoolean(
-                com.android.internal.R.bool.config_allowTheaterModeWakeFromMotionWhenNotDreaming);
-        mAllowTheaterModeWakeFromCameraLens = mContext.getResources().getBoolean(
-                com.android.internal.R.bool.config_allowTheaterModeWakeFromCameraLens);
-        mAllowTheaterModeWakeFromLidSwitch = mContext.getResources().getBoolean(
-                com.android.internal.R.bool.config_allowTheaterModeWakeFromLidSwitch);
-        mAllowTheaterModeWakeFromWakeGesture = mContext.getResources().getBoolean(
-                com.android.internal.R.bool.config_allowTheaterModeWakeFromGesture);
-
         mGoToSleepOnButtonPressTheaterMode = mContext.getResources().getBoolean(
                 com.android.internal.R.bool.config_goToSleepOnButtonPressTheaterMode);
 
@@ -2457,6 +2433,7 @@
                 com.android.internal.R.integer.config_keyguardDrawnTimeout);
         mKeyguardDelegate = injector.getKeyguardServiceDelegate();
         mTalkbackShortcutController = injector.getTalkbackShortcutController();
+        mWindowWakeUpPolicy = new WindowWakeUpPolicy(mContext);
         initKeyCombinationRules();
         initSingleKeyGestureRules(injector.getLooper());
         mButtonOverridePermissionChecker = injector.getButtonOverridePermissionChecker();
@@ -4483,8 +4460,7 @@
         updateRotation(true);
 
         if (lidOpen) {
-            wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromLidSwitch,
-                    PowerManager.WAKE_REASON_LID, "android.policy:LID");
+            mWindowWakeUpPolicy.wakeUpFromLid();
         } else if (getLidBehavior() != LID_BEHAVIOR_SLEEP) {
             mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
         }
@@ -4510,8 +4486,7 @@
             } else {
                 intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
             }
-            wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromCameraLens,
-                    PowerManager.WAKE_REASON_CAMERA_LAUNCH, "android.policy:CAMERA_COVER");
+            mWindowWakeUpPolicy.wakeUpFromCameraCover(whenNanos / 1000000);
             startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
         }
         mCameraLensCoverState = lensCoverState;
@@ -4589,7 +4564,7 @@
             boolean shouldTurnOnTv = false;
             if (down && (keyCode == KeyEvent.KEYCODE_POWER
                     || keyCode == KeyEvent.KEYCODE_TV_POWER)) {
-                wakeUpFromPowerKey(event.getDownTime());
+                wakeUpFromWakeKey(event);
                 shouldTurnOnTv = true;
             } else if (down && (isWakeKey || keyCode == KeyEvent.KEYCODE_WAKEUP)
                     && isWakeKeyWhenScreenOff(keyCode)) {
@@ -5104,9 +5079,7 @@
         if (mRequestedOrSleepingDefaultDisplay) {
             mCameraGestureTriggeredDuringGoingToSleep = true;
             // Wake device up early to prevent display doing redundant turning off/on stuff.
-            wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromPowerKey,
-                    PowerManager.WAKE_REASON_CAMERA_LAUNCH,
-                    "android.policy:CAMERA_GESTURE_PREVENT_LOCK");
+            mWindowWakeUpPolicy.wakeUpFromPowerKeyCameraGesture();
         }
         return true;
     }
@@ -5204,8 +5177,7 @@
     public int interceptMotionBeforeQueueingNonInteractive(int displayId, int source, int action,
             long whenNanos, int policyFlags) {
         if ((policyFlags & FLAG_WAKE) != 0) {
-            if (wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotion,
-                    PowerManager.WAKE_REASON_WAKE_MOTION, "android.policy:MOTION")) {
+            if (mWindowWakeUpPolicy.wakeUpFromMotion(whenNanos / 1000000)) {
                 // Woke up. Pass motion events to user.
                 return ACTION_PASS_TO_USER;
             }
@@ -5219,8 +5191,7 @@
         // there will be no dream to intercept the touch and wake into ambient.  The device should
         // wake up in this case.
         if (isTheaterModeEnabled() && (policyFlags & FLAG_WAKE) != 0) {
-            if (wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotionWhenNotDreaming,
-                    PowerManager.WAKE_REASON_WAKE_MOTION, "android.policy:MOTION")) {
+            if (mWindowWakeUpPolicy.wakeUpFromMotion(whenNanos / 1000000)) {
                 // Woke up. Pass motion events to user.
                 return ACTION_PASS_TO_USER;
             }
@@ -5554,37 +5525,22 @@
         return sleepDurationRealtime > mWakeUpToLastStateTimeout;
     }
 
-    private void wakeUpFromPowerKey(long eventTime) {
-        if (wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey,
-                PowerManager.WAKE_REASON_POWER_BUTTON, "android.policy:POWER")) {
-            // Start HOME with "reason" extra if sleeping for more than mWakeUpToLastStateTimeout
-            if (shouldWakeUpWithHomeIntent()) {
-                startDockOrHome(DEFAULT_DISPLAY, /*fromHomeKey*/ false, /*wakenFromDreams*/ true,
-                        PowerManager.wakeReasonToString(PowerManager.WAKE_REASON_POWER_BUTTON));
-            }
-        }
-    }
-
     private void wakeUpFromWakeKey(KeyEvent event) {
-        if (wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey,
-                PowerManager.WAKE_REASON_WAKE_KEY, "android.policy:KEY")) {
-            // Start HOME with "reason" extra if sleeping for more than mWakeUpToLastStateTimeout
-            if (shouldWakeUpWithHomeIntent() && event.getKeyCode() == KEYCODE_HOME) {
-                startDockOrHome(DEFAULT_DISPLAY, /*fromHomeKey*/ true, /*wakenFromDreams*/ true,
-                        PowerManager.wakeReasonToString(PowerManager.WAKE_REASON_WAKE_KEY));
-            }
-        }
+        wakeUpFromWakeKey(event.getEventTime(), event.getKeyCode());
     }
 
-    private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode, @WakeReason int reason,
-            String details) {
-        final boolean theaterModeEnabled = isTheaterModeEnabled();
-        if (!wakeInTheaterMode && theaterModeEnabled) {
-            return false;
+    private void wakeUpFromWakeKey(long eventTime, int keyCode) {
+        if (mWindowWakeUpPolicy.wakeUpFromKey(eventTime, keyCode)) {
+            final boolean keyCanLaunchHome = keyCode == KEYCODE_HOME || keyCode == KEYCODE_POWER;
+            // Start HOME with "reason" extra if sleeping for more than mWakeUpToLastStateTimeout
+            if (shouldWakeUpWithHomeIntent() &&  keyCanLaunchHome) {
+                startDockOrHome(
+                        DEFAULT_DISPLAY,
+                        /*fromHomeKey*/ keyCode == KEYCODE_HOME,
+                        /*wakenFromDreams*/ true,
+                        "Wake from " + KeyEvent. keyCodeToString(keyCode));
+            }
         }
-
-        mPowerManager.wakeUp(wakeTime, reason, details);
-        return true;
     }
 
     private void finishKeyguardDrawn() {
diff --git a/services/core/java/com/android/server/policy/WindowWakeUpPolicy.java b/services/core/java/com/android/server/policy/WindowWakeUpPolicy.java
new file mode 100644
index 0000000..392d0d4
--- /dev/null
+++ b/services/core/java/com/android/server/policy/WindowWakeUpPolicy.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.policy;
+
+import static android.os.PowerManager.WAKE_REASON_CAMERA_LAUNCH;
+import static android.os.PowerManager.WAKE_REASON_GESTURE;
+import static android.os.PowerManager.WAKE_REASON_LID;
+import static android.os.PowerManager.WAKE_REASON_POWER_BUTTON;
+import static android.os.PowerManager.WAKE_REASON_WAKE_KEY;
+import static android.os.PowerManager.WAKE_REASON_WAKE_MOTION;
+import static android.view.KeyEvent.KEYCODE_POWER;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.os.PowerManager;
+import android.os.PowerManager.WakeReason;
+import android.os.SystemClock;
+import android.provider.Settings;
+import android.util.Slog;
+
+
+/** Policy controlling the decision and execution of window-related wake ups. */
+class WindowWakeUpPolicy {
+    private static final String TAG = "WindowWakeUpPolicy";
+
+    private static final boolean DEBUG = false;
+
+    private final Context mContext;
+    private final PowerManager mPowerManager;
+
+    private final boolean mAllowTheaterModeWakeFromKey;
+    private final boolean mAllowTheaterModeWakeFromPowerKey;
+    private final boolean mAllowTheaterModeWakeFromMotion;
+    private final boolean mAllowTheaterModeWakeFromMotionWhenNotDreaming;
+    private final boolean mAllowTheaterModeWakeFromCameraLens;
+    private final boolean mAllowTheaterModeWakeFromLidSwitch;
+    private final boolean mAllowTheaterModeWakeFromWakeGesture;
+
+    WindowWakeUpPolicy(Context context) {
+        mContext = context;
+        mPowerManager = context.getSystemService(PowerManager.class);
+
+        final Resources res = context.getResources();
+        mAllowTheaterModeWakeFromKey = res.getBoolean(
+                com.android.internal.R.bool.config_allowTheaterModeWakeFromKey);
+        mAllowTheaterModeWakeFromPowerKey = mAllowTheaterModeWakeFromKey
+                || res.getBoolean(
+                    com.android.internal.R.bool.config_allowTheaterModeWakeFromPowerKey);
+        mAllowTheaterModeWakeFromMotion = res.getBoolean(
+                com.android.internal.R.bool.config_allowTheaterModeWakeFromMotion);
+        mAllowTheaterModeWakeFromMotionWhenNotDreaming = res.getBoolean(
+                com.android.internal.R.bool.config_allowTheaterModeWakeFromMotionWhenNotDreaming);
+        mAllowTheaterModeWakeFromCameraLens = res.getBoolean(
+                com.android.internal.R.bool.config_allowTheaterModeWakeFromCameraLens);
+        mAllowTheaterModeWakeFromLidSwitch = res.getBoolean(
+                com.android.internal.R.bool.config_allowTheaterModeWakeFromLidSwitch);
+        mAllowTheaterModeWakeFromWakeGesture = res.getBoolean(
+                com.android.internal.R.bool.config_allowTheaterModeWakeFromGesture);
+    }
+
+    /**
+     * Wakes up from a key event.
+     *
+     * @param eventTime the timestamp of the event in {@link SystemClock#uptimeMillis()}.
+     * @param keyCode the {@link android.view.KeyEvent} key code of the key event.
+     * @return {@code true} if the policy allows the requested wake up and the request has been
+     *      executed; {@code false} otherwise.
+     */
+    boolean wakeUpFromKey(long eventTime, int keyCode) {
+        final boolean wakeAllowedDuringTheaterMode =
+                keyCode == KEYCODE_POWER
+                        ? mAllowTheaterModeWakeFromPowerKey
+                        : mAllowTheaterModeWakeFromKey;
+        return wakeUp(
+                eventTime,
+                wakeAllowedDuringTheaterMode,
+                keyCode == KEYCODE_POWER ? WAKE_REASON_POWER_BUTTON : WAKE_REASON_WAKE_KEY,
+                keyCode == KEYCODE_POWER ? "POWER" : "KEY");
+    }
+
+    /**
+     * Wakes up from a motion event.
+     *
+     * @param eventTime the timestamp of the event in {@link SystemClock#uptimeMillis()}.
+     * @return {@code true} if the policy allows the requested wake up and the request has been
+     *      executed; {@code false} otherwise.
+     */
+    boolean wakeUpFromMotion(long eventTime) {
+        return wakeUp(
+                eventTime, mAllowTheaterModeWakeFromMotion, WAKE_REASON_WAKE_MOTION, "MOTION");
+    }
+
+    /**
+     * Wakes up due to an opened camera cover.
+     *
+     * @param eventTime the timestamp of the event in {@link SystemClock#uptimeMillis()}.
+     * @return {@code true} if the policy allows the requested wake up and the request has been
+     *      executed; {@code false} otherwise.
+     */
+    boolean wakeUpFromCameraCover(long eventTime) {
+        return wakeUp(
+                eventTime,
+                mAllowTheaterModeWakeFromCameraLens,
+                WAKE_REASON_CAMERA_LAUNCH,
+                "CAMERA_COVER");
+    }
+
+    /**
+     * Wakes up due to an opened lid.
+     *
+     * @return {@code true} if the policy allows the requested wake up and the request has been
+     *      executed; {@code false} otherwise.
+     */
+    boolean wakeUpFromLid() {
+        return wakeUp(
+                SystemClock.uptimeMillis(),
+                mAllowTheaterModeWakeFromLidSwitch,
+                WAKE_REASON_LID,
+                "LID");
+    }
+
+    /**
+     * Wakes up to prevent sleeping when opening camera through power button.
+     *
+     * @return {@code true} if the policy allows the requested wake up and the request has been
+     *      executed; {@code false} otherwise.
+     */
+    boolean wakeUpFromPowerKeyCameraGesture() {
+        return wakeUp(
+                SystemClock.uptimeMillis(),
+                mAllowTheaterModeWakeFromPowerKey,
+                WAKE_REASON_CAMERA_LAUNCH,
+                "CAMERA_GESTURE_PREVENT_LOCK");
+    }
+
+    /**
+     * Wake up from a wake gesture.
+     *
+     * @return {@code true} if the policy allows the requested wake up and the request has been
+     *      executed; {@code false} otherwise.
+     */
+    boolean wakeUpFromWakeGesture() {
+        return wakeUp(
+                SystemClock.uptimeMillis(),
+                mAllowTheaterModeWakeFromWakeGesture,
+                WAKE_REASON_GESTURE,
+                "GESTURE");
+    }
+
+    private boolean wakeUp(
+            long wakeTime, boolean wakeInTheaterMode, @WakeReason int reason, String details) {
+        final boolean isTheaterModeEnabled =
+                Settings.Global.getInt(
+                        mContext.getContentResolver(), Settings.Global.THEATER_MODE_ON, 0) == 1;
+        if (!wakeInTheaterMode && isTheaterModeEnabled) {
+            if (DEBUG) Slog.d(TAG, "Unable to wake up from " + details);
+            return false;
+        }
+        mPowerManager.wakeUp(wakeTime, reason, "android.policy:" + details);
+        return true;
+    }
+}