From 93ef33655c53ccefd782b51f9743eee3fc0abb62 Mon Sep 17 00:00:00 2001 From: jasonwshsu Date: Fri, 12 Feb 2021 00:49:51 +0800 Subject: [PATCH 1/7] Setup basic layout and resources for the accessibility button settings page Bug: 173940869 Test: atest AccessibilityButtonFragmentTest Change-Id: I3f1d8b161d1baadeead36f49f18f00a91fd40b4c --- res/values/arrays.xml | 32 +++++++++++ res/values/strings.xml | 20 +++++++ res/xml/accessibility_button_settings.xml | 57 +++++++++++++++++++ res/xml/accessibility_shortcuts_settings.xml | 7 +++ .../AccessibilityButtonFragment.java | 55 ++++++++++++++++++ .../AccessibilityButtonFragmentTest.java | 50 ++++++++++++++++ 6 files changed, 221 insertions(+) create mode 100644 res/xml/accessibility_button_settings.xml create mode 100644 src/com/android/settings/accessibility/AccessibilityButtonFragment.java create mode 100644 tests/robotests/src/com/android/settings/accessibility/AccessibilityButtonFragmentTest.java diff --git a/res/values/arrays.xml b/res/values/arrays.xml index 183dd1e579d..2d03c11227e 100644 --- a/res/values/arrays.xml +++ b/res/values/arrays.xml @@ -966,6 +966,38 @@ -1 + + + Floating over other apps + Navigation bar + + + + + + + 1 + + 0 + + + + + Small + Large + Half Circle + + + + + + 0 + + 1 + + 2 + + diff --git a/res/values/strings.xml b/res/values/strings.xml index 107ca3897cd..4878825b1da 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -5123,6 +5123,26 @@ Shortcut from lock screen Allow feature shortcut to turn on from the lock screen. Hold both volume keys for a few seconds. + + Accessibility button + + Quickly access accessibility features + + Quickly access accessibility features from any screen. \n\nTo get started, go to accessibility settings and select a feature. Tap on the shortcut and select the accessibility button. + + Location + + Size + + Fade when not in use + + Fades after a few seconds so it\u2019s easier to see your screen + + Transparency when not in use + + Transparent + + Non-transparent High contrast text diff --git a/res/xml/accessibility_button_settings.xml b/res/xml/accessibility_button_settings.xml new file mode 100644 index 00000000000..7bb534f3fbb --- /dev/null +++ b/res/xml/accessibility_button_settings.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/res/xml/accessibility_shortcuts_settings.xml b/res/xml/accessibility_shortcuts_settings.xml index 35314e708bb..465f96d74df 100644 --- a/res/xml/accessibility_shortcuts_settings.xml +++ b/res/xml/accessibility_shortcuts_settings.xml @@ -21,6 +21,13 @@ android:persistent="false" android:title="@string/accessibility_shortcuts_settings_title"> + + niks = AccessibilityButtonFragment.SEARCH_INDEX_DATA_PROVIDER + .getNonIndexableKeys(mContext); + final List keys = + XmlTestUtils.getKeysFromPreferenceXml(mContext, + R.xml.accessibility_button_settings); + + assertThat(keys).containsAtLeastElementsIn(niks); + } +} From 123464429dbe0e677a4cb9118e436444bd575061 Mon Sep 17 00:00:00 2001 From: jasonwshsu Date: Wed, 17 Feb 2021 17:07:43 +0800 Subject: [PATCH 2/7] Add the preference controller to control accessibility button location preference Bug: 173940869 Test: atest AccessibilityButtonLocationPreferenceControllerTest Change-Id: I49a23b2eb4e07e79afcefc5a148c23b06396ec1c --- res/xml/accessibility_button_settings.xml | 3 +- ...ityButtonLocationPreferenceController.java | 89 +++++++++++++++ ...uttonLocationPreferenceControllerTest.java | 106 ++++++++++++++++++ 3 files changed, 197 insertions(+), 1 deletion(-) create mode 100644 src/com/android/settings/accessibility/AccessibilityButtonLocationPreferenceController.java create mode 100644 tests/robotests/src/com/android/settings/accessibility/AccessibilityButtonLocationPreferenceControllerTest.java diff --git a/res/xml/accessibility_button_settings.xml b/res/xml/accessibility_button_settings.xml index 7bb534f3fbb..2fa2e0d0938 100644 --- a/res/xml/accessibility_button_settings.xml +++ b/res/xml/accessibility_button_settings.xml @@ -25,7 +25,8 @@ android:key="accessibility_button_location" android:title="@string/accessibility_button_location_title" android:summary="%s" - android:persistent="false"/> + android:persistent="false" + settings:controller="com.android.settings.accessibility.AccessibilityButtonLocationPreferenceController"/> mValueTitleMap = new ArrayMap<>(); + private int mDefaultLocation; + + public AccessibilityButtonLocationPreferenceController(Context context, String preferenceKey) { + super(context, preferenceKey); + initValueTitleMap(); + } + + @Override + public int getAvailabilityStatus() { + return AccessibilityUtil.isGestureNavigateEnabled(mContext) + ? DISABLED_DEPENDENT_SETTING : AVAILABLE; + } + + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + final ListPreference listPreference = (ListPreference) preference; + final Integer value = Ints.tryParse((String) newValue); + if (value != null) { + Settings.Secure.putInt(mContext.getContentResolver(), + Settings.Secure.ACCESSIBILITY_BUTTON_MODE, value); + updateState(listPreference); + } + return true; + } + + @Override + public void updateState(Preference preference) { + super.updateState(preference); + final ListPreference listPreference = (ListPreference) preference; + + listPreference.setValue(getCurrentAccessibilityButtonMode()); + } + + private String getCurrentAccessibilityButtonMode() { + final int mode = Settings.Secure.getInt(mContext.getContentResolver(), + Settings.Secure.ACCESSIBILITY_BUTTON_MODE, mDefaultLocation); + return String.valueOf(mode); + } + + private void initValueTitleMap() { + if (mValueTitleMap.size() == 0) { + final String[] values = mContext.getResources().getStringArray( + R.array.accessibility_button_location_selector_values); + final String[] titles = mContext.getResources().getStringArray( + R.array.accessibility_button_location_selector_titles); + final int mapSize = values.length; + + mDefaultLocation = Integer.parseInt(values[0]); + for (int i = 0; i < mapSize; i++) { + mValueTitleMap.put(values[i], titles[i]); + } + } + } +} diff --git a/tests/robotests/src/com/android/settings/accessibility/AccessibilityButtonLocationPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/AccessibilityButtonLocationPreferenceControllerTest.java new file mode 100644 index 00000000000..a67038a6b2d --- /dev/null +++ b/tests/robotests/src/com/android/settings/accessibility/AccessibilityButtonLocationPreferenceControllerTest.java @@ -0,0 +1,106 @@ +/* + * 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. + */ + +package com.android.settings.accessibility; + +import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU; +import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR; +import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON; +import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL; + +import static com.android.settings.core.BasePreferenceController.AVAILABLE; +import static com.android.settings.core.BasePreferenceController.DISABLED_DEPENDENT_SETTING; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.when; + +import android.content.ContentResolver; +import android.content.Context; +import android.content.res.Resources; +import android.provider.Settings; + +import androidx.preference.ListPreference; +import androidx.test.core.app.ApplicationProvider; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Spy; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; +import org.robolectric.RobolectricTestRunner; + +/** Tests for {@link AccessibilityButtonLocationPreferenceController}. */ +@RunWith(RobolectricTestRunner.class) +public class AccessibilityButtonLocationPreferenceControllerTest { + + @Rule + public final MockitoRule mockito = MockitoJUnit.rule(); + + @Spy + private final Context mContext = ApplicationProvider.getApplicationContext(); + @Spy + private final Resources mResources = mContext.getResources(); + private final ContentResolver mContentResolver = mContext.getContentResolver(); + private final ListPreference mListPreference = new ListPreference(mContext); + private AccessibilityButtonLocationPreferenceController mController; + + + @Before + public void setUp() { + mController = new AccessibilityButtonLocationPreferenceController(mContext, + "test_key"); + when(mContext.getResources()).thenReturn(mResources); + } + + @Test + public void getAvailabilityStatus_navigationGestureEnabled_returnDisabledDependentSetting() { + when(mResources.getInteger(com.android.internal.R.integer.config_navBarInteractionMode)) + .thenReturn(NAV_BAR_MODE_GESTURAL); + + assertThat(mController.getAvailabilityStatus()).isEqualTo(DISABLED_DEPENDENT_SETTING); + } + + @Test + public void getAvailabilityStatus_navigationGestureDisabled_returnAvailable() { + when(mResources.getInteger(com.android.internal.R.integer.config_navBarInteractionMode)) + .thenReturn(NAV_BAR_MODE_2BUTTON); + + assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE); + } + + @Test + public void updateState_a11yBtnModeNavigationBar_navigationBarValue() { + Settings.Secure.putInt(mContentResolver, Settings.Secure.ACCESSIBILITY_BUTTON_MODE, + ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR); + + mController.updateState(mListPreference); + + final String navigationBarValue = String.valueOf(ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR); + assertThat(mListPreference.getValue()).isEqualTo(navigationBarValue); + } + + @Test + public void onPreferenceChange_a11yBtnModeFloatingMenu_floatingMenuValue() { + final String floatingMenuValue = String.valueOf(ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU); + + mController.onPreferenceChange(mListPreference, floatingMenuValue); + + assertThat(mListPreference.getValue()).isEqualTo(floatingMenuValue); + } +} From 04955b96aea80194ae979912f87eac1e1ec6a9d3 Mon Sep 17 00:00:00 2001 From: jasonwshsu Date: Thu, 18 Feb 2021 00:49:43 +0800 Subject: [PATCH 3/7] Add the preference controller to control accessibility button size preference Bug: 173940869 Test: atest FloatingMenuSizePreferenceControllerTest Change-Id: Ic206a940abde90641442df37a634c8cb3a345597 --- res/xml/accessibility_button_settings.xml | 3 +- .../accessibility/AccessibilityUtil.java | 8 + .../FloatingMenuSizePreferenceController.java | 199 ++++++++++++++++++ ...atingMenuSizePreferenceControllerTest.java | 145 +++++++++++++ 4 files changed, 354 insertions(+), 1 deletion(-) create mode 100644 src/com/android/settings/accessibility/FloatingMenuSizePreferenceController.java create mode 100644 tests/robotests/src/com/android/settings/accessibility/FloatingMenuSizePreferenceControllerTest.java diff --git a/res/xml/accessibility_button_settings.xml b/res/xml/accessibility_button_settings.xml index 2fa2e0d0938..e348b77ffb0 100644 --- a/res/xml/accessibility_button_settings.xml +++ b/res/xml/accessibility_button_settings.xml @@ -34,7 +34,8 @@ android:key="accessibility_button_size" android:title="@string/accessibility_button_size_title" android:summary="%s" - android:persistent="false"/> + android:persistent="false" + settings:controller="com.android.settings.accessibility.FloatingMenuSizePreferenceController"/> mValueTitleMap = new ArrayMap<>(); + private int mDefaultSize; + + @Retention(RetentionPolicy.SOURCE) + @IntDef({ + Size.SMALL, + Size.LARGE, + Size.EDGE + }) + @VisibleForTesting + @interface Size { + int SMALL = 0; + int LARGE = 1; + int EDGE = 2; + } + + @Retention(RetentionPolicy.SOURCE) + @IntDef({ + EdgeMode.FULL_CIRCLE, + EdgeMode.HALF_CIRCLE, + }) + @VisibleForTesting + @interface EdgeMode { + int FULL_CIRCLE = 0; + int HALF_CIRCLE = 1; + } + + public FloatingMenuSizePreferenceController(Context context, String preferenceKey) { + super(context, preferenceKey); + mContentResolver = context.getContentResolver(); + mContentObserver = new ContentObserver(new Handler(Looper.getMainLooper())) { + @Override + public void onChange(boolean selfChange) { + updateAvailabilityStatus(); + } + }; + + initValueTitleMap(); + } + + @Override + public int getAvailabilityStatus() { + return AccessibilityUtil.isFloatingMenuEnabled(mContext) + ? AVAILABLE : DISABLED_DEPENDENT_SETTING; + } + + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + + mPreference = screen.findPreference(getPreferenceKey()); + } + + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + final ListPreference listPreference = (ListPreference) preference; + final Integer value = Ints.tryParse((String) newValue); + if (value != null) { + writeToFloatingMenuSettings(value); + updateState(listPreference); + } + return true; + } + + @Override + public void updateState(Preference preference) { + super.updateState(preference); + final ListPreference listPreference = (ListPreference) preference; + + listPreference.setValue(getCurrentAccessibilityButtonSize()); + } + + @Override + public void onResume() { + mContentResolver.registerContentObserver( + Settings.Secure.getUriFor( + Settings.Secure.ACCESSIBILITY_BUTTON_MODE), /* notifyForDescendants= */ + false, mContentObserver); + + } + + @Override + public void onPause() { + mContentResolver.unregisterContentObserver(mContentObserver); + } + + private void updateAvailabilityStatus() { + mPreference.setEnabled(AccessibilityUtil.isFloatingMenuEnabled(mContext)); + } + + private void initValueTitleMap() { + if (mValueTitleMap.size() == 0) { + final String[] values = mContext.getResources().getStringArray( + R.array.accessibility_button_size_selector_values); + final String[] titles = mContext.getResources().getStringArray( + R.array.accessibility_button_size_selector_titles); + final int mapSize = values.length; + + mDefaultSize = Integer.parseInt(values[0]); + for (int i = 0; i < mapSize; i++) { + mValueTitleMap.put(values[i], titles[i]); + } + } + } + + private void writeToFloatingMenuSettings(@Size int sizeValue) { + if (sizeValue == Size.EDGE) { + putAccessibilityFloatingMenuSize(Size.SMALL); + putAccessibilityFloatingMenuIconType(EdgeMode.HALF_CIRCLE); + } else { + putAccessibilityFloatingMenuSize(sizeValue); + putAccessibilityFloatingMenuIconType(EdgeMode.FULL_CIRCLE); + } + } + + private String getCurrentAccessibilityButtonSize() { + final @EdgeMode int iconType = getAccessibilityFloatingMenuIconType(EdgeMode.FULL_CIRCLE); + final @Size int btnSize = getAccessibilityFloatingMenuSize(mDefaultSize); + + return (iconType == EdgeMode.HALF_CIRCLE) + ? String.valueOf(Size.EDGE) : String.valueOf(btnSize); + } + + @Size + private int getAccessibilityFloatingMenuSize(@Size int defaultValue) { + return Settings.Secure.getInt(mContentResolver, + Settings.Secure.ACCESSIBILITY_FLOATING_MENU_SIZE, defaultValue); + } + + private void putAccessibilityFloatingMenuSize(@Size int value) { + Settings.Secure.putInt(mContentResolver, + Settings.Secure.ACCESSIBILITY_FLOATING_MENU_SIZE, value); + } + + @EdgeMode + private int getAccessibilityFloatingMenuIconType(@EdgeMode int defaultValue) { + return Settings.Secure.getInt(mContentResolver, + Settings.Secure.ACCESSIBILITY_FLOATING_MENU_ICON_TYPE, defaultValue); + } + + private void putAccessibilityFloatingMenuIconType(@EdgeMode int value) { + Settings.Secure.putInt(mContentResolver, + Settings.Secure.ACCESSIBILITY_FLOATING_MENU_ICON_TYPE, value); + } +} diff --git a/tests/robotests/src/com/android/settings/accessibility/FloatingMenuSizePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/FloatingMenuSizePreferenceControllerTest.java new file mode 100644 index 00000000000..70257ca6931 --- /dev/null +++ b/tests/robotests/src/com/android/settings/accessibility/FloatingMenuSizePreferenceControllerTest.java @@ -0,0 +1,145 @@ +/* + * 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. + */ + +package com.android.settings.accessibility; + +import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU; +import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR; + +import static com.android.settings.core.BasePreferenceController.AVAILABLE; +import static com.android.settings.core.BasePreferenceController.DISABLED_DEPENDENT_SETTING; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.content.ContentResolver; +import android.content.Context; +import android.provider.Settings; + +import androidx.preference.ListPreference; +import androidx.test.core.app.ApplicationProvider; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Spy; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; +import org.robolectric.RobolectricTestRunner; + +/** Tests for {@link FloatingMenuSizePreferenceController}. */ +@RunWith(RobolectricTestRunner.class) +public class FloatingMenuSizePreferenceControllerTest { + + @Rule + public MockitoRule mocks = MockitoJUnit.rule(); + + @Spy + private final Context mContext = ApplicationProvider.getApplicationContext(); + @Mock + private ContentResolver mContentResolver; + private final ListPreference mListPreference = new ListPreference(mContext); + private FloatingMenuSizePreferenceController mController; + + @Before + public void setUp() { + when(mContext.getContentResolver()).thenReturn(mContentResolver); + mController = new FloatingMenuSizePreferenceController(mContext, "test_key"); + } + + @Test + public void getAvailabilityStatus_a11yBtnModeFloatingMenu_returnAvailable() { + Settings.Secure.putInt(mContentResolver, Settings.Secure.ACCESSIBILITY_BUTTON_MODE, + ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU); + + assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE); + } + + @Test + public void getAvailabilityStatus_a11yBtnModeNavigationBar_returnDisabledDependentSetting() { + Settings.Secure.putInt(mContentResolver, Settings.Secure.ACCESSIBILITY_BUTTON_MODE, + ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR); + + assertThat(mController.getAvailabilityStatus()).isEqualTo(DISABLED_DEPENDENT_SETTING); + } + + @Test + public void updateState_floatingMenuLargeSizeAndFullCircle_largeSizeValue() { + Settings.Secure.putInt(mContentResolver, Settings.Secure.ACCESSIBILITY_FLOATING_MENU_SIZE, + FloatingMenuSizePreferenceController.Size.LARGE); + Settings.Secure.putInt(mContentResolver, + Settings.Secure.ACCESSIBILITY_FLOATING_MENU_ICON_TYPE, + FloatingMenuSizePreferenceController.EdgeMode.FULL_CIRCLE); + + mController.updateState(mListPreference); + + final String largeSize = String.valueOf(FloatingMenuSizePreferenceController.Size.LARGE); + assertThat(mListPreference.getValue()).isEqualTo(largeSize); + } + + @Test + public void updateState_floatingMenuHalfCircle_edgeSizeValue() { + Settings.Secure.putInt(mContentResolver, + Settings.Secure.ACCESSIBILITY_FLOATING_MENU_ICON_TYPE, + FloatingMenuSizePreferenceController.EdgeMode.HALF_CIRCLE); + + mController.updateState(mListPreference); + + final String edgeSize = String.valueOf(FloatingMenuSizePreferenceController.Size.EDGE); + assertThat(mListPreference.getValue()).isEqualTo(edgeSize); + } + + @Test + public void onPreferenceChange_floatingMenuEdgeSize_edgeSizeValue() { + final String edgeSize = String.valueOf( + FloatingMenuSizePreferenceController.Size.EDGE); + + mController.onPreferenceChange(mListPreference, edgeSize); + + assertThat(mListPreference.getValue()).isEqualTo(edgeSize); + } + + @Test + public void onChange_a11yBtnModeChangeToNavigationBar_preferenceDisabled() { + mController.mPreference = mListPreference; + Settings.Secure.putInt(mContentResolver, Settings.Secure.ACCESSIBILITY_BUTTON_MODE, + ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR); + + mController.mContentObserver.onChange(false); + + assertThat(mController.mPreference.isEnabled()).isFalse(); + } + + @Test + public void onResume_registerSpecificContentObserver() { + mController.onResume(); + + verify(mContentResolver).registerContentObserver( + Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_BUTTON_MODE), false, + mController.mContentObserver); + } + + @Test + public void onPause_unregisterContentObserver() { + mController.onPause(); + + verify(mContentResolver).unregisterContentObserver(mController.mContentObserver); + } +} From c497c7aabeb004b5d1ace57a9cfe164f9ecfa597 Mon Sep 17 00:00:00 2001 From: jasonwshsu Date: Thu, 18 Feb 2021 03:29:26 +0800 Subject: [PATCH 4/7] Add the preference controller to control accessibility button opacity preference Bug: 173940869 Test: atest FloatingMenuOpacityPreferenceControllerTest Change-Id: I1fbe3157c93fef4611c3b9b13569c9b339e2898a --- res/xml/accessibility_button_settings.xml | 3 +- ...oatingMenuOpacityPreferenceController.java | 142 ++++++++++++++++++ ...ngMenuOpacityPreferenceControllerTest.java | 137 +++++++++++++++++ 3 files changed, 281 insertions(+), 1 deletion(-) create mode 100644 src/com/android/settings/accessibility/FloatingMenuOpacityPreferenceController.java create mode 100644 tests/robotests/src/com/android/settings/accessibility/FloatingMenuOpacityPreferenceControllerTest.java diff --git a/res/xml/accessibility_button_settings.xml b/res/xml/accessibility_button_settings.xml index e348b77ffb0..8d4631afbba 100644 --- a/res/xml/accessibility_button_settings.xml +++ b/res/xml/accessibility_button_settings.xml @@ -47,7 +47,8 @@ android:key="accessibility_button_opacity" android:title="@string/accessibility_button_opacity_title" android:selectable="true" - android:persistent="false"/> + android:persistent="false" + settings:controller="com.android.settings.accessibility.FloatingMenuOpacityPreferenceController"/> maxValue) ? DEFAULT_OPACITY : value; + } +} + diff --git a/tests/robotests/src/com/android/settings/accessibility/FloatingMenuOpacityPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/FloatingMenuOpacityPreferenceControllerTest.java new file mode 100644 index 00000000000..98ad00a8fda --- /dev/null +++ b/tests/robotests/src/com/android/settings/accessibility/FloatingMenuOpacityPreferenceControllerTest.java @@ -0,0 +1,137 @@ +/* + * 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. + */ + +package com.android.settings.accessibility; + +import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU; +import static android.provider.Settings.Secure.ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR; + +import static com.android.settings.accessibility.FloatingMenuOpacityPreferenceController.DEFAULT_OPACITY; +import static com.android.settings.accessibility.FloatingMenuOpacityPreferenceController.PRECISION; +import static com.android.settings.core.BasePreferenceController.AVAILABLE; +import static com.android.settings.core.BasePreferenceController.DISABLED_DEPENDENT_SETTING; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.content.ContentResolver; +import android.content.Context; +import android.provider.Settings; + +import androidx.test.core.app.ApplicationProvider; + +import com.android.settings.widget.SeekBarPreference; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Spy; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; +import org.robolectric.RobolectricTestRunner; + +/** Tests for {@link FloatingMenuOpacityPreferenceController}. */ +@RunWith(RobolectricTestRunner.class) +public class FloatingMenuOpacityPreferenceControllerTest { + + @Rule + public MockitoRule mocks = MockitoJUnit.rule(); + + @Spy + private final Context mContext = ApplicationProvider.getApplicationContext(); + @Mock + private ContentResolver mContentResolver; + private FloatingMenuOpacityPreferenceController mController; + + @Before + public void setUp() { + when(mContext.getContentResolver()).thenReturn(mContentResolver); + mController = new FloatingMenuOpacityPreferenceController(mContext, "test_key"); + } + + @Test + public void getAvailabilityStatus_a11yBtnModeFloatingMenu_returnAvailable() { + Settings.Secure.putInt(mContentResolver, Settings.Secure.ACCESSIBILITY_BUTTON_MODE, + ACCESSIBILITY_BUTTON_MODE_FLOATING_MENU); + + assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE); + } + + @Test + public void getAvailabilityStatus_a11yBtnModeNavigationBar_returnDisabledDependentSetting() { + Settings.Secure.putInt(mContentResolver, Settings.Secure.ACCESSIBILITY_BUTTON_MODE, + ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR); + + assertThat(mController.getAvailabilityStatus()).isEqualTo(DISABLED_DEPENDENT_SETTING); + } + + @Test + public void onChange_a11yBtnModeChangeToNavigationBar_preferenceDisabled() { + mController.mPreference = new SeekBarPreference(mContext); + Settings.Secure.putInt(mContentResolver, Settings.Secure.ACCESSIBILITY_BUTTON_MODE, + ACCESSIBILITY_BUTTON_MODE_NAVIGATION_BAR); + + mController.mContentObserver.onChange(false); + + assertThat(mController.mPreference.isEnabled()).isFalse(); + } + + @Test + public void getSliderPosition_putNormalOpacityValue_expectedValue() { + Settings.Secure.putFloat(mContext.getContentResolver(), + Settings.Secure.ACCESSIBILITY_FLOATING_MENU_OPACITY, 0.35f); + + assertThat(mController.getSliderPosition()).isEqualTo(35); + } + + @Test + public void getSliderPosition_putOutOfBoundOpacityValue_defaultValue() { + Settings.Secure.putFloat(mContext.getContentResolver(), + Settings.Secure.ACCESSIBILITY_FLOATING_MENU_OPACITY, 0.01f); + + final int defaultValue = Math.round(DEFAULT_OPACITY * PRECISION); + assertThat(mController.getSliderPosition()).isEqualTo(defaultValue); + } + + @Test + public void setSliderPosition_expectedValue() { + mController.setSliderPosition(27); + + final float value = Settings.Secure.getFloat(mContext.getContentResolver(), + Settings.Secure.ACCESSIBILITY_FLOATING_MENU_OPACITY, -1); + assertThat(value).isEqualTo(0.27f); + } + + @Test + public void onResume_registerSpecificContentObserver() { + mController.onResume(); + + verify(mContentResolver).registerContentObserver( + Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_BUTTON_MODE), false, + mController.mContentObserver); + } + + @Test + public void onPause_unregisterContentObserver() { + mController.onPause(); + + verify(mContentResolver).unregisterContentObserver(mController.mContentObserver); + } +} From 603014760fb6ceb4a66c805ebeef07918fba6652 Mon Sep 17 00:00:00 2001 From: jasonwshsu Date: Thu, 18 Feb 2021 04:01:01 +0800 Subject: [PATCH 5/7] Add the preference controller to control accessibility button preview preference * Create FloatingMenuLayerDrawable class to handle the preview layer drawable Bug: 173940869 Test: atest AccessibilityButtonPreviewPreferenceControllerTest FloatingMenuLayerDrawableTest Change-Id: Ia3d030547b377e87c505b2310f559f7f3876ecd5 --- .../accessibility_button_navigation.xml | 70 +++++++++ .../accessibility_button_preview_base.xml | 45 ++++++ ...ity_button_preview_large_floating_menu.xml | 41 ++++++ ...ity_button_preview_small_floating_menu.xml | 41 ++++++ res/layout/accessibility_button_preview.xml | 33 +++++ res/values/dimens.xml | 2 + res/xml/accessibility_button_settings.xml | 9 ++ ...lityButtonPreviewPreferenceController.java | 126 +++++++++++++++++ .../FloatingMenuLayerDrawable.java | 133 ++++++++++++++++++ ...ButtonPreviewPreferenceControllerTest.java | 120 ++++++++++++++++ .../FloatingMenuLayerDrawableTest.java | 73 ++++++++++ 11 files changed, 693 insertions(+) create mode 100644 res/drawable/accessibility_button_navigation.xml create mode 100644 res/drawable/accessibility_button_preview_base.xml create mode 100644 res/drawable/accessibility_button_preview_large_floating_menu.xml create mode 100644 res/drawable/accessibility_button_preview_small_floating_menu.xml create mode 100644 res/layout/accessibility_button_preview.xml create mode 100644 src/com/android/settings/accessibility/AccessibilityButtonPreviewPreferenceController.java create mode 100644 src/com/android/settings/accessibility/FloatingMenuLayerDrawable.java create mode 100644 tests/robotests/src/com/android/settings/accessibility/AccessibilityButtonPreviewPreferenceControllerTest.java create mode 100644 tests/robotests/src/com/android/settings/accessibility/FloatingMenuLayerDrawableTest.java diff --git a/res/drawable/accessibility_button_navigation.xml b/res/drawable/accessibility_button_navigation.xml new file mode 100644 index 00000000000..30273fb4e1f --- /dev/null +++ b/res/drawable/accessibility_button_navigation.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/res/drawable/accessibility_button_preview_base.xml b/res/drawable/accessibility_button_preview_base.xml new file mode 100644 index 00000000000..0712b9508b1 --- /dev/null +++ b/res/drawable/accessibility_button_preview_base.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/res/drawable/accessibility_button_preview_large_floating_menu.xml b/res/drawable/accessibility_button_preview_large_floating_menu.xml new file mode 100644 index 00000000000..e003dc7322c --- /dev/null +++ b/res/drawable/accessibility_button_preview_large_floating_menu.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/res/drawable/accessibility_button_preview_small_floating_menu.xml b/res/drawable/accessibility_button_preview_small_floating_menu.xml new file mode 100644 index 00000000000..3ff8e4b25f4 --- /dev/null +++ b/res/drawable/accessibility_button_preview_small_floating_menu.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/res/layout/accessibility_button_preview.xml b/res/layout/accessibility_button_preview.xml new file mode 100644 index 00000000000..07cb0ffb8ab --- /dev/null +++ b/res/layout/accessibility_button_preview.xml @@ -0,0 +1,33 @@ + + + + + + + \ No newline at end of file diff --git a/res/values/dimens.xml b/res/values/dimens.xml index 16db9088b53..79d54cf1d79 100755 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -57,6 +57,8 @@ 320dp + 200dp + 4dp diff --git a/res/xml/accessibility_button_settings.xml b/res/xml/accessibility_button_settings.xml index 8d4631afbba..fc91dcaeef6 100644 --- a/res/xml/accessibility_button_settings.xml +++ b/res/xml/accessibility_button_settings.xml @@ -19,6 +19,15 @@ xmlns:settings="http://schemas.android.com/apk/res-auto" android:title="@string/accessibility_button_title"> + + Date: Fri, 19 Feb 2021 16:44:57 +0800 Subject: [PATCH 6/7] Add the preference controller to control accessibility button fade preference * Opacity preference will be disabled when fade is disabled Bug: 173940869 Test: atest AccessibilityButtonFadePreferenceControllerTest AccessibilityButtonOactiyPreferenceControllerTest Change-Id: I1efd9760aa0287899cddd10ddd9a88a81ccc39ba --- res/xml/accessibility_button_settings.xml | 3 +- .../FloatingMenuFadePreferenceController.java | 116 ++++++++++++++++ ...oatingMenuOpacityPreferenceController.java | 12 +- ...atingMenuFadePreferenceControllerTest.java | 131 ++++++++++++++++++ ...ngMenuOpacityPreferenceControllerTest.java | 4 + 5 files changed, 263 insertions(+), 3 deletions(-) create mode 100644 src/com/android/settings/accessibility/FloatingMenuFadePreferenceController.java create mode 100644 tests/robotests/src/com/android/settings/accessibility/FloatingMenuFadePreferenceControllerTest.java diff --git a/res/xml/accessibility_button_settings.xml b/res/xml/accessibility_button_settings.xml index fc91dcaeef6..5e81616bffc 100644 --- a/res/xml/accessibility_button_settings.xml +++ b/res/xml/accessibility_button_settings.xml @@ -50,7 +50,8 @@ android:key="accessibility_button_fade" android:title="@string/accessibility_button_fade_title" android:summary="@string/accessibility_button_fade_summary" - android:persistent="false"/> + android:persistent="false" + settings:controller="com.android.settings.accessibility.FloatingMenuFadePreferenceController"/> Date: Thu, 18 Feb 2021 03:43:26 +0800 Subject: [PATCH 7/7] Add seekBar properties 'tickMark' to LabeledSeekBarPreference Bug: 173940869 Test: manual Change-Id: I135e52181bdb86ded6187a3fa30b9cffeb69d451 --- res/values/attrs.xml | 1 + .../settings/widget/LabeledSeekBarPreference.java | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/res/values/attrs.xml b/res/values/attrs.xml index f78120c7e78..bde52886e69 100644 --- a/res/values/attrs.xml +++ b/res/values/attrs.xml @@ -170,6 +170,7 @@ + diff --git a/src/com/android/settings/widget/LabeledSeekBarPreference.java b/src/com/android/settings/widget/LabeledSeekBarPreference.java index e2b2d686988..3a9ac18beb0 100644 --- a/src/com/android/settings/widget/LabeledSeekBarPreference.java +++ b/src/com/android/settings/widget/LabeledSeekBarPreference.java @@ -18,6 +18,7 @@ package com.android.settings.widget; import android.content.Context; import android.content.res.TypedArray; +import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.widget.SeekBar; import android.widget.TextView; @@ -32,6 +33,7 @@ public class LabeledSeekBarPreference extends SeekBarPreference { private final int mTextStartId; private final int mTextEndId; + private final int mTickMarkId; private OnPreferenceChangeListener mStopListener; public LabeledSeekBarPreference(Context context, AttributeSet attrs, int defStyleAttr, @@ -48,6 +50,8 @@ public class LabeledSeekBarPreference extends SeekBarPreference { mTextEndId = styledAttrs.getResourceId( R.styleable.LabeledSeekBarPreference_textEnd, R.string.summary_placeholder); + mTickMarkId = styledAttrs.getResourceId( + R.styleable.LabeledSeekBarPreference_tickMark, /* defValue= */ 0); styledAttrs.recycle(); } @@ -65,6 +69,13 @@ public class LabeledSeekBarPreference extends SeekBarPreference { final TextView endText = (TextView) holder.findViewById(android.R.id.text2); startText.setText(mTextStartId); endText.setText(mTextEndId); + + if (mTickMarkId != 0) { + final Drawable tickMark = getContext().getDrawable(mTickMarkId); + final SeekBar seekBar = (SeekBar) holder.findViewById( + com.android.internal.R.id.seekbar); + seekBar.setTickMark(tickMark); + } } public void setOnPreferenceChangeStopListener(OnPreferenceChangeListener listener) {