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

This commit is contained in:
TreeHugger Robot
2021-10-19 19:25:12 +00:00
committed by Android (Google) Code Review
6 changed files with 380 additions and 1 deletions

View File

@@ -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>

View File

@@ -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" />

View File

@@ -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:

View File

@@ -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;
}

View File

@@ -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();
}

View File

@@ -6609,5 +6609,33 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
mActivityInterceptorCallbacks.put(id, callback);
}
}
@Override
public ActivityManager.RecentTaskInfo getMostRecentTaskFromBackground() {
List<ActivityManager.RunningTaskInfo> runningTaskInfoList = getTasks(1);
ActivityManager.RunningTaskInfo runningTaskInfo;
if (runningTaskInfoList.size() > 0) {
runningTaskInfo = runningTaskInfoList.get(0);
} else {
Slog.i(TAG, "No running task found!");
return null;
}
// Get 2 most recent tasks.
List<ActivityManager.RecentTaskInfo> recentTaskInfoList =
getRecentTasks(
2,
ActivityManager.RECENT_IGNORE_UNAVAILABLE,
mContext.getUserId())
.getList();
ActivityManager.RecentTaskInfo targetTask = null;
for (ActivityManager.RecentTaskInfo info : recentTaskInfoList) {
// Find a recent task that is not the current running task on screen.
if (info.id != runningTaskInfo.id) {
targetTask = info;
break;
}
}
return targetTask;
}
}
}