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

Commit a3762e3a authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge changes from topic "revert-30698369-revert-30412668-HWHJRSWUQP-SSEJIYIUHQ" into main

* changes:
  Fixes failing PowerMenuTest.
  Revert^2 "Launch wallet app on double tap option."
  Revert "Revert "Allow focused privileged windows to capture the ..."
parents 6179ebc7 0d09c285
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -27,11 +27,13 @@ public class KeyInterceptionInfo {
    // Debug friendly name to help identify the window
    public final String windowTitle;
    public final int windowOwnerUid;
    public final int inputFeaturesFlags;

    public KeyInterceptionInfo(int type, int flags, String title, int uid) {
    public KeyInterceptionInfo(int type, int flags, String title, int uid, int inputFeaturesFlags) {
        layoutParamsType = type;
        layoutParamsPrivateFlags = flags;
        windowTitle = title;
        windowOwnerUid = uid;
        this.inputFeaturesFlags = inputFeaturesFlags;
    }
}
+263 −46
Original line number Diff line number Diff line
@@ -16,9 +16,14 @@

package com.android.server;

import static android.service.quickaccesswallet.Flags.launchWalletOptionOnPowerDoubleTap;

import static com.android.hardware.input.Flags.overridePowerKeyBehaviorInFocusedWindow;
import static com.android.internal.R.integer.config_defaultMinEmergencyGestureTapDurationMillis;

import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.app.PendingIntent;
import android.app.StatusBarManager;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -33,6 +38,7 @@ import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.hardware.TriggerEvent;
import android.hardware.TriggerEventListener;
import android.os.Bundle;
import android.os.Handler;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
@@ -41,10 +47,12 @@ import android.os.SystemProperties;
import android.os.Trace;
import android.os.UserHandle;
import android.provider.Settings;
import android.service.quickaccesswallet.QuickAccessWalletClient;
import android.util.MutableBoolean;
import android.util.Slog;
import android.view.KeyEvent;

import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.UiEvent;
@@ -70,7 +78,8 @@ public class GestureLauncherService extends SystemService {
     * Time in milliseconds in which the power button must be pressed twice so it will be considered
     * as a camera launch.
     */
    @VisibleForTesting static final long CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS = 300;
    @VisibleForTesting
    static final long POWER_DOUBLE_TAP_MAX_TIME_MS = 300;


    /**
@@ -100,10 +109,23 @@ public class GestureLauncherService extends SystemService {
    @VisibleForTesting
    static final int EMERGENCY_GESTURE_POWER_BUTTON_COOLDOWN_PERIOD_MS_MAX = 5000;

    /**
     * Number of taps required to launch camera shortcut.
     */
    private static final int CAMERA_POWER_TAP_COUNT_THRESHOLD = 2;
    /** Indicates camera should be launched on power double tap. */
    @VisibleForTesting static final int LAUNCH_CAMERA_ON_DOUBLE_TAP_POWER = 0;

    /** Indicates wallet should be launched on power double tap. */
    @VisibleForTesting static final int LAUNCH_WALLET_ON_DOUBLE_TAP_POWER = 1;

    /** Number of taps required to launch the double tap shortcut (either camera or wallet). */
    public static final int DOUBLE_POWER_TAP_COUNT_THRESHOLD = 2;

    /** Bundle to send with PendingIntent to grant background activity start privileges. */
    private static final Bundle GRANT_BACKGROUND_START_PRIVILEGES =
            ActivityOptions.makeBasic()
                    .setPendingIntentBackgroundActivityStartMode(
                            ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOW_ALWAYS)
                    .toBundle();

    private final QuickAccessWalletClient mQuickAccessWalletClient;

    /** The listener that receives the gesture event. */
    private final GestureEventListener mGestureListener = new GestureEventListener();
@@ -158,6 +180,9 @@ public class GestureLauncherService extends SystemService {
     */
    private boolean mCameraDoubleTapPowerEnabled;

    /** Whether wallet double tap power button gesture is currently enabled. */
    private boolean mWalletDoubleTapPowerEnabled;

    /**
     * Whether emergency gesture is currently enabled
     */
@@ -204,14 +229,22 @@ public class GestureLauncherService extends SystemService {
        }
    }
    public GestureLauncherService(Context context) {
        this(context, new MetricsLogger(), new UiEventLoggerImpl());
        this(
                context,
                new MetricsLogger(),
                QuickAccessWalletClient.create(context),
                new UiEventLoggerImpl());
    }

    @VisibleForTesting
    GestureLauncherService(Context context, MetricsLogger metricsLogger,
    public GestureLauncherService(
            Context context,
            MetricsLogger metricsLogger,
            QuickAccessWalletClient quickAccessWalletClient,
            UiEventLogger uiEventLogger) {
        super(context);
        mContext = context;
        mQuickAccessWalletClient = quickAccessWalletClient;
        mMetricsLogger = metricsLogger;
        mUiEventLogger = uiEventLogger;
    }
@@ -237,6 +270,9 @@ public class GestureLauncherService extends SystemService {
                    "GestureLauncherService");
            updateCameraRegistered();
            updateCameraDoubleTapPowerEnabled();
            if (launchWalletOptionOnPowerDoubleTap()) {
                updateWalletDoubleTapPowerEnabled();
            }
            updateEmergencyGestureEnabled();
            updateEmergencyGesturePowerButtonCooldownPeriodMs();

@@ -291,6 +327,14 @@ public class GestureLauncherService extends SystemService {
        }
    }

    @VisibleForTesting
    void updateWalletDoubleTapPowerEnabled() {
        boolean enabled = isWalletDoubleTapPowerSettingEnabled(mContext, mUserId);
        synchronized (this) {
            mWalletDoubleTapPowerEnabled = enabled;
        }
    }

    @VisibleForTesting
    void updateEmergencyGestureEnabled() {
        boolean enabled = isEmergencyGestureSettingEnabled(mContext, mUserId);
@@ -418,11 +462,34 @@ public class GestureLauncherService extends SystemService {
                        Settings.Secure.CAMERA_GESTURE_DISABLED, 0, userId) == 0);
    }

    /** Checks if camera should be launched on double press of the power button. */
    public static boolean isCameraDoubleTapPowerSettingEnabled(Context context, int userId) {
        return isCameraDoubleTapPowerEnabled(context.getResources())
        boolean res;

        if (launchWalletOptionOnPowerDoubleTap()) {
            res = isDoubleTapPowerGestureSettingEnabled(context, userId)
                    && getDoubleTapPowerGestureAction(context, userId)
                    == LAUNCH_CAMERA_ON_DOUBLE_TAP_POWER;
        } else {
            // These are legacy settings that will be deprecated once the option to launch both
            // wallet and camera has been created.
            res = isCameraDoubleTapPowerEnabled(context.getResources())
                    && (Settings.Secure.getIntForUser(context.getContentResolver(),
                    Settings.Secure.CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, 0, userId) == 0);
        }
        return res;
    }

    /** Checks if wallet should be launched on double tap of the power button. */
    public static boolean isWalletDoubleTapPowerSettingEnabled(Context context, int userId) {
        if (!launchWalletOptionOnPowerDoubleTap()) {
            return false;
        }

        return isDoubleTapPowerGestureSettingEnabled(context, userId)
                && getDoubleTapPowerGestureAction(context, userId)
                        == LAUNCH_WALLET_ON_DOUBLE_TAP_POWER;
    }

    public static boolean isCameraLiftTriggerSettingEnabled(Context context, int userId) {
        return isCameraLiftTriggerEnabled(context.getResources())
@@ -441,6 +508,28 @@ public class GestureLauncherService extends SystemService {
                isDefaultEmergencyGestureEnabled(context.getResources()) ? 1 : 0, userId) != 0;
    }

    private static int getDoubleTapPowerGestureAction(Context context, int userId) {
        return Settings.Secure.getIntForUser(
                context.getContentResolver(),
                Settings.Secure.DOUBLE_TAP_POWER_BUTTON_GESTURE,
                LAUNCH_CAMERA_ON_DOUBLE_TAP_POWER,
                userId);
    }

    /** Whether the shortcut to launch app on power double press is enabled. */
    private static boolean isDoubleTapPowerGestureSettingEnabled(Context context, int userId) {
        return Settings.Secure.getIntForUser(
                                context.getContentResolver(),
                                Settings.Secure.DOUBLE_TAP_POWER_BUTTON_GESTURE_ENABLED,
                                isDoubleTapConfigEnabled(context.getResources()) ? 1 : 0,
                                userId)
                        == 1;
    }

    private static boolean isDoubleTapConfigEnabled(Resources resources) {
        return resources.getBoolean(R.bool.config_doubleTapPowerGestureEnabled);
    }

    /**
     * Gets power button cooldown period in milliseconds after emergency gesture is triggered. The
     * value is capped at a maximum
@@ -494,10 +583,56 @@ public class GestureLauncherService extends SystemService {
     * Whether GestureLauncherService should be enabled according to system properties.
     */
    public static boolean isGestureLauncherEnabled(Resources resources) {
        return isCameraLaunchEnabled(resources)
                || isCameraDoubleTapPowerEnabled(resources)
        boolean res =
                isCameraLaunchEnabled(resources)
                        || isCameraLiftTriggerEnabled(resources)
                        || isEmergencyGestureEnabled(resources);
        if (launchWalletOptionOnPowerDoubleTap()) {
            res |= isDoubleTapConfigEnabled(resources);
        } else {
            res |= isCameraDoubleTapPowerEnabled(resources);
        }
        return res;
    }

    /**
     * Processes a power key event in GestureLauncherService without performing an action. This
     * method is called on every KEYCODE_POWER ACTION_DOWN event and ensures that, even if
     * KEYCODE_POWER events are passed to and handled by the app, the GestureLauncherService still
     * keeps track of all running KEYCODE_POWER events for its gesture detection and relevant
     * actions.
     */
    public void processPowerKeyDown(KeyEvent event) {
        if (mEmergencyGestureEnabled && mEmergencyGesturePowerButtonCooldownPeriodMs >= 0
                && event.getEventTime() - mLastEmergencyGestureTriggered
                < mEmergencyGesturePowerButtonCooldownPeriodMs) {
            return;
        }
        if (event.isLongPress()) {
            return;
        }

        final long powerTapInterval;

        synchronized (this) {
            powerTapInterval = event.getEventTime() - mLastPowerDown;
            mLastPowerDown = event.getEventTime();
            if (powerTapInterval >= POWER_SHORT_TAP_SEQUENCE_MAX_INTERVAL_MS) {
                // Tap too slow, reset consecutive tap counts.
                mFirstPowerDown = event.getEventTime();
                mPowerButtonConsecutiveTaps = 1;
                mPowerButtonSlowConsecutiveTaps = 1;
            } else if (powerTapInterval >= POWER_DOUBLE_TAP_MAX_TIME_MS) {
                // Tap too slow for shortcuts
                mFirstPowerDown = event.getEventTime();
                mPowerButtonConsecutiveTaps = 1;
                mPowerButtonSlowConsecutiveTaps++;
            } else if (powerTapInterval > 0) {
                // Fast consecutive tap
                mPowerButtonConsecutiveTaps++;
                mPowerButtonSlowConsecutiveTaps++;
            }
        }
    }

    /**
@@ -507,8 +642,8 @@ public class GestureLauncherService extends SystemService {
     * @param outLaunched true if some action is taken as part of the key intercept (eg, app launch)
     * @return true if the key down event is intercepted
     */
    public boolean interceptPowerKeyDown(KeyEvent event, boolean interactive,
            MutableBoolean outLaunched) {
    public boolean interceptPowerKeyDown(
            KeyEvent event, boolean interactive, MutableBoolean outLaunched) {
        if (mEmergencyGestureEnabled && mEmergencyGesturePowerButtonCooldownPeriodMs >= 0
                && event.getEventTime() - mLastEmergencyGestureTriggered
                < mEmergencyGesturePowerButtonCooldownPeriodMs) {
@@ -530,6 +665,7 @@ public class GestureLauncherService extends SystemService {
            return false;
        }
        boolean launchCamera = false;
        boolean launchWallet = false;
        boolean launchEmergencyGesture = false;
        boolean intercept = false;
        long powerTapInterval;
@@ -541,12 +677,12 @@ public class GestureLauncherService extends SystemService {
                mFirstPowerDown  = event.getEventTime();
                mPowerButtonConsecutiveTaps = 1;
                mPowerButtonSlowConsecutiveTaps = 1;
            } else if (powerTapInterval >= CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS) {
            } else if (powerTapInterval >= POWER_DOUBLE_TAP_MAX_TIME_MS) {
                // Tap too slow for shortcuts
                mFirstPowerDown  = event.getEventTime();
                mPowerButtonConsecutiveTaps = 1;
                mPowerButtonSlowConsecutiveTaps++;
            } else {
            } else if (!overridePowerKeyBehaviorInFocusedWindow() || powerTapInterval > 0) {
                // Fast consecutive tap
                mPowerButtonConsecutiveTaps++;
                mPowerButtonSlowConsecutiveTaps++;
@@ -586,10 +722,16 @@ public class GestureLauncherService extends SystemService {
                }
            }
            if (mCameraDoubleTapPowerEnabled
                    && powerTapInterval < CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS
                    && mPowerButtonConsecutiveTaps == CAMERA_POWER_TAP_COUNT_THRESHOLD) {
                    && powerTapInterval < POWER_DOUBLE_TAP_MAX_TIME_MS
                    && mPowerButtonConsecutiveTaps == DOUBLE_POWER_TAP_COUNT_THRESHOLD) {
                launchCamera = true;
                intercept = interactive;
            } else if (launchWalletOptionOnPowerDoubleTap()
                    && mWalletDoubleTapPowerEnabled
                    && powerTapInterval < POWER_DOUBLE_TAP_MAX_TIME_MS
                    && mPowerButtonConsecutiveTaps == DOUBLE_POWER_TAP_COUNT_THRESHOLD) {
                launchWallet = true;
                intercept = interactive;
            }
        }
        if (mPowerButtonConsecutiveTaps > 1 || mPowerButtonSlowConsecutiveTaps > 1) {
@@ -608,6 +750,10 @@ public class GestureLauncherService extends SystemService {
                        (int) powerTapInterval);
                mUiEventLogger.log(GestureLauncherEvent.GESTURE_CAMERA_DOUBLE_TAP_POWER);
            }
        } else if (launchWallet) {
            Slog.i(TAG, "Power button double tap gesture detected, launching wallet. Interval="
                    + powerTapInterval + "ms");
            launchWallet = sendGestureTargetActivityPendingIntent();
        } else if (launchEmergencyGesture) {
            Slog.i(TAG, "Emergency gesture detected, launching.");
            launchEmergencyGesture = handleEmergencyGesture();
@@ -623,11 +769,74 @@ public class GestureLauncherService extends SystemService {
                mPowerButtonSlowConsecutiveTaps);
        mMetricsLogger.histogram("power_double_tap_interval", (int) powerTapInterval);

        outLaunched.value = launchCamera || launchEmergencyGesture;
        outLaunched.value = launchCamera || launchEmergencyGesture || launchWallet;
        // Intercept power key event if the press is part of a gesture (camera, eGesture) and the
        // user has completed setup.
        return intercept && isUserSetupComplete();
    }

    /**
     * Fetches and sends gestureTargetActivityPendingIntent from QuickAccessWallet, which is a
     * specific activity that QuickAccessWalletService has defined to be launch on detection of the
     * power button gesture.
     */
    private boolean sendGestureTargetActivityPendingIntent() {
        boolean userSetupComplete = isUserSetupComplete();
        if (mQuickAccessWalletClient == null
                || !mQuickAccessWalletClient.isWalletServiceAvailable()) {
            Slog.w(TAG, "QuickAccessWalletService is not available, ignoring wallet gesture.");
            return false;
        }

        if (!userSetupComplete) {
            if (DBG) {
                Slog.d(TAG, "userSetupComplete = false, ignoring wallet gesture.");
            }
            return false;
        }
        if (DBG) {
            Slog.d(TAG, "userSetupComplete = true, performing wallet gesture.");
        }

        mQuickAccessWalletClient.getGestureTargetActivityPendingIntent(
                getContext().getMainExecutor(),
                gesturePendingIntent -> {
                    if (gesturePendingIntent == null) {
                        Slog.d(TAG, "getGestureTargetActivityPendingIntent is null.");
                        sendFallbackPendingIntent();
                        return;
                    }
                    sendPendingIntentWithBackgroundStartPrivileges(gesturePendingIntent);
                });
        return true;
    }

    /**
     * If gestureTargetActivityPendingIntent is null, this method is invoked to start the activity
     * that QuickAccessWalletService has defined to host the Wallet view, which is typically the
     * home screen of the Wallet application.
     */
    private void sendFallbackPendingIntent() {
        mQuickAccessWalletClient.getWalletPendingIntent(
                getContext().getMainExecutor(),
                walletPendingIntent -> {
                    if (walletPendingIntent == null) {
                        Slog.w(TAG, "getWalletPendingIntent returns null. Not launching "
                                + "anything for wallet.");
                        return;
                    }
                    sendPendingIntentWithBackgroundStartPrivileges(walletPendingIntent);
                });
    }

    private void sendPendingIntentWithBackgroundStartPrivileges(PendingIntent pendingIntent) {
        try {
            pendingIntent.send(GRANT_BACKGROUND_START_PRIVILEGES);
        } catch (PendingIntent.CanceledException e) {
            Slog.e(TAG, "PendingIntent was canceled", e);
        }
    }

    /**
     * @return true if camera was launched, false otherwise.
     */
@@ -700,7 +909,8 @@ public class GestureLauncherService extends SystemService {
                Settings.Secure.USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) != 0;
    }

    private final BroadcastReceiver mUserReceiver = new BroadcastReceiver() {
    private final BroadcastReceiver mUserReceiver =
            new BroadcastReceiver() {
                @Override
                public void onReceive(Context context, Intent intent) {
                    if (Intent.ACTION_USER_SWITCHED.equals(intent.getAction())) {
@@ -709,17 +919,24 @@ public class GestureLauncherService extends SystemService {
                        registerContentObservers();
                        updateCameraRegistered();
                        updateCameraDoubleTapPowerEnabled();
                        if (launchWalletOptionOnPowerDoubleTap()) {
                            updateWalletDoubleTapPowerEnabled();
                        }
                        updateEmergencyGestureEnabled();
                        updateEmergencyGesturePowerButtonCooldownPeriodMs();
                    }
                }
            };

    private final ContentObserver mSettingObserver = new ContentObserver(new Handler()) {
    private final ContentObserver mSettingObserver =
            new ContentObserver(new Handler()) {
                public void onChange(boolean selfChange, android.net.Uri uri, int userId) {
                    if (userId == mUserId) {
                        updateCameraRegistered();
                        updateCameraDoubleTapPowerEnabled();
                        if (launchWalletOptionOnPowerDoubleTap()) {
                            updateWalletDoubleTapPowerEnabled();
                        }
                        updateEmergencyGestureEnabled();
                        updateEmergencyGesturePowerButtonCooldownPeriodMs();
                    }
+228 −5

File changed.

Preview size limit exceeded, changes collapsed.

+3 −2
Original line number Diff line number Diff line
@@ -5750,9 +5750,10 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
                || mKeyInterceptionInfo.layoutParamsPrivateFlags != getAttrs().privateFlags
                || mKeyInterceptionInfo.layoutParamsType != getAttrs().type
                || mKeyInterceptionInfo.windowTitle != getWindowTag()
                || mKeyInterceptionInfo.windowOwnerUid != getOwningUid()) {
                || mKeyInterceptionInfo.windowOwnerUid != getOwningUid()
                || mKeyInterceptionInfo.inputFeaturesFlags != getAttrs().inputFeatures) {
            mKeyInterceptionInfo = new KeyInterceptionInfo(getAttrs().type, getAttrs().privateFlags,
                    getWindowTag().toString(), getOwningUid());
                    getWindowTag().toString(), getOwningUid(), getAttrs().inputFeatures);
        }
        return mKeyInterceptionInfo;
    }
+489 −71

File changed.

Preview size limit exceeded, changes collapsed.

Loading