Merge changes from topic "ohm-shortcut" into sc-dev
* changes: 3/ Listen ONE_HANDED_MODE_ACTIVATED for A11y shortcut action 2/ Implement Shortcut for One Handed mode feature
This commit is contained in:
@@ -80,6 +80,8 @@ public class AccessibilityShortcutController {
|
||||
"com.android.server.accessibility.MagnificationController";
|
||||
public static final ComponentName MAGNIFICATION_COMPONENT_NAME =
|
||||
new ComponentName("com.android.server.accessibility", "Magnification");
|
||||
public static final ComponentName ONE_HANDED_COMPONENT_NAME =
|
||||
new ComponentName("com.android.server.accessibility", "OneHandedMode");
|
||||
public static final ComponentName REDUCE_BRIGHT_COLORS_COMPONENT_NAME =
|
||||
new ComponentName("com.android.server.accessibility", "ReduceBrightColors");
|
||||
|
||||
@@ -117,7 +119,7 @@ public class AccessibilityShortcutController {
|
||||
public static Map<ComponentName, ToggleableFrameworkFeatureInfo>
|
||||
getFrameworkShortcutFeaturesMap() {
|
||||
if (sFrameworkShortcutFeaturesMap == null) {
|
||||
Map<ComponentName, ToggleableFrameworkFeatureInfo> featuresMap = new ArrayMap<>(2);
|
||||
Map<ComponentName, ToggleableFrameworkFeatureInfo> featuresMap = new ArrayMap<>(4);
|
||||
featuresMap.put(COLOR_INVERSION_COMPONENT_NAME,
|
||||
new ToggleableFrameworkFeatureInfo(
|
||||
Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED,
|
||||
@@ -128,6 +130,11 @@ public class AccessibilityShortcutController {
|
||||
Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED,
|
||||
"1" /* Value to enable */, "0" /* Value to disable */,
|
||||
R.string.color_correction_feature_name));
|
||||
featuresMap.put(ONE_HANDED_COMPONENT_NAME,
|
||||
new ToggleableFrameworkFeatureInfo(
|
||||
Settings.Secure.ONE_HANDED_MODE_ACTIVATED,
|
||||
"1" /* Value to enable */, "0" /* Value to disable */,
|
||||
R.string.one_handed_mode_feature_name));
|
||||
featuresMap.put(REDUCE_BRIGHT_COLORS_COMPONENT_NAME,
|
||||
new ToggleableFrameworkFeatureInfo(
|
||||
Settings.Secure.REDUCE_BRIGHT_COLORS_ACTIVATED,
|
||||
|
||||
@@ -21,6 +21,7 @@ import static android.view.accessibility.AccessibilityManager.ACCESSIBILITY_BUTT
|
||||
import static com.android.internal.accessibility.AccessibilityShortcutController.COLOR_INVERSION_COMPONENT_NAME;
|
||||
import static com.android.internal.accessibility.AccessibilityShortcutController.DALTONIZER_COMPONENT_NAME;
|
||||
import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_CONTROLLER_NAME;
|
||||
import static com.android.internal.accessibility.AccessibilityShortcutController.ONE_HANDED_COMPONENT_NAME;
|
||||
import static com.android.internal.accessibility.AccessibilityShortcutController.REDUCE_BRIGHT_COLORS_COMPONENT_NAME;
|
||||
import static com.android.internal.accessibility.util.AccessibilityUtils.getAccessibilityServiceFragmentType;
|
||||
import static com.android.internal.accessibility.util.ShortcutUtils.isShortcutContained;
|
||||
@@ -230,6 +231,16 @@ public final class AccessibilityTargetHelper {
|
||||
context.getDrawable(R.drawable.ic_accessibility_color_inversion),
|
||||
Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED);
|
||||
|
||||
final ToggleAllowListingFeatureTarget oneHandedMode =
|
||||
new ToggleAllowListingFeatureTarget(context,
|
||||
shortcutType,
|
||||
isShortcutContained(context, shortcutType,
|
||||
ONE_HANDED_COMPONENT_NAME.flattenToString()),
|
||||
ONE_HANDED_COMPONENT_NAME.flattenToString(),
|
||||
context.getString(R.string.one_handed_mode_feature_name),
|
||||
context.getDrawable(R.drawable.ic_accessibility_one_handed),
|
||||
Settings.Secure.ONE_HANDED_MODE_ACTIVATED);
|
||||
|
||||
final ToggleAllowListingFeatureTarget reduceBrightColors =
|
||||
new ToggleAllowListingFeatureTarget(context,
|
||||
shortcutType,
|
||||
@@ -243,6 +254,7 @@ public final class AccessibilityTargetHelper {
|
||||
targets.add(magnification);
|
||||
targets.add(daltonizer);
|
||||
targets.add(colorInversion);
|
||||
targets.add(oneHandedMode);
|
||||
targets.add(reduceBrightColors);
|
||||
|
||||
return targets;
|
||||
|
||||
25
core/res/res/drawable/ic_accessibility_one_handed.xml
Normal file
25
core/res/res/drawable/ic_accessibility_one_handed.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2021 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.
|
||||
-->
|
||||
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/accessibility_feature_background" />
|
||||
<foreground>
|
||||
<inset
|
||||
android:drawable="@drawable/ic_accessibility_one_handed_foreground"
|
||||
android:inset="@dimen/accessibility_icon_foreground_padding_ratio" />
|
||||
</foreground>
|
||||
</adaptive-icon>
|
||||
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2021 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.
|
||||
-->
|
||||
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="18dp"
|
||||
android:height="18dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
|
||||
<path android:fillColor="@android:color/white"
|
||||
android:pathData="M4.64169 3C3.88567 3 3.27271 3.61296 3.27271 4.36898V18.4011C3.27271 19.154 3.88875 19.7701 4.64169 19.7701H12.5339C12.5339 19.7701 12.5425 18.0588 11.2324 18.0588H6.01067C5.44597 18.0588 4.98393 17.5968 4.98393 17.0321V5.73797C4.98393 5.17326 5.44597 4.71123 6.01067 4.71123H15.9358C16.5005 4.71123 16.9625 5.17326 16.9625 5.73797V9.84492C16.9625 10.9651 16.4899 12.5952 15.5936 13.2674L9.77538 9.16043C8.58505 10.425 8.88177 11.705 10.1176 12.9251L13.1978 16.0053C13.1978 16.0053 13.3231 17.4572 13.5401 18.0588C14.2034 19.8984 16.2781 20.7968 16.2781 20.7968H19.231H19.2967C20.0835 20.7968 20.7273 20.153 20.7273 19.3662V12.2543L18.9441 4.06781C18.7662 3.23718 18.4068 3 17.8729 3H4.64169Z"/>
|
||||
</vector>
|
||||
@@ -4636,6 +4636,9 @@
|
||||
shown in the warning dialog about the accessibility shortcut. -->
|
||||
<string name="color_correction_feature_name">Color Correction</string>
|
||||
|
||||
<!-- Title of One Handed Mode feature, shown in the system gestures of the accessibility shortcut. [CHAR LIMIT=none] -->
|
||||
<string name="one_handed_mode_feature_name">One-Handed mode</string>
|
||||
|
||||
<!-- Title of Reduce Brightness feature, shown in the warning dialog about the accessibility shortcut. [CHAR LIMIT=none] -->
|
||||
<string name="reduce_bright_colors_feature_name">Extra dim</string>
|
||||
|
||||
|
||||
@@ -3410,9 +3410,12 @@
|
||||
<java-symbol type="drawable" name="ic_accessibility_color_correction" />
|
||||
<java-symbol type="drawable" name="ic_accessibility_magnification" />
|
||||
<java-symbol type="drawable" name="ic_accessibility_reduce_bright_colors" />
|
||||
<java-symbol type="drawable" name="ic_accessibility_one_handed" />
|
||||
|
||||
<java-symbol type="string" name="reduce_bright_colors_feature_name" />
|
||||
|
||||
<java-symbol type="string" name="one_handed_mode_feature_name" />
|
||||
|
||||
<!-- com.android.internal.widget.RecyclerView -->
|
||||
<java-symbol type="id" name="item_touch_helper_previous_elevation"/>
|
||||
<java-symbol type="dimen" name="item_touch_helper_max_drag_scroll_per_frame"/>
|
||||
|
||||
@@ -135,6 +135,7 @@ public class OneHandedController implements RemoteCallable<OneHandedController>
|
||||
}
|
||||
};
|
||||
|
||||
private final ContentObserver mActivatedObserver;
|
||||
private final ContentObserver mEnabledObserver;
|
||||
private final ContentObserver mTimeoutObserver;
|
||||
private final ContentObserver mTaskChangeExitObserver;
|
||||
@@ -170,11 +171,13 @@ public class OneHandedController implements RemoteCallable<OneHandedController>
|
||||
@Override
|
||||
public void onStartFinished(Rect bounds) {
|
||||
mState.setState(STATE_ACTIVE);
|
||||
notifyShortcutState(STATE_ACTIVE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopFinished(Rect bounds) {
|
||||
mState.setState(STATE_NONE);
|
||||
notifyShortcutState(STATE_NONE);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -287,6 +290,7 @@ public class OneHandedController implements RemoteCallable<OneHandedController>
|
||||
context.getContentResolver(), mUserId);
|
||||
mTimeoutHandler = timeoutHandler;
|
||||
|
||||
mActivatedObserver = getObserver(this::onActivatedActionChanged);
|
||||
mEnabledObserver = getObserver(this::onEnabledSettingChanged);
|
||||
mTimeoutObserver = getObserver(this::onTimeoutSettingChanged);
|
||||
mTaskChangeExitObserver = getObserver(this::onTaskChangeExitSettingChanged);
|
||||
@@ -347,6 +351,12 @@ public class OneHandedController implements RemoteCallable<OneHandedController>
|
||||
updateOneHandedEnabled();
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void notifyShortcutState(@OneHandedState.State int state) {
|
||||
mOneHandedSettingsUtil.setOneHandedModeActivated(
|
||||
mContext.getContentResolver(), state == STATE_ACTIVE ? 1 : 0, mUserId);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void startOneHanded() {
|
||||
if (isLockedDisabled()) {
|
||||
@@ -416,6 +426,9 @@ public class OneHandedController implements RemoteCallable<OneHandedController>
|
||||
}
|
||||
|
||||
private void registerSettingObservers(int newUserId) {
|
||||
mOneHandedSettingsUtil.registerSettingsKeyObserver(
|
||||
Settings.Secure.ONE_HANDED_MODE_ACTIVATED,
|
||||
mContext.getContentResolver(), mActivatedObserver, newUserId);
|
||||
mOneHandedSettingsUtil.registerSettingsKeyObserver(Settings.Secure.ONE_HANDED_MODE_ENABLED,
|
||||
mContext.getContentResolver(), mEnabledObserver, newUserId);
|
||||
mOneHandedSettingsUtil.registerSettingsKeyObserver(Settings.Secure.ONE_HANDED_MODE_TIMEOUT,
|
||||
@@ -465,6 +478,26 @@ public class OneHandedController implements RemoteCallable<OneHandedController>
|
||||
};
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void onActivatedActionChanged() {
|
||||
if (mState.isTransitioning() || !isOneHandedEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final boolean isActivated = mState.getState() == STATE_ACTIVE;
|
||||
final boolean requestActivated = mOneHandedSettingsUtil.getOneHandedModeActivated(
|
||||
mContext.getContentResolver(), mUserId);
|
||||
// When gesture trigger action, we will update settings and introduce observer callback
|
||||
// again, then the following logic will just ignore the second redundant callback.
|
||||
if (isActivated ^ requestActivated) {
|
||||
if (requestActivated) {
|
||||
startOneHanded();
|
||||
} else {
|
||||
stopOneHanded();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void onEnabledSettingChanged() {
|
||||
final boolean enabled = mOneHandedSettingsUtil.getSettingsOneHandedModeEnabled(
|
||||
@@ -544,6 +577,11 @@ public class OneHandedController implements RemoteCallable<OneHandedController>
|
||||
return mLockedDisabled;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
boolean isOneHandedEnabled() {
|
||||
return mIsOneHandedEnabled;
|
||||
}
|
||||
|
||||
private void updateOneHandedEnabled() {
|
||||
if (mState.getState() == STATE_ENTERING || mState.getState() == STATE_ACTIVE) {
|
||||
mMainExecutor.execute(() -> stopOneHanded());
|
||||
|
||||
@@ -131,8 +131,28 @@ public final class OneHandedSettingsUtil {
|
||||
* Returns whether swipe bottom to notification gesture enabled or not.
|
||||
*/
|
||||
public boolean getSettingsSwipeToNotificationEnabled(ContentResolver resolver, int userId) {
|
||||
return Settings.Secure.getInt(resolver,
|
||||
Settings.Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED, 0 /* Default OFF */) == 1;
|
||||
return Settings.Secure.getIntForUser(resolver,
|
||||
Settings.Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED, 0, userId) == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets one handed activated or not to notify state for shortcut
|
||||
*
|
||||
* @return activated or not
|
||||
*/
|
||||
public boolean getOneHandedModeActivated(ContentResolver resolver, int userId) {
|
||||
return Settings.Secure.getIntForUser(resolver,
|
||||
Settings.Secure.ONE_HANDED_MODE_ACTIVATED, 0, userId) == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets one handed activated or not to notify state for shortcut
|
||||
*
|
||||
* @return activated or not
|
||||
*/
|
||||
public boolean setOneHandedModeActivated(ContentResolver resolver, int state, int userId) {
|
||||
return Settings.Secure.putIntForUser(resolver,
|
||||
Settings.Secure.ONE_HANDED_MODE_ACTIVATED, state, userId);
|
||||
}
|
||||
|
||||
void dump(PrintWriter pw, String prefix, ContentResolver resolver,
|
||||
@@ -145,6 +165,8 @@ public final class OneHandedSettingsUtil {
|
||||
pw.println(getSettingsOneHandedModeTimeout(resolver, userId));
|
||||
pw.print(innerPrefix + "tapsAppToExit=");
|
||||
pw.println(getSettingsTapsAppToExit(resolver, userId));
|
||||
pw.print(innerPrefix + "shortcutActivated=");
|
||||
pw.println(getOneHandedModeActivated(resolver, userId));
|
||||
}
|
||||
|
||||
public OneHandedSettingsUtil() {
|
||||
|
||||
@@ -16,7 +16,9 @@
|
||||
|
||||
package com.android.wm.shell.onehanded;
|
||||
|
||||
import static com.android.wm.shell.onehanded.OneHandedState.STATE_ACTIVE;
|
||||
import static com.android.wm.shell.onehanded.OneHandedState.STATE_ENTERING;
|
||||
import static com.android.wm.shell.onehanded.OneHandedState.STATE_EXITING;
|
||||
import static com.android.wm.shell.onehanded.OneHandedState.STATE_NONE;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
@@ -360,4 +362,71 @@ public class OneHandedControllerTest extends OneHandedTestCase {
|
||||
|
||||
verify(mMockGestureHandler).onGestureEnabled(isOneHandedEnabled);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStateActive_shortcutRequestActivate_skipActions() {
|
||||
when(mSpiedTransitionState.getState()).thenReturn(STATE_ACTIVE);
|
||||
when(mSpiedTransitionState.isTransitioning()).thenReturn(false);
|
||||
when(mMockSettingsUitl.getOneHandedModeActivated(any(), anyInt())).thenReturn(true);
|
||||
mSpiedOneHandedController.onActivatedActionChanged();
|
||||
|
||||
verify(mSpiedOneHandedController, never()).startOneHanded();
|
||||
verify(mSpiedOneHandedController, never()).stopOneHanded();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStateNotActive_shortcutRequestInActivate_skipAction() {
|
||||
when(mSpiedTransitionState.getState()).thenReturn(STATE_NONE);
|
||||
when(mSpiedTransitionState.isTransitioning()).thenReturn(false);
|
||||
when(mMockSettingsUitl.getOneHandedModeActivated(any(), anyInt())).thenReturn(false);
|
||||
mSpiedOneHandedController.onActivatedActionChanged();
|
||||
|
||||
verify(mSpiedOneHandedController, never()).startOneHanded();
|
||||
verify(mSpiedOneHandedController, never()).stopOneHanded();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStateNotActive_shortcutRequestActivate_doAction() {
|
||||
when(mSpiedTransitionState.getState()).thenReturn(STATE_NONE);
|
||||
when(mSpiedTransitionState.isTransitioning()).thenReturn(false);
|
||||
when(mMockSettingsUitl.getOneHandedModeActivated(any(), anyInt())).thenReturn(true);
|
||||
mSpiedOneHandedController.onActivatedActionChanged();
|
||||
|
||||
verify(mSpiedOneHandedController).startOneHanded();
|
||||
verify(mSpiedOneHandedController, never()).stopOneHanded();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEnteringTransition_shortcutRequestActivate_skipActions() {
|
||||
when(mSpiedTransitionState.getState()).thenReturn(STATE_ENTERING);
|
||||
when(mSpiedTransitionState.isTransitioning()).thenReturn(true);
|
||||
when(mMockSettingsUitl.getOneHandedModeActivated(any(), anyInt())).thenReturn(true);
|
||||
mSpiedOneHandedController.onActivatedActionChanged();
|
||||
|
||||
verify(mSpiedOneHandedController, never()).startOneHanded();
|
||||
verify(mSpiedOneHandedController, never()).stopOneHanded();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExitingTransition_shortcutRequestActivate_skipActions() {
|
||||
when(mSpiedTransitionState.getState()).thenReturn(STATE_EXITING);
|
||||
when(mSpiedTransitionState.isTransitioning()).thenReturn(true);
|
||||
when(mMockSettingsUitl.getOneHandedModeActivated(any(), anyInt())).thenReturn(true);
|
||||
mSpiedOneHandedController.onActivatedActionChanged();
|
||||
|
||||
verify(mSpiedOneHandedController, never()).startOneHanded();
|
||||
verify(mSpiedOneHandedController, never()).stopOneHanded();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOneHandedDisabled_shortcutEnabled_skipActions() {
|
||||
when(mSpiedOneHandedController.isOneHandedEnabled()).thenReturn(false);
|
||||
when(mSpiedTransitionState.getState()).thenReturn(STATE_NONE);
|
||||
when(mSpiedTransitionState.isTransitioning()).thenReturn(false);
|
||||
when(mMockSettingsUitl.getOneHandedModeActivated(any(), anyInt())).thenReturn(true);
|
||||
mSpiedOneHandedController.onActivatedActionChanged();
|
||||
|
||||
verify(mSpiedOneHandedController, never()).startOneHanded();
|
||||
verify(mSpiedOneHandedController, never()).stopOneHanded();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user