diff --git a/src/com/android/settings/inputmethod/PointerFillStylePreferenceController.java b/src/com/android/settings/inputmethod/PointerFillStylePreferenceController.java index 5abc3833405..bd6bbd5744c 100644 --- a/src/com/android/settings/inputmethod/PointerFillStylePreferenceController.java +++ b/src/com/android/settings/inputmethod/PointerFillStylePreferenceController.java @@ -16,25 +16,39 @@ package com.android.settings.inputmethod; +import static android.view.PointerIcon.POINTER_ICON_VECTOR_STYLE_FILL_BLACK; + +import android.app.settings.SettingsEnums; import android.content.Context; import android.os.UserHandle; import android.provider.Settings; import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; +import androidx.lifecycle.Lifecycle; +import androidx.lifecycle.LifecycleEventObserver; +import androidx.lifecycle.LifecycleOwner; import androidx.preference.Preference; import androidx.preference.PreferenceDataStore; import androidx.preference.PreferenceScreen; import com.android.settings.core.BasePreferenceController; +import com.android.settings.overlay.FeatureFactory; +import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; -public class PointerFillStylePreferenceController extends BasePreferenceController { +public class PointerFillStylePreferenceController extends BasePreferenceController + implements LifecycleEventObserver { + + private MetricsFeatureProvider mMetricsFeatureProvider; @VisibleForTesting static final String KEY_POINTER_FILL_STYLE = "pointer_fill_style"; public PointerFillStylePreferenceController(@NonNull Context context) { super(context, KEY_POINTER_FILL_STYLE); + + mMetricsFeatureProvider = + FeatureFactory.getFeatureFactory().getMetricsFeatureProvider(); } @AvailabilityStatus @@ -64,4 +78,17 @@ public class PointerFillStylePreferenceController extends BasePreferenceControll } }); } + + @Override + public void onStateChanged(@NonNull LifecycleOwner lifecycleOwner, + @NonNull Lifecycle.Event event) { + if (event == Lifecycle.Event.ON_PAUSE) { + int currentValue = + Settings.System.getIntForUser(mContext.getContentResolver(), + Settings.System.POINTER_FILL_STYLE, + POINTER_ICON_VECTOR_STYLE_FILL_BLACK, UserHandle.USER_CURRENT); + mMetricsFeatureProvider.action(mContext, + SettingsEnums.ACTION_POINTER_ICON_FILL_STYLE_CHANGED, currentValue); + } + } } diff --git a/src/com/android/settings/inputmethod/PointerScaleSeekBarController.java b/src/com/android/settings/inputmethod/PointerScaleSeekBarController.java index 06d52030783..509cdd63b24 100644 --- a/src/com/android/settings/inputmethod/PointerScaleSeekBarController.java +++ b/src/com/android/settings/inputmethod/PointerScaleSeekBarController.java @@ -18,6 +18,7 @@ package com.android.settings.inputmethod; import static android.view.PointerIcon.DEFAULT_POINTER_SCALE; +import android.app.settings.SettingsEnums; import android.content.Context; import android.content.res.Resources; import android.os.UserHandle; @@ -25,19 +26,27 @@ import android.provider.Settings; import android.widget.SeekBar; import androidx.annotation.NonNull; +import androidx.lifecycle.Lifecycle; +import androidx.lifecycle.LifecycleEventObserver; +import androidx.lifecycle.LifecycleOwner; import androidx.preference.PreferenceScreen; import com.android.settings.R; import com.android.settings.core.BasePreferenceController; +import com.android.settings.overlay.FeatureFactory; import com.android.settings.widget.LabeledSeekBarPreference; +import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; -public class PointerScaleSeekBarController extends BasePreferenceController { +public class PointerScaleSeekBarController extends BasePreferenceController + implements LifecycleEventObserver { private final int mProgressMin; private final int mProgressMax; private final float mScaleMin; private final float mScaleMax; + private MetricsFeatureProvider mMetricsFeatureProvider; + public PointerScaleSeekBarController(@NonNull Context context, @NonNull String key) { super(context, key); @@ -46,6 +55,9 @@ public class PointerScaleSeekBarController extends BasePreferenceController { mProgressMax = res.getInteger(R.integer.pointer_scale_seek_bar_end); mScaleMin = res.getFloat(R.dimen.pointer_scale_size_start); mScaleMax = res.getFloat(R.dimen.pointer_scale_size_end); + + mMetricsFeatureProvider = + FeatureFactory.getFeatureFactory().getMetricsFeatureProvider(); } @AvailabilityStatus @@ -92,4 +104,18 @@ public class PointerScaleSeekBarController extends BasePreferenceController { (((scale - mScaleMin) * (mProgressMax - mProgressMin)) / (mScaleMax - mScaleMin)) + mProgressMin); } + + @Override + public void onStateChanged(@NonNull LifecycleOwner lifecycleOwner, + @NonNull Lifecycle.Event event) { + if (event == Lifecycle.Event.ON_PAUSE) { + float currentValue = + Settings.System.getFloatForUser(mContext.getContentResolver(), + Settings.System.POINTER_SCALE, DEFAULT_POINTER_SCALE, + UserHandle.USER_CURRENT); + mMetricsFeatureProvider.action(mContext, + SettingsEnums.ACTION_POINTER_ICON_SCALE_CHANGED, + Float.toString(currentValue)); + } + } } diff --git a/src/com/android/settings/inputmethod/PointerStrokeStylePreferenceController.java b/src/com/android/settings/inputmethod/PointerStrokeStylePreferenceController.java index e4ea996d8d6..714e7b54982 100644 --- a/src/com/android/settings/inputmethod/PointerStrokeStylePreferenceController.java +++ b/src/com/android/settings/inputmethod/PointerStrokeStylePreferenceController.java @@ -16,25 +16,39 @@ package com.android.settings.inputmethod; +import static android.view.PointerIcon.POINTER_ICON_VECTOR_STYLE_STROKE_WHITE; + +import android.app.settings.SettingsEnums; import android.content.Context; import android.os.UserHandle; import android.provider.Settings; import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; +import androidx.lifecycle.Lifecycle; +import androidx.lifecycle.LifecycleEventObserver; +import androidx.lifecycle.LifecycleOwner; import androidx.preference.Preference; import androidx.preference.PreferenceDataStore; import androidx.preference.PreferenceScreen; import com.android.settings.core.BasePreferenceController; +import com.android.settings.overlay.FeatureFactory; +import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; -public class PointerStrokeStylePreferenceController extends BasePreferenceController { +public class PointerStrokeStylePreferenceController extends BasePreferenceController + implements LifecycleEventObserver { + + private MetricsFeatureProvider mMetricsFeatureProvider; @VisibleForTesting static final String KEY_POINTER_STROKE_STYLE = "pointer_stroke_style"; public PointerStrokeStylePreferenceController(@NonNull Context context) { super(context, KEY_POINTER_STROKE_STYLE); + + mMetricsFeatureProvider = + FeatureFactory.getFeatureFactory().getMetricsFeatureProvider(); } @AvailabilityStatus @@ -64,4 +78,17 @@ public class PointerStrokeStylePreferenceController extends BasePreferenceContro } }); } + + @Override + public void onStateChanged(@NonNull LifecycleOwner lifecycleOwner, + @NonNull Lifecycle.Event event) { + if (event == Lifecycle.Event.ON_PAUSE) { + int currentValue = + Settings.System.getIntForUser(mContext.getContentResolver(), + Settings.System.POINTER_STROKE_STYLE, + POINTER_ICON_VECTOR_STYLE_STROKE_WHITE, UserHandle.USER_CURRENT); + mMetricsFeatureProvider.action(mContext, + SettingsEnums.ACTION_POINTER_ICON_STROKE_STYLE_CHANGED, currentValue); + } + } } diff --git a/tests/robotests/src/com/android/settings/inputmethod/PointerFillStylePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/inputmethod/PointerFillStylePreferenceControllerTest.java new file mode 100644 index 00000000000..d8765f24c8e --- /dev/null +++ b/tests/robotests/src/com/android/settings/inputmethod/PointerFillStylePreferenceControllerTest.java @@ -0,0 +1,113 @@ +/* + * 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.PointerFillStylePreferenceController.KEY_POINTER_FILL_STYLE; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assume.assumeTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.app.settings.SettingsEnums; +import android.content.Context; +import android.os.UserHandle; +import android.provider.Settings; + +import androidx.lifecycle.Lifecycle; +import androidx.lifecycle.LifecycleEventObserver; +import androidx.lifecycle.LifecycleOwner; +import androidx.preference.Preference; +import androidx.preference.PreferenceScreen; +import androidx.test.core.app.ApplicationProvider; + +import com.android.settings.testutils.FakeFeatureFactory; +import com.android.settings.testutils.shadow.ShadowSystemSettings; + +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; +import org.robolectric.annotation.Config; + +/** Tests for {@link PointerFillStylePreferenceController} */ +@RunWith(RobolectricTestRunner.class) +@Config(shadows = { + ShadowSystemSettings.class, +}) +public class PointerFillStylePreferenceControllerTest { + @Rule + public MockitoRule mMockitoRule = MockitoJUnit.rule(); + + @Mock + PreferenceScreen mPreferenceScreen; + @Mock + LifecycleOwner mLifecycleOwner; + + private Context mContext; + private PointerFillStylePreferenceController mController; + private FakeFeatureFactory mFeatureFactory; + + @Before + public void setUp() { + mContext = ApplicationProvider.getApplicationContext(); + mFeatureFactory = FakeFeatureFactory.setupForTest(); + mController = new PointerFillStylePreferenceController(mContext); + } + + @Test + public void displayPreference_initializeDataStore() { + Preference fillPreference = new Preference(mContext); + fillPreference.setKey(KEY_POINTER_FILL_STYLE); + when(mPreferenceScreen.findPreference(eq(KEY_POINTER_FILL_STYLE))).thenReturn( + fillPreference); + + mController.displayPreference(mPreferenceScreen); + + assertNotNull(fillPreference.getPreferenceDataStore()); + } + + @Test + public void getAvailabilityStatus_flagEnabled() { + assumeTrue(enableVectorCursorA11ySettings()); + + assertEquals(mController.getAvailabilityStatus(), AVAILABLE); + } + + @Test + public void onPause_logCurrentFillValue() { + int fillStyle = 1; + Settings.System.putIntForUser(mContext.getContentResolver(), + Settings.System.POINTER_FILL_STYLE, fillStyle, UserHandle.USER_CURRENT); + + mController.onStateChanged(mLifecycleOwner, Lifecycle.Event.ON_PAUSE); + + verify(mFeatureFactory.metricsFeatureProvider).action( + any(), eq(SettingsEnums.ACTION_POINTER_ICON_FILL_STYLE_CHANGED), + eq(fillStyle)); + } +} diff --git a/tests/robotests/src/com/android/settings/inputmethod/PointerScaleSeekBarControllerTest.java b/tests/robotests/src/com/android/settings/inputmethod/PointerScaleSeekBarControllerTest.java index 152649fb3c5..18705c48d1f 100644 --- a/tests/robotests/src/com/android/settings/inputmethod/PointerScaleSeekBarControllerTest.java +++ b/tests/robotests/src/com/android/settings/inputmethod/PointerScaleSeekBarControllerTest.java @@ -22,16 +22,24 @@ import static com.android.settings.core.BasePreferenceController.AVAILABLE; import static org.junit.Assert.assertEquals; import static org.junit.Assume.assumeTrue; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.app.settings.SettingsEnums; import android.content.Context; import android.os.UserHandle; import android.provider.Settings; import android.widget.SeekBar; +import androidx.lifecycle.Lifecycle; +import androidx.lifecycle.LifecycleEventObserver; +import androidx.lifecycle.LifecycleOwner; import androidx.preference.PreferenceScreen; +import com.android.settings.testutils.FakeFeatureFactory; import com.android.settings.testutils.shadow.ShadowSystemSettings; import com.android.settings.widget.LabeledSeekBarPreference; @@ -58,14 +66,17 @@ public class PointerScaleSeekBarControllerTest { @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule(); @Mock private PreferenceScreen mPreferenceScreen; + @Mock private LifecycleOwner mLifecycleOwner; private Context mContext; private LabeledSeekBarPreference mPreference; private PointerScaleSeekBarController mController; + private FakeFeatureFactory mFeatureFactory; @Before public void setUp() { mContext = RuntimeEnvironment.application; + mFeatureFactory = FakeFeatureFactory.setupForTest(); mPreference = new LabeledSeekBarPreference(mContext, null); mController = new PointerScaleSeekBarController(mContext, PREFERENCE_KEY); } @@ -91,4 +102,17 @@ public class PointerScaleSeekBarControllerTest { Settings.System.POINTER_SCALE, -1, UserHandle.USER_CURRENT); assertEquals(expectedScale, currentScale, /* delta= */ 0.001f); } + + @Test + public void onPause_logCurrentScaleValue() { + float scale = 1.5f; + Settings.System.putFloatForUser(mContext.getContentResolver(), + Settings.System.POINTER_SCALE, scale, UserHandle.USER_CURRENT); + + mController.onStateChanged(mLifecycleOwner, Lifecycle.Event.ON_PAUSE); + + verify(mFeatureFactory.metricsFeatureProvider).action( + any(), eq(SettingsEnums.ACTION_POINTER_ICON_SCALE_CHANGED), + eq(Float.toString(scale))); + } } diff --git a/tests/robotests/src/com/android/settings/inputmethod/PointerStrokeStylePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/inputmethod/PointerStrokeStylePreferenceControllerTest.java index 9b4d5ef0b7c..9fffdc3aa0f 100644 --- a/tests/robotests/src/com/android/settings/inputmethod/PointerStrokeStylePreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/inputmethod/PointerStrokeStylePreferenceControllerTest.java @@ -24,15 +24,26 @@ import static com.android.settings.inputmethod.PointerStrokeStylePreferenceContr import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assume.assumeTrue; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import android.app.settings.SettingsEnums; import android.content.Context; +import android.os.UserHandle; +import android.provider.Settings; +import androidx.lifecycle.Lifecycle; +import androidx.lifecycle.LifecycleEventObserver; +import androidx.lifecycle.LifecycleOwner; import androidx.preference.Preference; import androidx.preference.PreferenceScreen; import androidx.test.core.app.ApplicationProvider; +import com.android.settings.testutils.FakeFeatureFactory; +import com.android.settings.testutils.shadow.ShadowSystemSettings; + import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -41,22 +52,30 @@ import org.mockito.Mock; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; /** Tests for {@link PointerStrokeStylePreferenceController} */ @RunWith(RobolectricTestRunner.class) +@Config(shadows = { + ShadowSystemSettings.class, +}) public class PointerStrokeStylePreferenceControllerTest { @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule(); @Mock PreferenceScreen mPreferenceScreen; + @Mock + LifecycleOwner mLifecycleOwner; private Context mContext; private PointerStrokeStylePreferenceController mController; + private FakeFeatureFactory mFeatureFactory; @Before public void setUp() { mContext = ApplicationProvider.getApplicationContext(); + mFeatureFactory = FakeFeatureFactory.setupForTest(); mController = new PointerStrokeStylePreferenceController(mContext); } @@ -78,4 +97,17 @@ public class PointerStrokeStylePreferenceControllerTest { assertEquals(mController.getAvailabilityStatus(), AVAILABLE); } + + @Test + public void onPause_logCurrentStrokeValue() { + int strokeStyle = 1; + Settings.System.putIntForUser(mContext.getContentResolver(), + Settings.System.POINTER_STROKE_STYLE, strokeStyle, UserHandle.USER_CURRENT); + + mController.onStateChanged(mLifecycleOwner, Lifecycle.Event.ON_PAUSE); + + verify(mFeatureFactory.metricsFeatureProvider).action( + any(), eq(SettingsEnums.ACTION_POINTER_ICON_STROKE_STYLE_CHANGED), + eq(strokeStyle)); + } }