diff --git a/res/values/strings.xml b/res/values/strings.xml index 525de4796a0..ebd6d60ef55 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -11158,6 +11158,23 @@ To quickly open camera, press the power button twice. Works from any screen. + + Double tap power button + + %1$s / %2$s + + Use double tap + + Double Tap Power Button + + Open Camera + + Access Camera + + Open Wallet + + Access Wallet + Flip camera for selfie diff --git a/res/xml/double_tap_power_settings.xml b/res/xml/double_tap_power_settings.xml new file mode 100644 index 00000000000..cf4a2f60217 --- /dev/null +++ b/res/xml/double_tap_power_settings.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + diff --git a/res/xml/gestures.xml b/res/xml/gestures.xml index 035c7f7c801..bfb359ae804 100644 --- a/res/xml/gestures.xml +++ b/res/xml/gestures.xml @@ -29,7 +29,7 @@ diff --git a/src/com/android/settings/gestures/DoubleTapPowerPreferenceController.java b/src/com/android/settings/gestures/DoubleTapPowerPreferenceController.java index 86c955ba55b..686d64cf1f5 100644 --- a/src/com/android/settings/gestures/DoubleTapPowerPreferenceController.java +++ b/src/com/android/settings/gestures/DoubleTapPowerPreferenceController.java @@ -23,6 +23,8 @@ import android.content.SharedPreferences; import android.provider.Settings; import androidx.annotation.NonNull; +import androidx.preference.Preference; +import androidx.preference.PreferenceScreen; import com.android.settings.R; import com.android.settings.core.BasePreferenceController; @@ -39,8 +41,12 @@ public class DoubleTapPowerPreferenceController extends BasePreferenceController } private static boolean isGestureAvailable(@NonNull Context context) { - return context.getResources() - .getBoolean(com.android.internal.R.bool.config_cameraDoubleTapPowerGestureEnabled); + if (!android.service.quickaccesswallet.Flags.launchWalletOptionOnPowerDoubleTap()) { + return context.getResources() + .getBoolean( + com.android.internal.R.bool.config_cameraDoubleTapPowerGestureEnabled); + } + return DoubleTapPowerSettingsUtils.isDoubleTapPowerButtonGestureAvailable(context); } @Override @@ -48,18 +54,42 @@ public class DoubleTapPowerPreferenceController extends BasePreferenceController return isGestureAvailable(mContext) ? AVAILABLE : UNSUPPORTED_ON_DEVICE; } + @Override + public void displayPreference(@NonNull PreferenceScreen screen) { + if (!android.service.quickaccesswallet.Flags.launchWalletOptionOnPowerDoubleTap()) { + final Preference preference = screen.findPreference(getPreferenceKey()); + if (preference != null) { + preference.setTitle(R.string.double_tap_power_for_camera_title); + } + } + super.displayPreference(screen); + } + @Override @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); + if (!android.service.quickaccesswallet.Flags.launchWalletOptionOnPowerDoubleTap()) { + 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); + } + if (DoubleTapPowerSettingsUtils.isDoubleTapPowerButtonGestureEnabled(mContext)) { + final CharSequence onString = + mContext.getText(com.android.settings.R.string.gesture_setting_on); + final CharSequence actionString = + DoubleTapPowerSettingsUtils.isDoubleTapPowerButtonGestureForCameraLaunchEnabled( + mContext) + ? mContext.getText(R.string.double_tap_power_camera_action_summary) + : mContext.getText(R.string.double_tap_power_wallet_action_summary); + return mContext.getString(R.string.double_tap_power_summary, onString, actionString); + } + return mContext.getText(com.android.settings.R.string.gesture_setting_off); } } diff --git a/src/com/android/settings/gestures/DoubleTapPowerSettings.java b/src/com/android/settings/gestures/DoubleTapPowerSettings.java index 75140ed8c31..076f23fa660 100644 --- a/src/com/android/settings/gestures/DoubleTapPowerSettings.java +++ b/src/com/android/settings/gestures/DoubleTapPowerSettings.java @@ -19,6 +19,9 @@ package com.android.settings.gestures; import android.app.settings.SettingsEnums; import android.content.Context; import android.content.SharedPreferences; +import android.provider.SearchIndexableResource; + +import androidx.annotation.NonNull; import com.android.settings.R; import com.android.settings.dashboard.DashboardFragment; @@ -27,6 +30,8 @@ import com.android.settings.overlay.FeatureFactory; import com.android.settings.search.BaseSearchIndexProvider; import com.android.settingslib.search.SearchIndexable; +import java.util.List; + @SearchIndexable public class DoubleTapPowerSettings extends DashboardFragment { @@ -56,9 +61,24 @@ public class DoubleTapPowerSettings extends DashboardFragment { @Override protected int getPreferenceScreenResId() { - return R.xml.double_tap_power_to_open_camera_settings; + return android.service.quickaccesswallet.Flags.launchWalletOptionOnPowerDoubleTap() + ? R.xml.double_tap_power_settings + : R.xml.double_tap_power_to_open_camera_settings; } public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = - new BaseSearchIndexProvider(R.xml.double_tap_power_to_open_camera_settings); + new BaseSearchIndexProvider() { + @Override + @NonNull + public List getXmlResourcesToIndex( + @NonNull Context context, boolean enabled) { + final SearchIndexableResource sir = new SearchIndexableResource(context); + sir.xmlResId = + android.service.quickaccesswallet.Flags + .launchWalletOptionOnPowerDoubleTap() + ? R.xml.double_tap_power_settings + : R.xml.double_tap_power_to_open_camera_settings; + return List.of(sir); + } + }; } diff --git a/tests/robotests/src/com/android/settings/gestures/DoubleTapPowerPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/DoubleTapPowerPreferenceControllerTest.java index 873eeda6c5c..17b03f355bf 100644 --- a/tests/robotests/src/com/android/settings/gestures/DoubleTapPowerPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/gestures/DoubleTapPowerPreferenceControllerTest.java @@ -17,6 +17,7 @@ package com.android.settings.gestures; import static android.provider.Settings.Secure.CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED; +import static android.provider.Settings.Secure.DOUBLE_TAP_POWER_BUTTON_GESTURE_ENABLED; import static com.android.settings.gestures.DoubleTapPowerPreferenceController.isSuggestionComplete; import static com.android.settings.gestures.DoubleTapPowerToOpenCameraPreferenceController.OFF; @@ -24,18 +25,29 @@ import static com.android.settings.gestures.DoubleTapPowerToOpenCameraPreference import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + import android.content.ContentResolver; import android.content.Context; import android.content.SharedPreferences; +import android.platform.test.annotations.DisableFlags; +import android.platform.test.annotations.EnableFlags; +import android.platform.test.flag.junit.SetFlagsRule; import android.provider.Settings; +import android.service.quickaccesswallet.Flags; import android.text.TextUtils; +import androidx.preference.Preference; +import androidx.preference.PreferenceScreen; + import com.android.settings.R; import com.android.settings.dashboard.suggestions.SuggestionFeatureProviderImpl; 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.RobolectricTestRunner; @@ -46,16 +58,22 @@ import org.robolectric.annotation.Config; @Config(shadows = SettingsShadowResources.class) public class DoubleTapPowerPreferenceControllerTest { + @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); private Context mContext; private ContentResolver mContentResolver; private DoubleTapPowerPreferenceController mController; + private Preference mPreference; + private PreferenceScreen mScreen; private static final String KEY_DOUBLE_TAP_POWER = "gesture_double_tap_power"; @Before public void setUp() { - mContext = RuntimeEnvironment.application; + mContext = RuntimeEnvironment.getApplication(); mContentResolver = mContext.getContentResolver(); mController = new DoubleTapPowerPreferenceController(mContext, KEY_DOUBLE_TAP_POWER); + mPreference = new Preference(mContext); + mScreen = mock(PreferenceScreen.class); + when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference); } @After @@ -64,7 +82,26 @@ public class DoubleTapPowerPreferenceControllerTest { } @Test - public void isAvailable_configIsTrue_shouldReturnTrue() { + @EnableFlags(Flags.FLAG_LAUNCH_WALLET_OPTION_ON_POWER_DOUBLE_TAP) + public void isAvailable_flagEnabled_configIsTrue_returnsTrue() { + SettingsShadowResources.overrideResource( + com.android.internal.R.bool.config_doubleTapPowerGestureEnabled, Boolean.TRUE); + + assertThat(mController.isAvailable()).isTrue(); + } + + @Test + @EnableFlags(Flags.FLAG_LAUNCH_WALLET_OPTION_ON_POWER_DOUBLE_TAP) + public void isAvailable_flagEnabled_configIsFalse_returnsFalse() { + SettingsShadowResources.overrideResource( + com.android.internal.R.bool.config_doubleTapPowerGestureEnabled, Boolean.FALSE); + + assertThat(mController.isAvailable()).isFalse(); + } + + @Test + @DisableFlags(Flags.FLAG_LAUNCH_WALLET_OPTION_ON_POWER_DOUBLE_TAP) + public void isAvailable_flagDisabled_configIsTrue_returnsTrue() { SettingsShadowResources.overrideResource( com.android.internal.R.bool.config_cameraDoubleTapPowerGestureEnabled, Boolean.TRUE); @@ -73,7 +110,8 @@ public class DoubleTapPowerPreferenceControllerTest { } @Test - public void isAvailable_configIsFalse_shouldReturnFalse() { + @DisableFlags(Flags.FLAG_LAUNCH_WALLET_OPTION_ON_POWER_DOUBLE_TAP) + public void isAvailable_flagDisabled_configIsFalse_returnsFalse() { SettingsShadowResources.overrideResource( com.android.internal.R.bool.config_cameraDoubleTapPowerGestureEnabled, Boolean.FALSE); @@ -82,7 +120,42 @@ public class DoubleTapPowerPreferenceControllerTest { } @Test - public void isSuggestionCompleted_doubleTapPower_trueWhenNotAvailable() { + @EnableFlags(Flags.FLAG_LAUNCH_WALLET_OPTION_ON_POWER_DOUBLE_TAP) + public void isSuggestionCompleted_enableFlag_doubleTapPower_trueWhenNotAvailable() { + SettingsShadowResources.overrideResource( + com.android.internal.R.bool.config_doubleTapPowerGestureEnabled, false); + + assertThat(isSuggestionComplete(mContext, null /* prefs */)).isTrue(); + } + + @Test + @EnableFlags(Flags.FLAG_LAUNCH_WALLET_OPTION_ON_POWER_DOUBLE_TAP) + public void isSuggestionCompleted_enableFlag_doubleTapPower_falseWhenNotVisited() { + SettingsShadowResources.overrideResource( + com.android.internal.R.bool.config_doubleTapPowerGestureEnabled, true); + // No stored value in shared preferences if not visited yet. + final SharedPreferences prefs = + new SuggestionFeatureProviderImpl().getSharedPrefs(mContext); + + assertThat(isSuggestionComplete(mContext, prefs)).isFalse(); + } + + @Test + @EnableFlags(Flags.FLAG_LAUNCH_WALLET_OPTION_ON_POWER_DOUBLE_TAP) + public void isSuggestionCompleted_enableFlag_doubleTapPower_trueWhenVisited() { + SettingsShadowResources.overrideResource( + com.android.internal.R.bool.config_doubleTapPowerGestureEnabled, true); + // No stored value in shared preferences if not visited yet. + final SharedPreferences prefs = + new SuggestionFeatureProviderImpl().getSharedPrefs(mContext); + prefs.edit().putBoolean(DoubleTapPowerSettings.PREF_KEY_SUGGESTION_COMPLETE, true).commit(); + + assertThat(isSuggestionComplete(mContext, prefs)).isTrue(); + } + + @Test + @DisableFlags(Flags.FLAG_LAUNCH_WALLET_OPTION_ON_POWER_DOUBLE_TAP) + public void isSuggestionCompleted_disableFlag_doubleTapPower_trueWhenNotAvailable() { SettingsShadowResources.overrideResource( com.android.internal.R.bool.config_cameraDoubleTapPowerGestureEnabled, false); @@ -90,7 +163,8 @@ public class DoubleTapPowerPreferenceControllerTest { } @Test - public void isSuggestionCompleted_doubleTapPower_falseWhenNotVisited() { + @DisableFlags(Flags.FLAG_LAUNCH_WALLET_OPTION_ON_POWER_DOUBLE_TAP) + public void isSuggestionCompleted_disableFlag_doubleTapPower_falseWhenNotVisited() { SettingsShadowResources.overrideResource( com.android.internal.R.bool.config_cameraDoubleTapPowerGestureEnabled, true); // No stored value in shared preferences if not visited yet. @@ -101,7 +175,8 @@ public class DoubleTapPowerPreferenceControllerTest { } @Test - public void isSuggestionCompleted_doubleTapPower_trueWhenVisited() { + @DisableFlags(Flags.FLAG_LAUNCH_WALLET_OPTION_ON_POWER_DOUBLE_TAP) + public void isSuggestionCompleted_disableFlag_doubleTapPower_trueWhenVisited() { SettingsShadowResources.overrideResource( com.android.internal.R.bool.config_cameraDoubleTapPowerGestureEnabled, true); // No stored value in shared preferences if not visited yet. @@ -113,7 +188,20 @@ public class DoubleTapPowerPreferenceControllerTest { } @Test - public void getSummary_doubleTapPowerEnabled_returnsOn() { + @DisableFlags(Flags.FLAG_LAUNCH_WALLET_OPTION_ON_POWER_DOUBLE_TAP) + public void displayPreference_flagDisabled_doubleTapPowerLegacyTitleIsDisplayed() { + mController.displayPreference(mScreen); + + assertThat( + TextUtils.equals( + mPreference.getTitle(), + mContext.getText(R.string.double_tap_power_for_camera_title))) + .isTrue(); + } + + @Test + @DisableFlags(Flags.FLAG_LAUNCH_WALLET_OPTION_ON_POWER_DOUBLE_TAP) + public void getSummary_flagDisabled_doubleTapPowerEnabled_returnsOn() { // Set the setting to be enabled. Settings.Secure.putInt(mContentResolver, CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, ON); @@ -125,14 +213,67 @@ public class DoubleTapPowerPreferenceControllerTest { } @Test - public void getSummary_doubleTapPowerDisabled_returnsOff() { + @DisableFlags(Flags.FLAG_LAUNCH_WALLET_OPTION_ON_POWER_DOUBLE_TAP) + public void getSummary_flagDisabled_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))) + mContext.getText(R.string.gesture_setting_off))) + .isTrue(); + } + + @Test + @EnableFlags(Flags.FLAG_LAUNCH_WALLET_OPTION_ON_POWER_DOUBLE_TAP) + public void getSummary_flagEnabled_doubleTapPowerDisabled_returnsOff() { + // Set the setting to be disabled. + Settings.Secure.putInt( + mContentResolver, DOUBLE_TAP_POWER_BUTTON_GESTURE_ENABLED, 0 /* OFF */); + + assertThat( + TextUtils.equals( + mController.getSummary(), + mContext.getText(R.string.gesture_setting_off))) + .isTrue(); + } + + @Test + @EnableFlags(Flags.FLAG_LAUNCH_WALLET_OPTION_ON_POWER_DOUBLE_TAP) + public void getSummary_flagEnabled_doubleTapPowerEnabled_cameraTargetAction_returnsSummary() { + // Set the setting to be enabled. + Settings.Secure.putInt( + mContentResolver, DOUBLE_TAP_POWER_BUTTON_GESTURE_ENABLED, 1 /* ON */); + DoubleTapPowerSettingsUtils.setDoubleTapPowerButtonForCameraLaunch(mContext); + + assertThat( + TextUtils.equals( + mController.getSummary(), + mContext.getString( + R.string.double_tap_power_summary, + mContext.getText(R.string.gesture_setting_on), + mContext.getText( + R.string.double_tap_power_camera_action_summary)))) + .isTrue(); + } + + @Test + @EnableFlags(Flags.FLAG_LAUNCH_WALLET_OPTION_ON_POWER_DOUBLE_TAP) + public void getSummary_flagEnabled_doubleTapPowerEnabled_walletTargetAction_returnsSummary() { + // Set the setting to be enabled. + Settings.Secure.putInt( + mContentResolver, DOUBLE_TAP_POWER_BUTTON_GESTURE_ENABLED, 1 /* ON */); + DoubleTapPowerSettingsUtils.setDoubleTapPowerButtonForWalletLaunch(mContext); + + assertThat( + TextUtils.equals( + mController.getSummary(), + mContext.getString( + R.string.double_tap_power_summary, + mContext.getText(R.string.gesture_setting_on), + mContext.getText( + R.string.double_tap_power_wallet_action_summary)))) .isTrue(); } } diff --git a/tests/robotests/src/com/android/settings/gestures/DoubleTapPowerSettingsTest.java b/tests/robotests/src/com/android/settings/gestures/DoubleTapPowerSettingsTest.java index 10e2565b345..7d4f52e67a2 100644 --- a/tests/robotests/src/com/android/settings/gestures/DoubleTapPowerSettingsTest.java +++ b/tests/robotests/src/com/android/settings/gestures/DoubleTapPowerSettingsTest.java @@ -18,11 +18,16 @@ package com.android.settings.gestures; import static com.google.common.truth.Truth.assertThat; +import android.platform.test.annotations.DisableFlags; +import android.platform.test.annotations.EnableFlags; +import android.platform.test.flag.junit.SetFlagsRule; import android.provider.SearchIndexableResource; +import android.service.quickaccesswallet.Flags; import com.android.settings.R; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; @@ -33,6 +38,7 @@ import java.util.List; @RunWith(RobolectricTestRunner.class) public class DoubleTapPowerSettingsTest { + @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); private DoubleTapPowerSettings mSettings; @Before @@ -41,18 +47,38 @@ public class DoubleTapPowerSettingsTest { } @Test - public void getPreferenceResId_returnsResId() { + @EnableFlags(Flags.FLAG_LAUNCH_WALLET_OPTION_ON_POWER_DOUBLE_TAP) + public void getPreferenceScreenResId_flagEnabled_returnsFlagEnabledResId() { + assertThat(mSettings.getPreferenceScreenResId()).isEqualTo(R.xml.double_tap_power_settings); + } + + @Test + @DisableFlags(Flags.FLAG_LAUNCH_WALLET_OPTION_ON_POWER_DOUBLE_TAP) + public void getPreferenceScreenResId_flagDisabled_returnsFlagDisabledResId() { assertThat(mSettings.getPreferenceScreenResId()) .isEqualTo(R.xml.double_tap_power_to_open_camera_settings); } @Test - public void testSearchIndexProvider_shouldIndexResource() { + @EnableFlags(Flags.FLAG_LAUNCH_WALLET_OPTION_ON_POWER_DOUBLE_TAP) + public void testSearchIndexProvider_flagEnabled_shouldIndexFlagEnabledResource() { final List indexRes = DoubleTapPowerSettings.SEARCH_INDEX_DATA_PROVIDER.getXmlResourcesToIndex( - RuntimeEnvironment.application, true /* enabled */); + RuntimeEnvironment.getApplication(), true /* enabled */); assertThat(indexRes).isNotNull(); - assertThat(indexRes.get(0).xmlResId).isEqualTo(mSettings.getPreferenceScreenResId()); + assertThat(indexRes.get(0).xmlResId).isEqualTo(R.xml.double_tap_power_settings); + } + + @Test + @DisableFlags(Flags.FLAG_LAUNCH_WALLET_OPTION_ON_POWER_DOUBLE_TAP) + public void testSearchIndexProvider_flagDisabled_shouldIndexFlagDisabledResource() { + final List indexRes = + DoubleTapPowerSettings.SEARCH_INDEX_DATA_PROVIDER.getXmlResourcesToIndex( + RuntimeEnvironment.getApplication(), true /* enabled */); + + assertThat(indexRes).isNotNull(); + assertThat(indexRes.get(0).xmlResId) + .isEqualTo(R.xml.double_tap_power_to_open_camera_settings); } }