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

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

Merge "Import wear stem primary button gesture to master."

parents 8bcdafd4 9c404e8f
Loading
Loading
Loading
Loading
+33 −0
Original line number Diff line number Diff line
@@ -1051,6 +1051,39 @@
    -->
    <integer name="config_shortPressOnSleepBehavior">0</integer>

    <!-- Control the behavior when the user long presses the stem primary button.
         Stem primary button is only used on watch form factor. If a device is not
         a watch, setting this config is no-op.
            0 - Nothing
            1 - Launch voice assistant
    -->
    <integer name="config_longPressOnStemPrimaryBehavior">0</integer>

    <!-- Control the behavior when the user double presses the stem primary button.
         Stem primary button is only used on watch form factor. If a device is not
         a watch, setting this config is no-op.
            0 - Nothing
            1 - Switch to the recent app
    -->
    <integer name="config_doublePressOnStemPrimaryBehavior">0</integer>

    <!-- Control the behavior when the user triple presses the stem primary button.
         Stem primary button is only used on watch form factor. If a device is not
         a watch, setting this config is no-op.
            0 - Nothing
            1 - Toggle accessibility
    -->
    <integer name="config_triplePressOnStemPrimaryBehavior">0</integer>

    <!-- Control the behavior when the user short presses the stem primary button.
        Stem primary button is only used on watch form factor. If a device is not
        a watch, setting this config is no-op.
           0 - Nothing
           1 - Go to launch all apps
    -->
    <integer name="config_shortPressOnStemPrimaryBehavior">0</integer>


    <!-- Time to wait while a button is pressed before triggering a very long press. -->
    <integer name="config_veryLongPressTimeout">3500</integer>

+4 −0
Original line number Diff line number Diff line
@@ -459,6 +459,10 @@
  <java-symbol type="integer" name="config_toastDefaultGravity" />
  <java-symbol type="integer" name="config_triplePressOnPowerBehavior" />
  <java-symbol type="integer" name="config_shortPressOnSleepBehavior" />
  <java-symbol type="integer" name="config_longPressOnStemPrimaryBehavior" />
  <java-symbol type="integer" name="config_shortPressOnStemPrimaryBehavior" />
  <java-symbol type="integer" name="config_doublePressOnStemPrimaryBehavior" />
  <java-symbol type="integer" name="config_triplePressOnStemPrimaryBehavior" />
  <java-symbol type="integer" name="config_windowOutsetBottom" />
  <java-symbol type="integer" name="db_connection_pool_size" />
  <java-symbol type="integer" name="db_journal_size_limit" />
+306 −0
Original line number Diff line number Diff line
@@ -93,8 +93,10 @@ import static com.android.server.wm.WindowManagerPolicyProto.ROTATION_MODE;
import static com.android.server.wm.WindowManagerPolicyProto.SCREEN_ON_FULLY;
import static com.android.server.wm.WindowManagerPolicyProto.WINDOW_MANAGER_DRAW_COMPLETE;

import android.accessibilityservice.AccessibilityServiceInfo;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityManager.RecentTaskInfo;
import android.app.ActivityManagerInternal;
import android.app.ActivityTaskManager;
import android.app.AppOpsManager;
@@ -105,6 +107,7 @@ import android.app.SearchManager;
import android.app.UiModeManager;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
@@ -113,6 +116,7 @@ import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.res.CompatibilityInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
@@ -191,6 +195,7 @@ import android.view.autofill.AutofillManagerInternal;

