Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 34178b48 authored by Yeabkal Wubshit's avatar Yeabkal Wubshit Committed by Android (Google) Code Review
Browse files

Merge "Allow input wake up delegation" into main

parents 42c8338a c3b973d9
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -203,6 +203,7 @@ java_library_static {
        "com_android_wm_shell_flags_lib",
        "com.android.server.utils_aconfig-java",
        "service-jobscheduler-deviceidle.flags-aconfig-java",
        "policy_flags_lib",
    ],
    javac_shard_size: 50,
    javacflags: [
+10 −0
Original line number Diff line number Diff line
aconfig_declarations {
    name: "policy_flags",
    package: "com.android.server.policy",
    srcs: ["*.aconfig"],
}

java_aconfig_library {
    name: "policy_flags_lib",
    aconfig_declarations: "policy_flags",
}
+12 −7
Original line number Diff line number Diff line
@@ -1301,7 +1301,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
                    Settings.Global.putInt(mContext.getContentResolver(),
                            Settings.Global.THEATER_MODE_ON, 0);
                    if (!interactive) {
                        wakeUpFromWakeKey(eventTime, KEYCODE_POWER);
                        wakeUpFromWakeKey(eventTime, KEYCODE_POWER, /* isDown= */ false);
                    }
                } else {
                    Slog.i(TAG, "Toggling theater mode on.");
@@ -1317,7 +1317,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
            case MULTI_PRESS_POWER_BRIGHTNESS_BOOST:
                Slog.i(TAG, "Starting brightness boost.");
                if (!interactive) {
                    wakeUpFromWakeKey(eventTime, KEYCODE_POWER);
                    wakeUpFromWakeKey(eventTime, KEYCODE_POWER, /* isDown= */ false);
                }
                mPowerManager.boostScreenBrightness(eventTime);
                break;
@@ -5185,7 +5185,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
    public int interceptMotionBeforeQueueingNonInteractive(int displayId, int source, int action,
            long whenNanos, int policyFlags) {
        if ((policyFlags & FLAG_WAKE) != 0) {
            if (mWindowWakeUpPolicy.wakeUpFromMotion(whenNanos / 1000000)) {
            if (mWindowWakeUpPolicy.wakeUpFromMotion(
                        whenNanos / 1000000, source, action == MotionEvent.ACTION_DOWN)) {
                // Woke up. Pass motion events to user.
                return ACTION_PASS_TO_USER;
            }
@@ -5199,7 +5200,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
        // 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 (mWindowWakeUpPolicy.wakeUpFromMotion(whenNanos / 1000000)) {
            if (mWindowWakeUpPolicy.wakeUpFromMotion(
                        whenNanos / 1000000, source, action == MotionEvent.ACTION_DOWN)) {
                // Woke up. Pass motion events to user.
                return ACTION_PASS_TO_USER;
            }
@@ -5534,11 +5536,14 @@ public class PhoneWindowManager implements WindowManagerPolicy {
    }

    private void wakeUpFromWakeKey(KeyEvent event) {
        wakeUpFromWakeKey(event.getEventTime(), event.getKeyCode());
        wakeUpFromWakeKey(
                event.getEventTime(),
                event.getKeyCode(),
                event.getAction() == KeyEvent.ACTION_DOWN);
    }

    private void wakeUpFromWakeKey(long eventTime, int keyCode) {
        if (mWindowWakeUpPolicy.wakeUpFromKey(eventTime, keyCode)) {
    private void wakeUpFromWakeKey(long eventTime, int keyCode, boolean isDown) {
        if (mWindowWakeUpPolicy.wakeUpFromKey(eventTime, keyCode, isDown)) {
            final boolean keyCanLaunchHome = keyCode == KEYCODE_HOME || keyCode == KEYCODE_POWER;
            // Start HOME with "reason" extra if sleeping for more than mWakeUpToLastStateTimeout
            if (shouldWakeUpWithHomeIntent() &&  keyCanLaunchHome) {
+85 −36
Original line number Diff line number Diff line
@@ -24,6 +24,9 @@ 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 static com.android.server.policy.Flags.supportInputWakeupDelegate;

import android.annotation.Nullable;
import android.content.Context;
import android.content.res.Resources;
import android.os.PowerManager;
@@ -31,7 +34,11 @@ import android.os.PowerManager.WakeReason;
import android.os.SystemClock;
import android.provider.Settings;
import android.util.Slog;
import android.view.KeyEvent;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.Clock;
import com.android.server.LocalServices;

/** Policy controlling the decision and execution of window-related wake ups. */
class WindowWakeUpPolicy {
@@ -41,18 +48,27 @@ class WindowWakeUpPolicy {

    private final Context mContext;
    private final PowerManager mPowerManager;
    private final Clock mClock;

    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;

    // The policy will handle input-based wake ups if this delegate is null.
    @Nullable private WindowWakeUpPolicyInternal.InputWakeUpDelegate mInputWakeUpDelegate;

    WindowWakeUpPolicy(Context context) {
        this(context, Clock.SYSTEM_CLOCK);
    }

    @VisibleForTesting
    WindowWakeUpPolicy(Context context, Clock clock) {
        mContext = context;
        mPowerManager = context.getSystemService(PowerManager.class);
        mClock = clock;

        final Resources res = context.getResources();
        mAllowTheaterModeWakeFromKey = res.getBoolean(
@@ -62,14 +78,26 @@ class WindowWakeUpPolicy {
                    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);
        if (supportInputWakeupDelegate()) {
            LocalServices.addService(WindowWakeUpPolicyInternal.class, new LocalService());
        }
    }

    private final class LocalService implements WindowWakeUpPolicyInternal {
        @Override
        public void setInputWakeUpDelegate(@Nullable InputWakeUpDelegate delegate) {
            if (!supportInputWakeupDelegate()) {
                Slog.w(TAG, "Input wake up delegates not supported.");
                return;
            }
            mInputWakeUpDelegate = delegate;
        }
    }

    /**
@@ -77,31 +105,49 @@ class WindowWakeUpPolicy {
     *
     * @param eventTime the timestamp of the event in {@link SystemClock#uptimeMillis()}.
     * @param keyCode the {@link android.view.KeyEvent} key code of the key event.
     * @param isDown {@code true} if the event's action is {@link KeyEvent#ACTION_DOWN}.
     * @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) {
    boolean wakeUpFromKey(long eventTime, int keyCode, boolean isDown) {
        final boolean wakeAllowedDuringTheaterMode =
                keyCode == KEYCODE_POWER
                        ? mAllowTheaterModeWakeFromPowerKey
                        : mAllowTheaterModeWakeFromKey;
        return wakeUp(
        if (!canWakeUp(wakeAllowedDuringTheaterMode)) {
            if (DEBUG) Slog.d(TAG, "Unable to wake up from " + KeyEvent.keyCodeToString(keyCode));
            return false;
        }
        if (mInputWakeUpDelegate != null
                && mInputWakeUpDelegate.wakeUpFromKey(eventTime, keyCode, isDown)) {
            return true;
        }
        wakeUp(
                eventTime,
                wakeAllowedDuringTheaterMode,
                keyCode == KEYCODE_POWER ? WAKE_REASON_POWER_BUTTON : WAKE_REASON_WAKE_KEY,
                keyCode == KEYCODE_POWER ? "POWER" : "KEY");
        return true;
    }

    /**
     * Wakes up from a motion event.
     *
     * @param eventTime the timestamp of the event in {@link SystemClock#uptimeMillis()}.
     * @param isDown {@code true} if the event's action is {@link MotionEvent#ACTION_DOWN}.
     * @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");
    boolean wakeUpFromMotion(long eventTime, int source, boolean isDown) {
        if (!canWakeUp(mAllowTheaterModeWakeFromMotion)) {
            if (DEBUG) Slog.d(TAG, "Unable to wake up from motion.");
            return false;
        }
        if (mInputWakeUpDelegate != null
                && mInputWakeUpDelegate.wakeUpFromMotion(eventTime, source, isDown)) {
            return true;
        }
        wakeUp(eventTime, WAKE_REASON_WAKE_MOTION, "MOTION");
        return true;
    }

    /**
@@ -112,11 +158,12 @@ class WindowWakeUpPolicy {
     *      executed; {@code false} otherwise.
     */
    boolean wakeUpFromCameraCover(long eventTime) {
        return wakeUp(
                eventTime,
                mAllowTheaterModeWakeFromCameraLens,
                WAKE_REASON_CAMERA_LAUNCH,
                "CAMERA_COVER");
        if (!canWakeUp(mAllowTheaterModeWakeFromCameraLens)) {
            if (DEBUG) Slog.d(TAG, "Unable to wake up from camera cover.");
            return false;
        }
        wakeUp(eventTime, WAKE_REASON_CAMERA_LAUNCH, "CAMERA_COVER");
        return true;
    }

    /**
@@ -126,11 +173,12 @@ class WindowWakeUpPolicy {
     *      executed; {@code false} otherwise.
     */
    boolean wakeUpFromLid() {
        return wakeUp(
                SystemClock.uptimeMillis(),
                mAllowTheaterModeWakeFromLidSwitch,
                WAKE_REASON_LID,
                "LID");
        if (!canWakeUp(mAllowTheaterModeWakeFromLidSwitch)) {
            if (DEBUG) Slog.d(TAG, "Unable to wake up from lid.");
            return false;
        }
        wakeUp(mClock.uptimeMillis(), WAKE_REASON_LID, "LID");
        return true;
    }

    /**
@@ -140,11 +188,12 @@ class WindowWakeUpPolicy {
     *      executed; {@code false} otherwise.
     */
    boolean wakeUpFromPowerKeyCameraGesture() {
        return wakeUp(
                SystemClock.uptimeMillis(),
                mAllowTheaterModeWakeFromPowerKey,
                WAKE_REASON_CAMERA_LAUNCH,
                "CAMERA_GESTURE_PREVENT_LOCK");
        if (!canWakeUp(mAllowTheaterModeWakeFromPowerKey)) {
            if (DEBUG) Slog.d(TAG, "Unable to wake up from power key camera gesture.");
            return false;
        }
        wakeUp(mClock.uptimeMillis(), WAKE_REASON_CAMERA_LAUNCH, "CAMERA_GESTURE_PREVENT_LOCK");
        return true;
    }

    /**
@@ -154,23 +203,23 @@ class WindowWakeUpPolicy {
     *      executed; {@code false} otherwise.
     */
    boolean wakeUpFromWakeGesture() {
        return wakeUp(
                SystemClock.uptimeMillis(),
                mAllowTheaterModeWakeFromWakeGesture,
                WAKE_REASON_GESTURE,
                "GESTURE");
        if (!canWakeUp(mAllowTheaterModeWakeFromWakeGesture)) {
            if (DEBUG) Slog.d(TAG, "Unable to wake up from gesture.");
            return false;
        }
        wakeUp(mClock.uptimeMillis(), WAKE_REASON_GESTURE, "GESTURE");
        return true;
    }

    private boolean wakeUp(
            long wakeTime, boolean wakeInTheaterMode, @WakeReason int reason, String details) {
    private boolean canWakeUp(boolean wakeInTheaterMode) {
        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;
        return wakeInTheaterMode || !isTheaterModeEnabled;
    }

    /** Wakes up {@link PowerManager}. */
    private void wakeUp(long wakeTime, @WakeReason int reason, String details) {
        mPowerManager.wakeUp(wakeTime, reason, "android.policy:" + details);
        return true;
    }
}
+75 −0
Original line number Diff line number Diff line
/*
 * 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 android.annotation.Nullable;
import android.os.SystemClock;

import com.android.internal.annotations.Keep;
import com.android.server.LocalServices;

/** Policy controlling the decision and execution of window-related wake ups. */
@Keep
public interface WindowWakeUpPolicyInternal {

    /**
     * A delegate that can choose to intercept Input-related wake ups.
     *
     * <p>This delegate is not meant to control policy decisions on whether or not to wake up. The
     * policy makes that decision, and forwards the wake up request to the delegate as necessary.
     * Therefore, the role of the delegate is to handle the actual "waking" of the device in
     * response to the respective input event.
     */
    @Keep
    interface InputWakeUpDelegate {
        /**
         * Wakes up the device in response to 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.
         * @param isDown {@code true} if the event's action is {@link KeyEvent#ACTION_DOWN}.
         * @return {@code true} if the delegate handled the wake up. {@code false} if the delegate
         *      decided not to handle the wake up. The policy will execute the wake up in this case.
         */
        boolean wakeUpFromKey(long eventTime, int keyCode, boolean isDown);
        /**
         * Wakes up the device in response to a motion event.
         *
         * @param eventTime the timestamp of the event in {@link SystemClock#uptimeMillis()}.
         * @param source the {@link android.view.InputDevice} source that caused the event.
         * @param isDown {@code true} if the event's action is {@link MotionEvent#ACTION_DOWN}.
         * @return {@code true} if the delegate handled the wake up. {@code false} if the delegate
         *      decided not to handle the wake up. The policy will execute the wake up in this case.
         */
        boolean wakeUpFromMotion(long eventTime, int source, boolean isDown);
    }

    /**
     * Allows injecting a delegate for controlling input-based wake ups.
     *
     * <p>A delegate can be injected to the policy by system_server components only, and should be
     * done via the {@link LocalServices} interface.
     *
     * <p>There can at most be one active delegate. If there's no delegate set (or if a {@code null}
     * delegate is set), the policy will handle waking up the device in response to input events.
     *
     * @param delegate an implementation of {@link InputWakeUpDelegate} that handles input-based
     *      wake up requests. {@code null} to let the policy handle these wake ups.
     */
    @Keep
    void setInputWakeUpDelegate(@Nullable InputWakeUpDelegate delegate);
}
Loading