From 75536b091ffdf9242b68fbf706bdc0fdfb35201f Mon Sep 17 00:00:00 2001 From: Lorenzo Lucena Maguire Date: Fri, 29 Nov 2024 09:10:24 +0000 Subject: [PATCH] Refactor DoubleTapPowerPreferenceController DoubleTapPreferenceController was previously used as the controller for the "Quickly open camera" entry in the "System > Gestures" screen and as the controller for the toggle in the ["System > Gestures > Quickly open camera" screen. This CL separates the DoubleTapPowerPreferenceController into two new controllers to handle each case: - Double Tap Power Preference Controller to control the "Quickly open camera" entry - Double Tap Power To Open Camera Preference Controller to control the gesture's enable/disable toggle. Android Settings Feature Request: b/380287172 Bug: 381499912 Test: atest DoubleTapPowerPreferenceControllerTest Test: atest DoubleTapPowerToOpenCameraPreferenceControllerTest FLAG: android.service.quickaccesswallet.launch_wallet_option_on_power_double_tap Change-Id: I73fc7d97e1e330163858a60a4ba9a63bd9b5574f --- res/xml/double_tap_power_settings.xml | 2 +- .../DoubleTapPowerPreferenceController.java | 56 ++---- ...PowerToOpenCameraPreferenceController.java | 78 +++++++++ ...oubleTapPowerPreferenceControllerTest.java | 58 +++---- ...rToOpenCameraPreferenceControllerTest.java | 162 ++++++++++++++++++ 5 files changed, 283 insertions(+), 73 deletions(-) create mode 100644 src/com/android/settings/gestures/DoubleTapPowerToOpenCameraPreferenceController.java create mode 100644 tests/robotests/src/com/android/settings/gestures/DoubleTapPowerToOpenCameraPreferenceControllerTest.java diff --git a/res/xml/double_tap_power_settings.xml b/res/xml/double_tap_power_settings.xml index fb5dd52b913..deb171c27cd 100644 --- a/res/xml/double_tap_power_settings.xml +++ b/res/xml/double_tap_power_settings.xml @@ -31,6 +31,6 @@ android:title="@string/double_tap_power_for_camera_title" android:summary="@string/double_tap_power_for_camera_summary" app:keywords="@string/keywords_gesture" - app:controller="com.android.settings.gestures.DoubleTapPowerPreferenceController"/> + app:controller="com.android.settings.gestures.DoubleTapPowerToOpenCameraPreferenceController"/> diff --git a/src/com/android/settings/gestures/DoubleTapPowerPreferenceController.java b/src/com/android/settings/gestures/DoubleTapPowerPreferenceController.java index 3d2e1768b2e..86c955ba55b 100644 --- a/src/com/android/settings/gestures/DoubleTapPowerPreferenceController.java +++ b/src/com/android/settings/gestures/DoubleTapPowerPreferenceController.java @@ -21,22 +21,15 @@ import static android.provider.Settings.Secure.CAMERA_DOUBLE_TAP_POWER_GESTURE_D import android.content.Context; import android.content.SharedPreferences; import android.provider.Settings; -import android.text.TextUtils; -import androidx.annotation.VisibleForTesting; +import androidx.annotation.NonNull; -public class DoubleTapPowerPreferenceController extends GesturePreferenceController { +import com.android.settings.R; +import com.android.settings.core.BasePreferenceController; - @VisibleForTesting - static final int ON = 0; - @VisibleForTesting - static final int OFF = 1; +public class DoubleTapPowerPreferenceController extends BasePreferenceController { - private static final String PREF_KEY_VIDEO = "gesture_double_tap_power_video"; - - private final String SECURE_KEY = CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED; - - public DoubleTapPowerPreferenceController(Context context, String key) { + public DoubleTapPowerPreferenceController(@NonNull Context context, @NonNull String key) { super(context, key); } @@ -45,7 +38,7 @@ public class DoubleTapPowerPreferenceController extends GesturePreferenceControl || prefs.getBoolean(DoubleTapPowerSettings.PREF_KEY_SUGGESTION_COMPLETE, false); } - private static boolean isGestureAvailable(Context context) { + private static boolean isGestureAvailable(@NonNull Context context) { return context.getResources() .getBoolean(com.android.internal.R.bool.config_cameraDoubleTapPowerGestureEnabled); } @@ -56,30 +49,17 @@ public class DoubleTapPowerPreferenceController extends GesturePreferenceControl } @Override - public boolean isSliceable() { - return TextUtils.equals(getPreferenceKey(), "gesture_double_tap_power"); - } - - @Override - public boolean isPublicSlice() { - return true; - } - - @Override - protected String getVideoPrefKey() { - return PREF_KEY_VIDEO; - } - - @Override - public boolean isChecked() { - final int cameraDisabled = Settings.Secure.getInt(mContext.getContentResolver(), - SECURE_KEY, ON); - return cameraDisabled == ON; - } - - @Override - public boolean setChecked(boolean isChecked) { - return Settings.Secure.putInt(mContext.getContentResolver(), SECURE_KEY, - isChecked ? ON : OFF); + @NonNull + public CharSequence getSummary() { + final boolean isCameraDoubleTapPowerGestureEnabled = + Settings.Secure.getInt( + mContext.getContentResolver(), + CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, + DoubleTapPowerToOpenCameraPreferenceController.ON) + == DoubleTapPowerToOpenCameraPreferenceController.ON; + return mContext.getText( + isCameraDoubleTapPowerGestureEnabled + ? R.string.gesture_setting_on + : R.string.gesture_setting_off); } } diff --git a/src/com/android/settings/gestures/DoubleTapPowerToOpenCameraPreferenceController.java b/src/com/android/settings/gestures/DoubleTapPowerToOpenCameraPreferenceController.java new file mode 100644 index 00000000000..4362a661007 --- /dev/null +++ b/src/com/android/settings/gestures/DoubleTapPowerToOpenCameraPreferenceController.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 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.gestures; + +import static android.provider.Settings.Secure.CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED; + +import android.content.Context; +import android.provider.Settings; +import android.text.TextUtils; + +import androidx.annotation.NonNull; + +import com.android.settings.R; +import com.android.settings.core.TogglePreferenceController; + +public class DoubleTapPowerToOpenCameraPreferenceController extends TogglePreferenceController { + + static final int ON = 0; + static final int OFF = 1; + + public DoubleTapPowerToOpenCameraPreferenceController( + @NonNull Context context, @NonNull String key) { + super(context, key); + } + + @Override + public int getAvailabilityStatus() { + return mContext.getResources() + .getBoolean( + com.android.internal.R.bool + .config_cameraDoubleTapPowerGestureEnabled) + ? AVAILABLE + : UNSUPPORTED_ON_DEVICE; + } + + @Override + public boolean isChecked() { + return Settings.Secure.getInt( + mContext.getContentResolver(), CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, ON) + == ON; + } + + @Override + public boolean setChecked(boolean isChecked) { + return Settings.Secure.putInt( + mContext.getContentResolver(), + CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, + isChecked ? ON : OFF); + } + + @Override + public boolean isSliceable() { + return TextUtils.equals(getPreferenceKey(), "gesture_double_tap_power"); + } + + @Override + public boolean isPublicSlice() { + return true; + } + + @Override + public int getSliceHighlightMenuRes() { + return R.string.menu_key_system; + } +} diff --git a/tests/robotests/src/com/android/settings/gestures/DoubleTapPowerPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/DoubleTapPowerPreferenceControllerTest.java index 72dd36e60a0..873eeda6c5c 100644 --- a/tests/robotests/src/com/android/settings/gestures/DoubleTapPowerPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/gestures/DoubleTapPowerPreferenceControllerTest.java @@ -18,9 +18,9 @@ package com.android.settings.gestures; import static android.provider.Settings.Secure.CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED; -import static com.android.settings.gestures.DoubleTapPowerPreferenceController.OFF; -import static com.android.settings.gestures.DoubleTapPowerPreferenceController.ON; import static com.android.settings.gestures.DoubleTapPowerPreferenceController.isSuggestionComplete; +import static com.android.settings.gestures.DoubleTapPowerToOpenCameraPreferenceController.OFF; +import static com.android.settings.gestures.DoubleTapPowerToOpenCameraPreferenceController.ON; import static com.google.common.truth.Truth.assertThat; @@ -28,7 +28,9 @@ import android.content.ContentResolver; import android.content.Context; import android.content.SharedPreferences; import android.provider.Settings; +import android.text.TextUtils; +import com.android.settings.R; import com.android.settings.dashboard.suggestions.SuggestionFeatureProviderImpl; import com.android.settings.testutils.shadow.SettingsShadowResources; @@ -71,7 +73,7 @@ public class DoubleTapPowerPreferenceControllerTest { } @Test - public void isAvailable_configIsTrue_shouldReturnFalse() { + public void isAvailable_configIsFalse_shouldReturnFalse() { SettingsShadowResources.overrideResource( com.android.internal.R.bool.config_cameraDoubleTapPowerGestureEnabled, Boolean.FALSE); @@ -79,30 +81,12 @@ public class DoubleTapPowerPreferenceControllerTest { assertThat(mController.isAvailable()).isFalse(); } - @Test - public void testIsChecked_configIsNotSet_shouldReturnTrue() { - // Set the setting to be enabled. - Settings.Secure.putInt(mContentResolver, CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, ON); - mController = new DoubleTapPowerPreferenceController(mContext, KEY_DOUBLE_TAP_POWER); - - assertThat(mController.isChecked()).isTrue(); - } - - @Test - public void testIsChecked_configIsSet_shouldReturnFalse() { - // Set the setting to be disabled. - Settings.Secure.putInt(mContentResolver, CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, OFF); - mController = new DoubleTapPowerPreferenceController(mContext, KEY_DOUBLE_TAP_POWER); - - assertThat(mController.isChecked()).isFalse(); - } - @Test public void isSuggestionCompleted_doubleTapPower_trueWhenNotAvailable() { SettingsShadowResources.overrideResource( com.android.internal.R.bool.config_cameraDoubleTapPowerGestureEnabled, false); - assertThat(isSuggestionComplete(mContext, null/* prefs */)).isTrue(); + assertThat(isSuggestionComplete(mContext, null /* prefs */)).isTrue(); } @Test @@ -112,6 +96,7 @@ public class DoubleTapPowerPreferenceControllerTest { // No stored value in shared preferences if not visited yet. final SharedPreferences prefs = new SuggestionFeatureProviderImpl().getSharedPrefs(mContext); + assertThat(isSuggestionComplete(mContext, prefs)).isFalse(); } @@ -128,21 +113,26 @@ public class DoubleTapPowerPreferenceControllerTest { } @Test - public void isSliceableCorrectKey_returnsTrue() { - final DoubleTapPowerPreferenceController controller = - new DoubleTapPowerPreferenceController(mContext, "gesture_double_tap_power"); - assertThat(controller.isSliceable()).isTrue(); + public void getSummary_doubleTapPowerEnabled_returnsOn() { + // Set the setting to be enabled. + Settings.Secure.putInt(mContentResolver, CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, ON); + + assertThat( + TextUtils.equals( + mController.getSummary(), + mContext.getText(R.string.gesture_setting_on))) + .isTrue(); } @Test - public void isSliceableIncorrectKey_returnsFalse() { - final DoubleTapPowerPreferenceController controller = - new DoubleTapPowerPreferenceController(mContext, "bad_key"); - assertThat(controller.isSliceable()).isFalse(); - } + public void getSummary_doubleTapPowerDisabled_returnsOff() { + // Set the setting to be disabled. + Settings.Secure.putInt(mContentResolver, CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, OFF); - @Test - public void isPublicSlice_returnTrue() { - assertThat(mController.isPublicSlice()).isTrue(); + assertThat( + TextUtils.equals( + mController.getSummary(), + mContext.getText(R.string.gesture_setting_on))) + .isTrue(); } } diff --git a/tests/robotests/src/com/android/settings/gestures/DoubleTapPowerToOpenCameraPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/DoubleTapPowerToOpenCameraPreferenceControllerTest.java new file mode 100644 index 00000000000..54d17ba258c --- /dev/null +++ b/tests/robotests/src/com/android/settings/gestures/DoubleTapPowerToOpenCameraPreferenceControllerTest.java @@ -0,0 +1,162 @@ +/* + * Copyright (C) 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.gestures; + +import static android.provider.Settings.Secure.CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED; + +import static com.android.settings.gestures.DoubleTapPowerToOpenCameraPreferenceController.OFF; +import static com.android.settings.gestures.DoubleTapPowerToOpenCameraPreferenceController.ON; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.content.res.Resources; +import android.platform.test.flag.junit.SetFlagsRule; +import android.provider.Settings; + +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import com.android.internal.R; +import com.android.settings.core.BasePreferenceController; +import com.android.settings.testutils.shadow.SettingsShadowResources; + +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; + +@RunWith(AndroidJUnit4.class) +@Config(shadows = SettingsShadowResources.class) +public class DoubleTapPowerToOpenCameraPreferenceControllerTest { + @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); + private Context mContext; + private Resources mResources; + private DoubleTapPowerToOpenCameraPreferenceController mController; + private static final String KEY_DOUBLE_TAP_POWER = "gesture_double_tap_power"; + + @Before + public void setUp() { + mContext = spy(RuntimeEnvironment.getApplication()); + mResources = mock(Resources.class); + when(mContext.getResources()).thenReturn(mResources); + mController = + new DoubleTapPowerToOpenCameraPreferenceController(mContext, KEY_DOUBLE_TAP_POWER); + } + + @After + public void tearDown() { + SettingsShadowResources.reset(); + } + + @Test + public void getAvailabilityStatus_setDoubleTapPowerGestureDisabled_preferenceUnsupported() { + when(mResources.getBoolean(R.bool.config_cameraDoubleTapPowerGestureEnabled)) + .thenReturn(false); + + assertThat(mController.getAvailabilityStatus()) + .isEqualTo(BasePreferenceController.UNSUPPORTED_ON_DEVICE); + } + + @Test + public void getAvailabilityStatus_setDoubleTapPowerGestureEnabled_preferenceSupported() { + when(mResources.getBoolean(R.bool.config_cameraDoubleTapPowerGestureEnabled)) + .thenReturn(true); + + assertThat(mController.getAvailabilityStatus()) + .isEqualTo(BasePreferenceController.AVAILABLE); + } + + @Test + public void isChecked_configIsNotSet_returnsTrue() { + // Set the setting to be enabled. + Settings.Secure.putInt( + mContext.getContentResolver(), CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, ON); + + assertThat(mController.isChecked()).isTrue(); + } + + @Test + public void isChecked_setConfigFalse_returnsFalse() { + // Set the setting to be disabled. + Settings.Secure.putInt( + mContext.getContentResolver(), CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, OFF); + + assertThat(mController.isChecked()).isFalse(); + } + + @Test + public void isChecked_setConfigTrue_returnsFalse() { + // Set the setting to be disabled. + Settings.Secure.putInt( + mContext.getContentResolver(), CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, ON); + + assertThat(mController.isChecked()).isTrue(); + } + + @Test + public void setChecked_checkToggle_cameraDoubleTapPowerGestureEnabled() { + mController.setChecked(true); + + assertThat( + Settings.Secure.getInt( + mContext.getContentResolver(), + CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, + OFF)) + .isEqualTo(ON); + } + + @Test + public void setChecked_uncheckToggle_cameraDoubleTapPowerGestureDisabled() { + mController.setChecked(false); + + assertThat( + Settings.Secure.getInt( + mContext.getContentResolver(), + CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, + ON)) + .isEqualTo(OFF); + } + + @Test + public void isSliceableCorrectKey_returnsTrue() { + final DoubleTapPowerToOpenCameraPreferenceController controller = + new DoubleTapPowerToOpenCameraPreferenceController( + mContext, "gesture_double_tap_power"); + + assertThat(controller.isSliceable()).isTrue(); + } + + @Test + public void isSliceableIncorrectKey_returnsFalse() { + final DoubleTapPowerToOpenCameraPreferenceController controller = + new DoubleTapPowerToOpenCameraPreferenceController(mContext, "bad_key"); + + assertThat(controller.isSliceable()).isFalse(); + } + + @Test + public void isPublicSlice_returnTrue() { + assertThat(mController.isPublicSlice()).isTrue(); + } +}