From 620755c29380524d7b335048d5a9d15d47dc700c Mon Sep 17 00:00:00 2001 From: Pat Manning Date: Thu, 7 Mar 2024 16:41:47 +0000 Subject: [PATCH] Add Settings for vector-specific PointerIcon stroke colors. Bug: 305193969 Test: PointerIconLoadingTest Flag: android.view.flags.enable_vector_cursor_a11y_settings Change-Id: I72213e8806fed451a0edb16d497406ffae5c1a44 --- .../pointer_icon_stroke_style_layout.xml | 60 ++++++++++++ res/values/dimens.xml | 1 + res/values/strings.xml | 8 ++ res/xml/trackpad_settings.xml | 6 ++ .../PointerStrokeStylePreference.java | 75 +++++++++++++++ ...ointerStrokeStylePreferenceController.java | 67 ++++++++++++++ ...erStrokeStylePreferenceControllerTest.java | 81 ++++++++++++++++ .../PointerStrokeStylePreferenceTest.java | 92 +++++++++++++++++++ 8 files changed, 390 insertions(+) create mode 100644 res/layout/pointer_icon_stroke_style_layout.xml create mode 100644 src/com/android/settings/inputmethod/PointerStrokeStylePreference.java create mode 100644 src/com/android/settings/inputmethod/PointerStrokeStylePreferenceController.java create mode 100644 tests/robotests/src/com/android/settings/inputmethod/PointerStrokeStylePreferenceControllerTest.java create mode 100644 tests/robotests/src/com/android/settings/inputmethod/PointerStrokeStylePreferenceTest.java diff --git a/res/layout/pointer_icon_stroke_style_layout.xml b/res/layout/pointer_icon_stroke_style_layout.xml new file mode 100644 index 00000000000..acf919ada99 --- /dev/null +++ b/res/layout/pointer_icon_stroke_style_layout.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/res/values/dimens.xml b/res/values/dimens.xml index ce48720cf78..8a96727d0a2 100755 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -179,6 +179,7 @@ 8dp 1dp 3dp + 8dp 8dp 1.0 2.5 diff --git a/res/values/strings.xml b/res/values/strings.xml index 81c89739fbb..dfce5db6079 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -4501,6 +4501,14 @@ Change pointer fill style to pink Change pointer fill style to blue + + Pointer stroke style + + White + + Black + + None Learn touchpad gestures diff --git a/res/xml/trackpad_settings.xml b/res/xml/trackpad_settings.xml index 04422dd5df9..a479e17ce1c 100644 --- a/res/xml/trackpad_settings.xml +++ b/res/xml/trackpad_settings.xml @@ -68,6 +68,12 @@ android:order="50" settings:controller="com.android.settings.inputmethod.PointerFillStylePreferenceController"/> + + true); + + int currentStroke = getPreferenceDataStore().getInt(Settings.System.POINTER_STROKE_STYLE, + POINTER_ICON_VECTOR_STYLE_STROKE_WHITE); + initRadioButton(holder, R.id.stroke_style_white, POINTER_ICON_VECTOR_STYLE_STROKE_WHITE, + currentStroke); + initRadioButton(holder, R.id.stroke_style_black, POINTER_ICON_VECTOR_STYLE_STROKE_BLACK, + currentStroke); + initRadioButton(holder, R.id.stroke_style_none, POINTER_ICON_VECTOR_STYLE_STROKE_NONE, + currentStroke); + } + + private void initRadioButton(@NonNull PreferenceViewHolder holder, int id, int strokeStyle, + int currentStroke) { + RadioButton radioButton = (RadioButton) holder.findViewById(id); + if (radioButton == null) { + return; + } + radioButton.setOnCheckedChangeListener((v, isChecked) -> { + if (isChecked) { + getPreferenceDataStore().putInt(Settings.System.POINTER_STROKE_STYLE, strokeStyle); + } + }); + radioButton.setChecked(currentStroke == strokeStyle); + radioButton.setPointerIcon(PointerIcon.getSystemIcon(getContext(), PointerIcon.TYPE_ARROW)); + } +} diff --git a/src/com/android/settings/inputmethod/PointerStrokeStylePreferenceController.java b/src/com/android/settings/inputmethod/PointerStrokeStylePreferenceController.java new file mode 100644 index 00000000000..e4ea996d8d6 --- /dev/null +++ b/src/com/android/settings/inputmethod/PointerStrokeStylePreferenceController.java @@ -0,0 +1,67 @@ +/* + * Copyright 2024 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.inputmethod; + +import android.content.Context; +import android.os.UserHandle; +import android.provider.Settings; + +import androidx.annotation.NonNull; +import androidx.annotation.VisibleForTesting; +import androidx.preference.Preference; +import androidx.preference.PreferenceDataStore; +import androidx.preference.PreferenceScreen; + +import com.android.settings.core.BasePreferenceController; + +public class PointerStrokeStylePreferenceController extends BasePreferenceController { + + @VisibleForTesting + static final String KEY_POINTER_STROKE_STYLE = "pointer_stroke_style"; + + public PointerStrokeStylePreferenceController(@NonNull Context context) { + super(context, KEY_POINTER_STROKE_STYLE); + } + + @AvailabilityStatus + public int getAvailabilityStatus() { + return android.view.flags.Flags.enableVectorCursorA11ySettings() ? AVAILABLE + : CONDITIONALLY_UNAVAILABLE; + } + + @Override + public void displayPreference(@NonNull PreferenceScreen screen) { + super.displayPreference(screen); + Preference pointerStrokeStylePreference = screen.findPreference(KEY_POINTER_STROKE_STYLE); + if (pointerStrokeStylePreference == null) { + return; + } + pointerStrokeStylePreference.setPreferenceDataStore(new PreferenceDataStore() { + @Override + public void putInt(@NonNull String key, int value) { + Settings.System.putIntForUser(mContext.getContentResolver(), key, value, + UserHandle.USER_CURRENT); + } + + @Override + public int getInt(@NonNull String key, int defValue) { + return Settings.System.getIntForUser(mContext.getContentResolver(), key, defValue, + UserHandle.USER_CURRENT); + } + }); + } +} diff --git a/tests/robotests/src/com/android/settings/inputmethod/PointerStrokeStylePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/inputmethod/PointerStrokeStylePreferenceControllerTest.java new file mode 100644 index 00000000000..9b4d5ef0b7c --- /dev/null +++ b/tests/robotests/src/com/android/settings/inputmethod/PointerStrokeStylePreferenceControllerTest.java @@ -0,0 +1,81 @@ +/* + * Copyright 2024 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.inputmethod; + +import static android.view.flags.Flags.enableVectorCursorA11ySettings; + +import static com.android.settings.core.BasePreferenceController.AVAILABLE; +import static com.android.settings.inputmethod.PointerStrokeStylePreferenceController.KEY_POINTER_STROKE_STYLE; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assume.assumeTrue; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.when; + +import android.content.Context; + +import androidx.preference.Preference; +import androidx.preference.PreferenceScreen; +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.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; +import org.robolectric.RobolectricTestRunner; + +/** Tests for {@link PointerStrokeStylePreferenceController} */ +@RunWith(RobolectricTestRunner.class) +public class PointerStrokeStylePreferenceControllerTest { + @Rule + public MockitoRule mMockitoRule = MockitoJUnit.rule(); + + @Mock + PreferenceScreen mPreferenceScreen; + + private Context mContext; + private PointerStrokeStylePreferenceController mController; + + @Before + public void setUp() { + mContext = ApplicationProvider.getApplicationContext(); + mController = new PointerStrokeStylePreferenceController(mContext); + } + + @Test + public void displayPreference_initializeDataStore() { + Preference strokePreference = new Preference(mContext); + strokePreference.setKey(KEY_POINTER_STROKE_STYLE); + when(mPreferenceScreen.findPreference(eq(KEY_POINTER_STROKE_STYLE))).thenReturn( + strokePreference); + + mController.displayPreference(mPreferenceScreen); + + assertNotNull(strokePreference.getPreferenceDataStore()); + } + + @Test + public void getAvailabilityStatus_flagEnabled() { + assumeTrue(enableVectorCursorA11ySettings()); + + assertEquals(mController.getAvailabilityStatus(), AVAILABLE); + } +} diff --git a/tests/robotests/src/com/android/settings/inputmethod/PointerStrokeStylePreferenceTest.java b/tests/robotests/src/com/android/settings/inputmethod/PointerStrokeStylePreferenceTest.java new file mode 100644 index 00000000000..33b85922c46 --- /dev/null +++ b/tests/robotests/src/com/android/settings/inputmethod/PointerStrokeStylePreferenceTest.java @@ -0,0 +1,92 @@ +/* + * Copyright 2024 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.inputmethod; + +import static android.view.PointerIcon.POINTER_ICON_VECTOR_STYLE_STROKE_BLACK; +import static android.view.PointerIcon.POINTER_ICON_VECTOR_STYLE_STROKE_WHITE; + +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; + +import android.content.Context; +import android.provider.Settings; +import android.view.View; +import android.widget.RadioButton; + +import androidx.preference.PreferenceDataStore; +import androidx.preference.PreferenceViewHolder; +import androidx.test.core.app.ApplicationProvider; + +import com.android.settings.R; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; +import org.robolectric.RobolectricTestRunner; + +/** Tests for {@link PointerStrokeStylePreference} */ +@RunWith(RobolectricTestRunner.class) +public class PointerStrokeStylePreferenceTest { + @Rule + public MockitoRule mMockitoRule = MockitoJUnit.rule(); + + @Mock + PreferenceDataStore mPreferenceDataStore; + + private Context mContext; + private PreferenceViewHolder mViewHolder; + private PointerStrokeStylePreference mPreference; + + + @Before + public void setUp() { + mContext = ApplicationProvider.getApplicationContext(); + mPreference = new PointerStrokeStylePreference(mContext, null); + } + + @Test + public void onBindViewHolder_getCurrentStrokeStyleFromDataStore() { + final View view = spy(View.inflate(mContext, mPreference.getLayoutResource(), null)); + mViewHolder = PreferenceViewHolder.createInstanceForTests(view); + mPreference.setPreferenceDataStore(mPreferenceDataStore); + + mPreference.onBindViewHolder(mViewHolder); + + verify(mPreferenceDataStore).getInt(Settings.System.POINTER_STROKE_STYLE, + POINTER_ICON_VECTOR_STYLE_STROKE_WHITE); + } + + @Test + public void setChecked_radioButtonUpdatesDataStore() { + final View view = spy(View.inflate(mContext, mPreference.getLayoutResource(), null)); + mViewHolder = PreferenceViewHolder.createInstanceForTests(view); + mPreference.setPreferenceDataStore(mPreferenceDataStore); + RadioButton radioButton = (RadioButton) view.findViewById(R.id.stroke_style_black); + mPreference.onBindViewHolder(mViewHolder); + + radioButton.setChecked(true); + + verify(mPreferenceDataStore).getInt(Settings.System.POINTER_STROKE_STYLE, + POINTER_ICON_VECTOR_STYLE_STROKE_WHITE); + verify(mPreferenceDataStore).putInt(Settings.System.POINTER_STROKE_STYLE, + POINTER_ICON_VECTOR_STYLE_STROKE_BLACK); + } +}