import com.android.internal.R;
import com.android.internal.accessibility.AccessibilityShortcutController;
import com.android.internal.accessibility.util.AccessibilityUtils;
import com.android.internal.app.AssistUtils;
import com.android.internal.inputmethod.SoftInputShowHideReason;
import com.android.internal.logging.MetricsLogger;
@@ -230,6 +235,7 @@ import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * WindowManagerPolicy implementation for the Android phone UI.  This
@@ -308,6 +314,22 @@ public class PhoneWindowManager implements WindowManagerPolicy {

    static final int PENDING_KEY_NULL = -1;

    // Must match: config_shortPressOnStemPrimaryBehavior in config.xml
    static final int SHORT_PRESS_PRIMARY_NOTHING = 0;
    static final int SHORT_PRESS_PRIMARY_LAUNCH_ALL_APPS = 1;

    // Must match: config_longPressOnStemPrimaryBehavior in config.xml
    static final int LONG_PRESS_PRIMARY_NOTHING = 0;
    static final int LONG_PRESS_PRIMARY_LAUNCH_VOICE_ASSISTANT = 1;

    // Must match: config_doublePressOnStemPrimaryBehavior in config.xml
    static final int DOUBLE_PRESS_PRIMARY_NOTHING = 0;
    static final int DOUBLE_PRESS_PRIMARY_SWITCH_RECENT_APP = 1;

    // Must match: config_triplePressOnStemPrimaryBehavior in config.xml
    static final int TRIPLE_PRESS_PRIMARY_NOTHING = 0;
    static final int TRIPLE_PRESS_PRIMARY_TOGGLE_ACCESSIBILITY = 1;

    static public final String SYSTEM_DIALOG_REASON_KEY = "reason";
    static public final String SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS = "globalactions";
    static public final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
@@ -315,6 +337,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
    static public final String SYSTEM_DIALOG_REASON_ASSIST = "assist";
    static public final String SYSTEM_DIALOG_REASON_SCREENSHOT = "screenshot";

    private static final String TALKBACK_LABEL = "TalkBack";

    private static final int POWER_BUTTON_SUPPRESSION_DELAY_DEFAULT_MILLIS = 800;
    private static final AudioAttributes VIBRATION_ATTRIBUTES = new AudioAttributes.Builder()
            .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
@@ -487,6 +511,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
    int mShortPressOnSleepBehavior;
    int mShortPressOnWindowBehavior;
    int mPowerVolUpBehavior;
    int mShortPressOnStemPrimaryBehavior;
    int mDoublePressOnStemPrimaryBehavior;
    int mTriplePressOnStemPrimaryBehavior;
    int mLongPressOnStemPrimaryBehavior;
    boolean mHasSoftInput = false;
    boolean mHapticTextHandleEnabled;
    boolean mUseTvRouting;
@@ -1192,6 +1220,170 @@ public class PhoneWindowManager implements WindowManagerPolicy {
        return mLongPressOnPowerBehavior;
    }

    private void stemPrimaryPress(int count) {
        if (DEBUG_INPUT) {
            Slog.d(TAG, "stemPrimaryPress: " + count);
        }
        if (count == 3) {
            stemPrimaryTriplePressAction(mTriplePressOnStemPrimaryBehavior);
        } else if (count == 2) {
            stemPrimaryDoublePressAction(mDoublePressOnStemPrimaryBehavior);
        } else if (count == 1) {
            stemPrimarySinglePressAction(mShortPressOnStemPrimaryBehavior);
        }
    }

    private void stemPrimarySinglePressAction(int behavior) {
        switch (behavior) {
            case SHORT_PRESS_PRIMARY_NOTHING:
                break;
            case SHORT_PRESS_PRIMARY_LAUNCH_ALL_APPS:
                if (DEBUG_INPUT) {
                    Slog.d(TAG, "Executing stem primary short press action behavior.");
                }
                final boolean keyguardActive =
                        mKeyguardDelegate != null && mKeyguardDelegate.isShowing();
                if (!keyguardActive) {
                    Intent intent = new Intent(Intent.ACTION_ALL_APPS);
                    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                            | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
                    startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
                }
                break;
        }
    }

    private void stemPrimaryDoublePressAction(int behavior) {
        switch (behavior) {
            case DOUBLE_PRESS_PRIMARY_NOTHING:
                break;
            case DOUBLE_PRESS_PRIMARY_SWITCH_RECENT_APP:
                if (DEBUG_INPUT) {
                    Slog.d(TAG, "Executing stem primary double press action behavior.");
                }
                final boolean keyguardActive = mKeyguardDelegate == null
                        ? false
                        : mKeyguardDelegate.isShowing();
                if (!keyguardActive) {
                    switchRecentTask();
                }
                break;
        }
    }

    private void stemPrimaryTriplePressAction(int behavior) {
        switch (behavior) {
            case TRIPLE_PRESS_PRIMARY_NOTHING:
                break;
            case TRIPLE_PRESS_PRIMARY_TOGGLE_ACCESSIBILITY:
                if (DEBUG_INPUT) {
                    Slog.d(TAG, "Executing stem primary triple press action behavior.");
                }
                toggleTalkBack();
                break;
        }
    }

    private void stemPrimaryLongPress() {
        if (DEBUG_INPUT) {
            Slog.d(TAG, "Executing stem primary long press action behavior.");
        }

        switch (mLongPressOnStemPrimaryBehavior) {
            case LONG_PRESS_PRIMARY_NOTHING:
                break;
            case LONG_PRESS_PRIMARY_LAUNCH_VOICE_ASSISTANT:
                launchVoiceAssist(/* allowDuringSetup= */false);
                break;
        }
    }

    private void toggleTalkBack() {
        final ComponentName componentName = getTalkbackComponent();
        if (componentName == null) {
            return;
        }

        final Set<ComponentName> enabledServices =
                AccessibilityUtils.getEnabledServicesFromSettings(mContext, mCurrentUserId);

        AccessibilityUtils.setAccessibilityServiceState(mContext, componentName,
                !enabledServices.contains(componentName));
    }

    private ComponentName getTalkbackComponent() {
        AccessibilityManager accessibilityManager = mContext.getSystemService(
                AccessibilityManager.class);
        List<AccessibilityServiceInfo> serviceInfos =
                accessibilityManager.getInstalledAccessibilityServiceList();

        for (AccessibilityServiceInfo service : serviceInfos) {
            final ServiceInfo serviceInfo = service.getResolveInfo().serviceInfo;
            if (isTalkback(serviceInfo)) {
                return new ComponentName(serviceInfo.packageName, serviceInfo.name);
            }
        }
        return null;
    }

    private boolean isTalkback(ServiceInfo info) {
        String label = info.loadLabel(mPackageManager).toString();
        return label.equals(TALKBACK_LABEL);
    }

    /**
     * Load most recent task (expect current task) and bring it to the front.
     */
    private void switchRecentTask() {
        RecentTaskInfo targetTask = mActivityTaskManagerInternal.getMostRecentTaskFromBackground();
        if (targetTask == null) {
            if (DEBUG_INPUT) {
                Slog.w(TAG, "No recent task available! Show watch face.");
            }
            goHome();
            return;
        }

        if (DEBUG_INPUT) {
            Slog.d(
                    TAG,
                    "Starting task from recents. id="
                            + targetTask.id
                            + ", persistentId="
                            + targetTask.persistentId
                            + ", topActivity="
                            + targetTask.topActivity
                            + ", baseIntent="
                            + targetTask.baseIntent);
        }
        try {
            ActivityManager.getService().startActivityFromRecents(targetTask.persistentId, null);
        } catch (RemoteException e) {
            Slog.e(TAG, "Failed to start task " + targetTask.persistentId + " from recents", e);
        }
    }

    private int getMaxMultiPressStemPrimaryCount() {
        switch (mTriplePressOnStemPrimaryBehavior) {
            case TRIPLE_PRESS_PRIMARY_NOTHING:
                break;
            case TRIPLE_PRESS_PRIMARY_TOGGLE_ACCESSIBILITY:
                if (Settings.System.getIntForUser(
                                mContext.getContentResolver(),
                                Settings.System.WEAR_ACCESSIBILITY_GESTURE_ENABLED,
                                /* def= */ 0,
                                UserHandle.USER_CURRENT)
                        == 1) {
                    return 3;
                }
                break;
        }
        if (mDoublePressOnStemPrimaryBehavior != DOUBLE_PRESS_PRIMARY_NOTHING) {
            return 2;
        }
        return 1;
    }

    private boolean hasLongPressOnPowerBehavior() {
        return getResolvedLongPressOnPowerBehavior() != LONG_PRESS_POWER_NOTHING;
    }
@@ -1204,6 +1396,16 @@ public class PhoneWindowManager implements WindowManagerPolicy {
        return mLongPressOnBackBehavior != LONG_PRESS_BACK_NOTHING;
    }

    private boolean hasLongPressOnStemPrimaryBehavior() {
        return mLongPressOnStemPrimaryBehavior != LONG_PRESS_PRIMARY_NOTHING;
    }

    private boolean hasStemPrimaryBehavior() {
        return getMaxMultiPressStemPrimaryCount() > 1
                || hasLongPressOnStemPrimaryBehavior()
                || mShortPressOnStemPrimaryBehavior != SHORT_PRESS_PRIMARY_NOTHING;
    }

    private void interceptScreenshotChord() {
        mHandler.removeCallbacks(mScreenshotRunnable);
        mScreenshotRunnable.setScreenshotType(TAKE_SCREENSHOT_FULLSCREEN);
@@ -2037,6 +2239,35 @@ public class PhoneWindowManager implements WindowManagerPolicy {
        }
    }

    /**
     * Rule for single stem primary key gesture.
     */
    private final class StemPrimaryKeyRule extends SingleKeyGestureDetector.SingleKeyRule {
        StemPrimaryKeyRule(int gestures) {
            super(mContext, KeyEvent.KEYCODE_STEM_PRIMARY, gestures);
        }

        @Override
        int getMaxMultiPressCount() {
            return getMaxMultiPressStemPrimaryCount();
        }

        @Override
        void onPress(long downTime) {
            stemPrimaryPress(1 /*count*/);
        }

        @Override
        void onLongPress(long eventTime) {
            stemPrimaryLongPress();
        }

        @Override
        void onMultiPress(long downTime, int count) {
            stemPrimaryPress(count);
        }
    }

    private void initSingleKeyGestureRules() {
        mSingleKeyGestureDetector = new SingleKeyGestureDetector();

@@ -2052,6 +2283,13 @@ public class PhoneWindowManager implements WindowManagerPolicy {
        if (hasLongPressOnBackBehavior()) {
            mSingleKeyGestureDetector.addRule(new BackKeyRule(KEY_LONGPRESS));
        }
        if (hasStemPrimaryBehavior()) {
            int stemPrimaryKeyGestures = 0;
            if (hasLongPressOnStemPrimaryBehavior()) {
                stemPrimaryKeyGestures |= KEY_LONGPRESS;
            }
            mSingleKeyGestureDetector.addRule(new StemPrimaryKeyRule(stemPrimaryKeyGestures));
        }
    }

    /**
@@ -2080,6 +2318,14 @@ public class PhoneWindowManager implements WindowManagerPolicy {
        if (mPackageManager.hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)) {
            mShortPressOnWindowBehavior = SHORT_PRESS_WINDOW_PICTURE_IN_PICTURE;
        }
        mShortPressOnStemPrimaryBehavior = mContext.getResources().getInteger(
                com.android.internal.R.integer.config_shortPressOnStemPrimaryBehavior);
        mLongPressOnStemPrimaryBehavior = mContext.getResources().getInteger(
                com.android.internal.R.integer.config_longPressOnStemPrimaryBehavior);
        mDoublePressOnStemPrimaryBehavior = mContext.getResources().getInteger(
                com.android.internal.R.integer.config_doublePressOnStemPrimaryBehavior);
        mTriplePressOnStemPrimaryBehavior = mContext.getResources().getInteger(
                com.android.internal.R.integer.config_triplePressOnStemPrimaryBehavior);
    }

    public void updateSettings() {
@@ -5380,6 +5626,22 @@ public class PhoneWindowManager implements WindowManagerPolicy {
        pw.print(prefix);
                pw.print("mShortPressOnWindowBehavior=");
                pw.println(shortPressOnWindowBehaviorToString(mShortPressOnWindowBehavior));
        pw.print(prefix);
                pw.print("mShortPressOnStemPrimaryBehavior=");
                pw.println(shortPressOnStemPrimaryBehaviorToString(
                    mShortPressOnStemPrimaryBehavior));
        pw.print(prefix);
                pw.print("mDoublePressOnStemPrimaryBehavior=");
                pw.println(doublePressOnStemPrimaryBehaviorToString(
                    mDoublePressOnStemPrimaryBehavior));
        pw.print(prefix);
                pw.print("mTriplePressOnStemPrimaryBehavior=");
                pw.println(triplePressOnStemPrimaryBehaviorToString(
                    mTriplePressOnStemPrimaryBehavior));
        pw.print(prefix);
                pw.print("mLongPressOnStemPrimaryBehavior=");
                pw.println(longPressOnStemPrimaryBehaviorToString(
                    mLongPressOnStemPrimaryBehavior));
        pw.print(prefix);
                pw.print("mAllowStartActivityForLongPressOnPowerDuringSetup=");
                pw.println(mAllowStartActivityForLongPressOnPowerDuringSetup);
@@ -5596,6 +5858,50 @@ public class PhoneWindowManager implements WindowManagerPolicy {
        }
    }

    private static String shortPressOnStemPrimaryBehaviorToString(int behavior) {
        switch (behavior) {
            case SHORT_PRESS_PRIMARY_NOTHING:
                return "SHORT_PRESS_PRIMARY_NOTHING";
            case SHORT_PRESS_PRIMARY_LAUNCH_ALL_APPS:
                return "SHORT_PRESS_PRIMARY_LAUNCH_ALL_APPS";
            default:
                return Integer.toString(behavior);
        }
    }

    private static String doublePressOnStemPrimaryBehaviorToString(int behavior) {
        switch (behavior) {
            case DOUBLE_PRESS_PRIMARY_NOTHING:
                return "DOUBLE_PRESS_PRIMARY_NOTHING";
            case DOUBLE_PRESS_PRIMARY_SWITCH_RECENT_APP:
                return "DOUBLE_PRESS_PRIMARY_SWITCH_RECENT_APP";
            default:
                return Integer.toString(behavior);
        }
    }

    private static String triplePressOnStemPrimaryBehaviorToString(int behavior) {
        switch (behavior) {
            case TRIPLE_PRESS_PRIMARY_NOTHING:
                return "TRIPLE_PRESS_PRIMARY_NOTHING";
            case TRIPLE_PRESS_PRIMARY_TOGGLE_ACCESSIBILITY:
                return "TRIPLE_PRESS_PRIMARY_TOGGLE_ACCESSIBILITY";
            default:
                return Integer.toString(behavior);
        }
    }

    private static String longPressOnStemPrimaryBehaviorToString(int behavior) {
        switch (behavior) {
            case LONG_PRESS_PRIMARY_NOTHING:
                return "LONG_PRESS_PRIMARY_NOTHING";
            case LONG_PRESS_PRIMARY_LAUNCH_VOICE_ASSISTANT:
                return "LONG_PRESS_PRIMARY_LAUNCH_VOICE_ASSISTANT";
            default:
                return Integer.toString(behavior);
        }
    }

    private static String lidBehaviorToString(int behavior) {
        switch (behavior) {
            case LID_BEHAVIOR_LOCK:
+5 −1
Original line number Diff line number Diff line
@@ -53,6 +53,7 @@ public final class SingleKeyGestureDetector {
    // Key code of current key down event, reset when key up.
    private int mDownKeyCode = KeyEvent.KEYCODE_UNKNOWN;
    private volatile boolean mHandledByLongPress = false;
    private volatile boolean mHandledByMultiPress = false;
    private final Handler mHandler;
    private long mLastDownTime = 0;
    private static final long MULTI_PRESS_TIMEOUT = ViewConfiguration.getMultiPressTimeout();
@@ -271,6 +272,7 @@ public final class SingleKeyGestureDetector {
                        mKeyPressCounter + 1, mActiveRule);
                msg.setAsynchronous(true);
                mHandler.sendMessage(msg);
                mHandledByMultiPress = true;
                mKeyPressCounter = 0;
            }
        }
@@ -284,8 +286,9 @@ public final class SingleKeyGestureDetector {
            return false;
        }

        if (mHandledByLongPress) {
        if (mHandledByLongPress || mHandledByMultiPress) {
            mHandledByLongPress = false;
            mHandledByMultiPress = false;
            mKeyPressCounter = 0;
            return true;
        }
@@ -339,6 +342,7 @@ public final class SingleKeyGestureDetector {
        }

        mHandledByLongPress = false;
        mHandledByMultiPress = false;
        mDownKeyCode = KeyEvent.KEYCODE_UNKNOWN;
    }

+4 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.server.wm;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.AppProtoEnums;
import android.app.IActivityManager;
import android.app.IApplicationThread;
@@ -688,4 +689,7 @@ public abstract class ActivityTaskManagerInternal {
    public abstract void registerActivityStartInterceptor(
            @ActivityInterceptorCallback.OrderedId int id,
            ActivityInterceptorCallback callback);

    /** Get the most recent task excluding the first running task (the one on the front most). */
    public abstract ActivityManager.RecentTaskInfo getMostRecentTaskFromBackground();
}
Loading