Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 75536b09 authored by Lorenzo Lucena Maguire's avatar Lorenzo Lucena Maguire
Browse files

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
parent 235556da
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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"/>

</PreferenceScreen>
+18 −38
Original line number Diff line number Diff line
@@ -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);
    }
}
+78 −0
Original line number Diff line number Diff line
/*
 * 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;
    }
}
+24 −34
Original line number Diff line number Diff line
@@ -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,24 +81,6 @@ 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(
@@ -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);

    @Test
    public void isSliceableIncorrectKey_returnsFalse() {
        final DoubleTapPowerPreferenceController controller =
                new DoubleTapPowerPreferenceController(mContext, "bad_key");
        assertThat(controller.isSliceable()).isFalse();
        assertThat(
                        TextUtils.equals(
                                mController.getSummary(),
                                mContext.getText(R.string.gesture_setting_on)))
                .isTrue();
    }

    @Test
    public void isPublicSlice_returnTrue() {
        assertThat(mController.isPublicSlice()).isTrue();
    public void getSummary_doubleTapPowerDisabled_returnsOff() {
        // Set the setting to be disabled.
        Settings.Secure.putInt(mContentResolver, CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, OFF);

        assertThat(
                        TextUtils.equals(
                                mController.getSummary(),
                                mContext.getText(R.string.gesture_setting_on)))
                .isTrue();
    }
}
+162 −0
Original line number Diff line number Diff line
/*
 * 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();
    }
}