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

Commit 37dc0a68 authored by Charles Wang's avatar Charles Wang
Browse files

Revert^2 "Launch wallet app on double tap option."

bf5db735
Bug: 382133936
Test: android.platform.test.scenario.sysui.power.PowerMenuTest#testPower_verifySystemPowerMenuAppears

Change-Id: I1aebd5ab6d4da314a9bd043deaf131b5fae62d3e
parent d6efa30e
Loading
Loading
Loading
Loading
+217 −43
Original line number Diff line number Diff line
@@ -16,10 +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;
@@ -34,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;
@@ -42,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;
@@ -71,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;


    /**
@@ -101,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.
     */
    public 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();
@@ -159,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
     */
@@ -205,16 +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
    public GestureLauncherService(
            Context context,
            MetricsLogger metricsLogger,
            QuickAccessWalletClient quickAccessWalletClient,
            UiEventLogger uiEventLogger) {
        super(context);
        mContext = context;
        mQuickAccessWalletClient = quickAccessWalletClient;
        mMetricsLogger = metricsLogger;
        mUiEventLogger = uiEventLogger;
    }
@@ -240,6 +270,9 @@ public class GestureLauncherService extends SystemService {
                    "GestureLauncherService");
            updateCameraRegistered();
            updateCameraDoubleTapPowerEnabled();
            if (launchWalletOptionOnPowerDoubleTap()) {
                updateWalletDoubleTapPowerEnabled();
            }
            updateEmergencyGestureEnabled();
            updateEmergencyGesturePowerButtonCooldownPeriodMs();

@@ -294,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);
@@ -421,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())
@@ -444,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
@@ -497,10 +583,16 @@ 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;
    }

    /**
@@ -530,7 +622,7 @@ 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;
@@ -573,6 +665,7 @@ public class GestureLauncherService extends SystemService {
            return false;
        }
        boolean launchCamera = false;
        boolean launchWallet = false;
        boolean launchEmergencyGesture = false;
        boolean intercept = false;
        long powerTapInterval;
@@ -584,7 +677,7 @@ 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;
@@ -629,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) {
@@ -651,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();
@@ -666,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.
     */
@@ -743,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())) {
@@ -752,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();
                    }
+3 −3
Original line number Diff line number Diff line
@@ -91,7 +91,7 @@ import static com.android.hardware.input.Flags.modifierShortcutDump;
import static com.android.hardware.input.Flags.overridePowerKeyBehaviorInFocusedWindow;
import static com.android.hardware.input.Flags.useKeyGestureEventHandler;
import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.SCREENSHOT_KEYCHORD_DELAY;
import static com.android.server.GestureLauncherService.CAMERA_POWER_TAP_COUNT_THRESHOLD;
import static com.android.server.GestureLauncherService.DOUBLE_POWER_TAP_COUNT_THRESHOLD;
import static com.android.server.flags.Flags.modifierShortcutManagerMultiuser;
import static com.android.server.flags.Flags.newBugreportKeyboardShortcut;
import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVERED;
@@ -4150,7 +4150,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
        }

        // Intercept keys (don't send to app) for 3x, 4x, 5x gestures)
        if (mPowerButtonConsecutiveTaps > CAMERA_POWER_TAP_COUNT_THRESHOLD) {
        if (mPowerButtonConsecutiveTaps > DOUBLE_POWER_TAP_COUNT_THRESHOLD) {
            setDeferredKeyActionsExecutableAsync(KEYCODE_POWER, event.getDownTime());
            return true;
        }
@@ -5954,7 +5954,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
        }

        return powerTapInterval < POWER_MULTI_PRESS_TIMEOUT_MILLIS
                && mPowerButtonConsecutiveTaps == CAMERA_POWER_TAP_COUNT_THRESHOLD;
                && mPowerButtonConsecutiveTaps == DOUBLE_POWER_TAP_COUNT_THRESHOLD;
    }

    // The camera gesture will be detected by GestureLauncherService.
+423 −74

File changed.

Preview size limit exceeded, changes collapsed.

+1 −1
Original line number Diff line number Diff line
@@ -278,7 +278,7 @@ class TestPhoneWindowManager {
        mHandler = new Handler(mTestLooper.getLooper());
        mContext = mockingDetails(context).isSpy() ? context : spy(context);
        mGestureLauncherService = spy(new GestureLauncherService(mContext, mMetricsLogger,
                mUiEventLogger));
                mQuickAccessWalletClient, mUiEventLogger));
        setUp(supportSettingsUpdate);
        mTestLooper.dispatchAll();
    }