From 33f62b4e017c91eb0fa3ff7d4bb9c13928b22801 Mon Sep 17 00:00:00 2001 From: shaoweishen Date: Wed, 25 Dec 2024 05:57:16 +0000 Subject: [PATCH 01/17] [Physical Keyboard] Add Metrics event for keyboard relates pages Bug: 377602364 Flag: com.android.settings.keyboard.keyboard_and_touchpad_a11y_new_page_enabled Test: atest packages/apps/Settings/tests/robotests/src/com/android/settings/inputmethod Change-Id: I28fc5c7676dcce2ad4aa63ea5745f5597558b0c1 --- .../InputSettingPreferenceController.java | 8 ++++++++ .../KeyboardAccessibilityBounceKeysController.java | 12 ++++++++++++ .../KeyboardAccessibilityMouseKeysController.java | 5 +++++ .../KeyboardAccessibilitySlowKeysController.java | 12 ++++++++++++ .../KeyboardAccessibilityStickyKeysController.java | 5 +++++ .../inputmethod/KeyboardRepeatKeysMainFragment.java | 2 +- .../inputmethod/MouseKeysMainPageFragment.java | 2 +- ...ReverseVerticalScrollingPreferenceController.java | 10 ++++++++++ .../MouseSwapPrimaryButtonPreferenceController.java | 10 ++++++++++ 9 files changed, 64 insertions(+), 2 deletions(-) diff --git a/src/com/android/settings/inputmethod/InputSettingPreferenceController.java b/src/com/android/settings/inputmethod/InputSettingPreferenceController.java index 8dda8c5cd51..9cc8d05be25 100644 --- a/src/com/android/settings/inputmethod/InputSettingPreferenceController.java +++ b/src/com/android/settings/inputmethod/InputSettingPreferenceController.java @@ -40,6 +40,8 @@ import androidx.preference.Preference; import com.android.settings.R; import com.android.settings.core.TogglePreferenceController; import com.android.settings.keyboard.Flags; +import com.android.settings.overlay.FeatureFactory; +import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; import java.util.concurrent.TimeUnit; @@ -51,6 +53,7 @@ public abstract class InputSettingPreferenceController extends TogglePreferenceC private static final int CUSTOM_PROGRESS_INTERVAL = 100; private static final long MILLISECOND_IN_SECONDS = TimeUnit.SECONDS.toMillis(1); private final ContentResolver mContentResolver; + protected final MetricsFeatureProvider mMetricsFeatureProvider; private final ContentObserver mContentObserver = new ContentObserver(new Handler(true)) { @Override public void onChange(boolean selfChange, Uri uri) { @@ -72,10 +75,14 @@ public abstract class InputSettingPreferenceController extends TogglePreferenceC return 0; } + protected void onCustomValueUpdated(int thresholdTimeMillis) { + } + public InputSettingPreferenceController(@NonNull Context context, @NonNull String preferenceKey) { super(context, preferenceKey); mContentResolver = context.getContentResolver(); + mMetricsFeatureProvider = FeatureFactory.getFeatureFactory().getMetricsFeatureProvider(); } @Override @@ -150,6 +157,7 @@ public abstract class InputSettingPreferenceController extends TogglePreferenceC } } updateInputSettingKeysValue(threshold); + onCustomValueUpdated(threshold); }) .setNegativeButton(android.R.string.cancel, (dialog, which) -> dialog.dismiss()) .create(); diff --git a/src/com/android/settings/inputmethod/KeyboardAccessibilityBounceKeysController.java b/src/com/android/settings/inputmethod/KeyboardAccessibilityBounceKeysController.java index 6bd836feb08..9a0f1c0d6e3 100644 --- a/src/com/android/settings/inputmethod/KeyboardAccessibilityBounceKeysController.java +++ b/src/com/android/settings/inputmethod/KeyboardAccessibilityBounceKeysController.java @@ -16,6 +16,10 @@ package com.android.settings.inputmethod; +import static android.app.settings.SettingsEnums.ACTION_BOUNCE_KEYS_CUSTOM_VALUE_CHANGE; +import static android.app.settings.SettingsEnums.ACTION_BOUNCE_KEYS_DISABLED; +import static android.app.settings.SettingsEnums.ACTION_BOUNCE_KEYS_ENABLED; + import android.content.Context; import android.hardware.input.InputSettings; import android.net.Uri; @@ -78,9 +82,17 @@ public class KeyboardAccessibilityBounceKeysController extends @Override public boolean setChecked(boolean isChecked) { updateInputSettingKeysValue(isChecked ? BOUNCE_KEYS_THRESHOLD : 0); + mMetricsFeatureProvider.action(mContext, + isChecked ? ACTION_BOUNCE_KEYS_ENABLED : ACTION_BOUNCE_KEYS_DISABLED); return true; } + @Override + protected void onCustomValueUpdated(int thresholdTimeMillis) { + mMetricsFeatureProvider.action(mContext, ACTION_BOUNCE_KEYS_CUSTOM_VALUE_CHANGE, + thresholdTimeMillis); + } + @Override protected void onInputSettingUpdated() { if (mPrimaryPreference != null) { diff --git a/src/com/android/settings/inputmethod/KeyboardAccessibilityMouseKeysController.java b/src/com/android/settings/inputmethod/KeyboardAccessibilityMouseKeysController.java index 34f53c47dce..2db0e05a2de 100644 --- a/src/com/android/settings/inputmethod/KeyboardAccessibilityMouseKeysController.java +++ b/src/com/android/settings/inputmethod/KeyboardAccessibilityMouseKeysController.java @@ -16,6 +16,9 @@ package com.android.settings.inputmethod; +import static android.app.settings.SettingsEnums.ACTION_MOUSE_KEYS_DISABLED; +import static android.app.settings.SettingsEnums.ACTION_MOUSE_KEYS_ENABLED; + import android.content.Context; import android.hardware.input.InputSettings; import android.net.Uri; @@ -63,6 +66,8 @@ public class KeyboardAccessibilityMouseKeysController extends public boolean setChecked(boolean isChecked) { InputSettings.setAccessibilityMouseKeysEnabled(mContext, isChecked); + mMetricsFeatureProvider.action(mContext, + isChecked ? ACTION_MOUSE_KEYS_ENABLED : ACTION_MOUSE_KEYS_DISABLED); return true; } diff --git a/src/com/android/settings/inputmethod/KeyboardAccessibilitySlowKeysController.java b/src/com/android/settings/inputmethod/KeyboardAccessibilitySlowKeysController.java index 857623a6839..451742ff2d4 100644 --- a/src/com/android/settings/inputmethod/KeyboardAccessibilitySlowKeysController.java +++ b/src/com/android/settings/inputmethod/KeyboardAccessibilitySlowKeysController.java @@ -16,6 +16,10 @@ package com.android.settings.inputmethod; +import static android.app.settings.SettingsEnums.ACTION_SLOW_KEYS_CUSTOM_VALUE_CHANGE; +import static android.app.settings.SettingsEnums.ACTION_SLOW_KEYS_DISABLED; +import static android.app.settings.SettingsEnums.ACTION_SLOW_KEYS_ENABLED; + import android.content.Context; import android.hardware.input.InputSettings; import android.net.Uri; @@ -58,6 +62,8 @@ public class KeyboardAccessibilitySlowKeysController extends @Override public boolean setChecked(boolean isChecked) { updateInputSettingKeysValue(isChecked ? SLOW_KEYS_THRESHOLD : 0); + mMetricsFeatureProvider.action(mContext, + isChecked ? ACTION_SLOW_KEYS_ENABLED : ACTION_SLOW_KEYS_DISABLED); return true; } @@ -98,6 +104,12 @@ public class KeyboardAccessibilitySlowKeysController extends InputSettings.setAccessibilitySlowKeysThreshold(mContext, thresholdTimeMillis); } + @Override + protected void onCustomValueUpdated(int thresholdTimeMillis) { + mMetricsFeatureProvider.action(mContext, + ACTION_SLOW_KEYS_CUSTOM_VALUE_CHANGE, thresholdTimeMillis); + } + @Override protected int getInputSettingKeysValue() { return InputSettings.getAccessibilitySlowKeysThreshold(mContext); diff --git a/src/com/android/settings/inputmethod/KeyboardAccessibilityStickyKeysController.java b/src/com/android/settings/inputmethod/KeyboardAccessibilityStickyKeysController.java index fd2cb2e6e11..f0dcc9350c6 100644 --- a/src/com/android/settings/inputmethod/KeyboardAccessibilityStickyKeysController.java +++ b/src/com/android/settings/inputmethod/KeyboardAccessibilityStickyKeysController.java @@ -16,6 +16,9 @@ package com.android.settings.inputmethod; +import static android.app.settings.SettingsEnums.ACTION_STICKY_KEYS_DISABLED; +import static android.app.settings.SettingsEnums.ACTION_STICKY_KEYS_ENABLED; + import android.content.Context; import android.hardware.input.InputSettings; import android.net.Uri; @@ -52,6 +55,8 @@ public class KeyboardAccessibilityStickyKeysController extends public boolean setChecked(boolean isChecked) { InputSettings.setAccessibilityStickyKeysEnabled(mContext, isChecked); + mMetricsFeatureProvider.action(mContext, + isChecked ? ACTION_STICKY_KEYS_ENABLED : ACTION_STICKY_KEYS_DISABLED); return true; } diff --git a/src/com/android/settings/inputmethod/KeyboardRepeatKeysMainFragment.java b/src/com/android/settings/inputmethod/KeyboardRepeatKeysMainFragment.java index 39e605d1d59..8c06c30ec28 100644 --- a/src/com/android/settings/inputmethod/KeyboardRepeatKeysMainFragment.java +++ b/src/com/android/settings/inputmethod/KeyboardRepeatKeysMainFragment.java @@ -68,7 +68,7 @@ public class KeyboardRepeatKeysMainFragment extends DashboardFragment @Override public int getMetricsCategory() { - return SettingsEnums.PHYSICAL_KEYBOARD_A11Y; + return SettingsEnums.PHYSICAL_KEYBOARD_REPEAT_KEYS; } @Override diff --git a/src/com/android/settings/inputmethod/MouseKeysMainPageFragment.java b/src/com/android/settings/inputmethod/MouseKeysMainPageFragment.java index dd9c1ddf62f..1f6035f03ec 100644 --- a/src/com/android/settings/inputmethod/MouseKeysMainPageFragment.java +++ b/src/com/android/settings/inputmethod/MouseKeysMainPageFragment.java @@ -83,7 +83,7 @@ public class MouseKeysMainPageFragment extends DashboardFragment @Override public int getMetricsCategory() { - return SettingsEnums.PHYSICAL_KEYBOARD_A11Y; + return SettingsEnums.SETTINGS_PHYSICAL_KEYBOARD_MOUSE_KEYS; } @Override diff --git a/src/com/android/settings/inputmethod/MouseReverseVerticalScrollingPreferenceController.java b/src/com/android/settings/inputmethod/MouseReverseVerticalScrollingPreferenceController.java index 977e906e2a5..a1a86153577 100644 --- a/src/com/android/settings/inputmethod/MouseReverseVerticalScrollingPreferenceController.java +++ b/src/com/android/settings/inputmethod/MouseReverseVerticalScrollingPreferenceController.java @@ -16,6 +16,9 @@ package com.android.settings.inputmethod; +import static android.app.settings.SettingsEnums.ACTION_MOUSE_REVERSE_VERTICAL_SCROLLING_DISABLED; +import static android.app.settings.SettingsEnums.ACTION_MOUSE_REVERSE_VERTICAL_SCROLLING_ENABLED; + import android.content.Context; import android.hardware.input.InputSettings; @@ -23,12 +26,16 @@ import androidx.annotation.NonNull; import com.android.settings.R; import com.android.settings.core.TogglePreferenceController; +import com.android.settings.overlay.FeatureFactory; +import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; public class MouseReverseVerticalScrollingPreferenceController extends TogglePreferenceController { + private final MetricsFeatureProvider mMetricsFeatureProvider; public MouseReverseVerticalScrollingPreferenceController( @NonNull Context context, @NonNull String key) { super(context, key); + mMetricsFeatureProvider = FeatureFactory.getFeatureFactory().getMetricsFeatureProvider(); } @Override @@ -39,6 +46,9 @@ public class MouseReverseVerticalScrollingPreferenceController extends TogglePre @Override public boolean setChecked(boolean isChecked) { InputSettings.setMouseReverseVerticalScrolling(mContext, isChecked); + mMetricsFeatureProvider.action(mContext, + isChecked ? ACTION_MOUSE_REVERSE_VERTICAL_SCROLLING_ENABLED : + ACTION_MOUSE_REVERSE_VERTICAL_SCROLLING_DISABLED); return true; } diff --git a/src/com/android/settings/inputmethod/MouseSwapPrimaryButtonPreferenceController.java b/src/com/android/settings/inputmethod/MouseSwapPrimaryButtonPreferenceController.java index 88199d8d64e..63dfc053df6 100644 --- a/src/com/android/settings/inputmethod/MouseSwapPrimaryButtonPreferenceController.java +++ b/src/com/android/settings/inputmethod/MouseSwapPrimaryButtonPreferenceController.java @@ -16,6 +16,9 @@ package com.android.settings.inputmethod; +import static android.app.settings.SettingsEnums.ACTION_MOUSE_SWAP_PRIMARY_BUTTON_DISABLED; +import static android.app.settings.SettingsEnums.ACTION_MOUSE_SWAP_PRIMARY_BUTTON_ENABLED; + import android.content.Context; import android.hardware.input.InputSettings; @@ -23,12 +26,16 @@ import androidx.annotation.NonNull; import com.android.settings.R; import com.android.settings.core.TogglePreferenceController; +import com.android.settings.overlay.FeatureFactory; +import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; public class MouseSwapPrimaryButtonPreferenceController extends TogglePreferenceController { + private final MetricsFeatureProvider mMetricsFeatureProvider; public MouseSwapPrimaryButtonPreferenceController( @NonNull Context context, @NonNull String key) { super(context, key); + mMetricsFeatureProvider = FeatureFactory.getFeatureFactory().getMetricsFeatureProvider(); } @Override @@ -39,6 +46,9 @@ public class MouseSwapPrimaryButtonPreferenceController extends TogglePreference @Override public boolean setChecked(boolean isChecked) { InputSettings.setMouseSwapPrimaryButton(mContext, isChecked); + mMetricsFeatureProvider.action(mContext, + isChecked ? ACTION_MOUSE_SWAP_PRIMARY_BUTTON_ENABLED : + ACTION_MOUSE_SWAP_PRIMARY_BUTTON_DISABLED); return true; } From 611c62294a0e025370cb582a72f97a94d9ac1478 Mon Sep 17 00:00:00 2001 From: Chaohui Wang Date: Thu, 2 Jan 2025 10:34:30 +0800 Subject: [PATCH 02/17] Use BytesFormatter for data usage Change "480 B" to "480 byte". And no longer use FormattedDataUsage. Bug: 321861088 Flag: EXEMPT bug fix Test: manual - App data usage Test: unit test Change-Id: I9ed220e2d5b8fc512d7d28f6fa7faebb37beab83 --- .../AppDataUsageSummaryController.kt | 12 +++----- .../settings/datausage/DataUsageList.kt | 2 +- .../datausage/lib/DataUsageFormatter.kt | 30 ++----------------- .../datausage/lib/NetworkUsageData.kt | 7 ++--- .../DataUsagePreferenceController.kt | 13 ++++---- .../spa/app/appinfo/AppDataUsagePreference.kt | 2 +- .../AppDataUsageSummaryControllerTest.kt | 14 +++------ .../datausage/lib/DataUsageFormatterTest.kt | 12 +++----- .../DataUsagePreferenceControllerTest.kt | 4 +-- 9 files changed, 30 insertions(+), 66 deletions(-) diff --git a/src/com/android/settings/datausage/AppDataUsageSummaryController.kt b/src/com/android/settings/datausage/AppDataUsageSummaryController.kt index fb7101dba9b..1cab87f42bf 100644 --- a/src/com/android/settings/datausage/AppDataUsageSummaryController.kt +++ b/src/com/android/settings/datausage/AppDataUsageSummaryController.kt @@ -37,8 +37,7 @@ class AppDataUsageSummaryController(context: Context, preferenceKey: String) : private val dataFlow = MutableStateFlow(NetworkUsageDetailsData.AllZero) private val dataUsageFormatter = DataUsageFormatter(context) - private val emptyDataUsage = - DataUsageFormatter.FormattedDataUsage(context.getPlaceholder(), context.getPlaceholder()) + private val emptyDataUsage = context.getPlaceholder() private val totalUsageFlow = dataFlow.map { dataUsageFormatter.formatDataUsage(it.totalUsage) @@ -66,18 +65,15 @@ class AppDataUsageSummaryController(context: Context, preferenceKey: String) : val backgroundUsage by backgroundUsageFlow.collectAsStateWithLifecycle(emptyDataUsage) Preference(object : PreferenceModel { override val title = stringResource(R.string.total_size_label) - override val summary = { totalUsage.displayText } - override val summaryContentDescription = { totalUsage.contentDescription } + override val summary = { totalUsage } }) Preference(object : PreferenceModel { override val title = stringResource(R.string.data_usage_label_foreground) - override val summary = { foregroundUsage.displayText } - override val summaryContentDescription = { foregroundUsage.contentDescription } + override val summary = { foregroundUsage } }) Preference(object : PreferenceModel { override val title = stringResource(R.string.data_usage_label_background) - override val summary = { backgroundUsage.displayText } - override val summaryContentDescription = { backgroundUsage.contentDescription } + override val summary = { backgroundUsage } }) } } diff --git a/src/com/android/settings/datausage/DataUsageList.kt b/src/com/android/settings/datausage/DataUsageList.kt index a2932776669..8636c56de69 100644 --- a/src/com/android/settings/datausage/DataUsageList.kt +++ b/src/com/android/settings/datausage/DataUsageList.kt @@ -172,7 +172,7 @@ open class DataUsageList : DashboardFragment() { private fun updateSelectedCycle(usageData: NetworkUsageData) { Log.d(TAG, "showing cycle $usageData") - usageAmount?.title = usageData.getDataUsedString(requireContext()).displayText + usageAmount?.title = usageData.getDataUsedString(requireContext()) viewModel.selectedCycleFlow.value = usageData updateApps(usageData) diff --git a/src/com/android/settings/datausage/lib/DataUsageFormatter.kt b/src/com/android/settings/datausage/lib/DataUsageFormatter.kt index 0a4c06b264b..849ff0dc89c 100644 --- a/src/com/android/settings/datausage/lib/DataUsageFormatter.kt +++ b/src/com/android/settings/datausage/lib/DataUsageFormatter.kt @@ -16,40 +16,16 @@ package com.android.settings.datausage.lib -import android.annotation.StringRes import android.content.Context import android.content.res.Resources -import android.icu.text.UnicodeSet -import android.icu.text.UnicodeSetSpanner -import android.text.BidiFormatter import android.text.format.Formatter -import com.android.internal.R +import com.android.settingslib.spaprivileged.framework.common.BytesFormatter class DataUsageFormatter(private val context: Context) { - data class FormattedDataUsage( - val displayText: String, - val contentDescription: String, - ) { - fun format(context: Context, @StringRes resId: Int, vararg formatArgs: Any?) = - FormattedDataUsage( - displayText = context.getString(resId, displayText, *formatArgs), - contentDescription = context.getString(resId, contentDescription, *formatArgs), - ) - } - /** Formats the data usage. */ - fun formatDataUsage(sizeBytes: Long): FormattedDataUsage { - val result = Formatter.formatBytes(context.resources, sizeBytes, Formatter.FLAG_IEC_UNITS) - return FormattedDataUsage( - displayText = BidiFormatter.getInstance().unicodeWrap( - context.getString(R.string.fileSizeSuffix, result.value, result.units) - ), - contentDescription = context.getString( - R.string.fileSizeSuffix, result.value, result.unitsContentDescription - ), - ) - } + fun formatDataUsage(sizeBytes: Long): String = + BytesFormatter(context).format(sizeBytes, BytesFormatter.UseCase.DataUsage) companion object { /** diff --git a/src/com/android/settings/datausage/lib/NetworkUsageData.kt b/src/com/android/settings/datausage/lib/NetworkUsageData.kt index 26578e325b4..0c34edf1059 100644 --- a/src/com/android/settings/datausage/lib/NetworkUsageData.kt +++ b/src/com/android/settings/datausage/lib/NetworkUsageData.kt @@ -20,7 +20,6 @@ import android.content.Context import android.text.format.DateUtils import android.util.Range import com.android.settings.R -import com.android.settings.datausage.lib.DataUsageFormatter.FormattedDataUsage /** * Base data structure representing usage data in a period. @@ -38,11 +37,11 @@ data class NetworkUsageData( fun formatDateRange(context: Context): String = DateUtils.formatDateRange(context, startTime, endTime, DATE_FORMAT) - fun formatUsage(context: Context): FormattedDataUsage = + fun formatUsage(context: Context): String = DataUsageFormatter(context).formatDataUsage(usage) - fun getDataUsedString(context: Context): FormattedDataUsage = - formatUsage(context).format(context, R.string.data_used_template) + fun getDataUsedString(context: Context): String = + context.getString(R.string.data_used_template, formatUsage(context)) companion object { val AllZero = NetworkUsageData( diff --git a/src/com/android/settings/network/telephony/DataUsagePreferenceController.kt b/src/com/android/settings/network/telephony/DataUsagePreferenceController.kt index aa113b692dc..2d8c0f77024 100644 --- a/src/com/android/settings/network/telephony/DataUsagePreferenceController.kt +++ b/src/com/android/settings/network/telephony/DataUsagePreferenceController.kt @@ -31,7 +31,6 @@ import androidx.preference.PreferenceScreen import com.android.settings.R import com.android.settings.core.BasePreferenceController import com.android.settings.datausage.DataUsageUtils -import com.android.settings.datausage.lib.DataUsageFormatter.FormattedDataUsage import com.android.settings.datausage.lib.DataUsageLib import com.android.settings.datausage.lib.NetworkCycleDataRepository import com.android.settings.datausage.lib.NetworkStatsRepository.Companion.AllTimeRange @@ -88,7 +87,7 @@ class DataUsagePreferenceController(context: Context, key: String) : getDataUsageSummaryAndEnabled() } preference.isEnabled = enabled - preference.summary = summary?.displayText + preference.summary = summary } private fun getNetworkTemplate(): NetworkTemplate? = @@ -100,12 +99,16 @@ class DataUsagePreferenceController(context: Context, key: String) : fun createNetworkCycleDataRepository(): NetworkCycleDataRepository? = networkTemplate?.let { NetworkCycleDataRepository(mContext, it) } - private fun getDataUsageSummaryAndEnabled(): Pair { + private fun getDataUsageSummaryAndEnabled(): Pair { val repository = createNetworkCycleDataRepository() ?: return null to false repository.loadFirstCycle()?.let { usageData -> - val formattedDataUsage = usageData.formatUsage(mContext) - .format(mContext, R.string.data_usage_template, usageData.formatDateRange(mContext)) + val formattedDataUsage = + mContext.getString( + R.string.data_usage_template, + usageData.formatUsage(mContext), + usageData.formatDateRange(mContext), + ) val hasUsage = usageData.usage > 0 || repository.queryUsage(AllTimeRange).usage > 0 return formattedDataUsage to hasUsage } diff --git a/src/com/android/settings/spa/app/appinfo/AppDataUsagePreference.kt b/src/com/android/settings/spa/app/appinfo/AppDataUsagePreference.kt index 7b8cf8c8b55..7e6e72613b7 100644 --- a/src/com/android/settings/spa/app/appinfo/AppDataUsagePreference.kt +++ b/src/com/android/settings/spa/app/appinfo/AppDataUsagePreference.kt @@ -113,7 +113,7 @@ private class AppDataUsagePresenter( } else { context.getString( R.string.data_summary_format, - appUsageData.formatUsage(context).displayText, + appUsageData.formatUsage(context), appUsageData.formatStartDate(context), ) } diff --git a/tests/spa_unit/src/com/android/settings/datausage/AppDataUsageSummaryControllerTest.kt b/tests/spa_unit/src/com/android/settings/datausage/AppDataUsageSummaryControllerTest.kt index be839dd416f..9323a4a7759 100644 --- a/tests/spa_unit/src/com/android/settings/datausage/AppDataUsageSummaryControllerTest.kt +++ b/tests/spa_unit/src/com/android/settings/datausage/AppDataUsageSummaryControllerTest.kt @@ -56,13 +56,10 @@ class AppDataUsageSummaryControllerTest { composeTestRule.onNode(hasTextExactly("Total", "6.75 kB")).assertIsDisplayed() composeTestRule.onNode(hasTextExactly("Foreground", "5.54 kB")).assertIsDisplayed() composeTestRule.onNode(hasTextExactly("Background", "1.21 kB")).assertIsDisplayed() - composeTestRule.onNodeWithContentDescription("6.75 kB").assertIsDisplayed() - composeTestRule.onNodeWithContentDescription("5.54 kB").assertIsDisplayed() - composeTestRule.onNodeWithContentDescription("1.21 kB").assertIsDisplayed() } @Test - fun summary_zero() { + fun summary_smallByte() { val appUsage = NetworkUsageDetailsData( range = Range(1L, 2L), totalUsage = 3, @@ -75,12 +72,9 @@ class AppDataUsageSummaryControllerTest { controller.Content() } - composeTestRule.onNode(hasTextExactly("Total", "3 B")).assertIsDisplayed() - composeTestRule.onNode(hasTextExactly("Foreground", "1 B")).assertIsDisplayed() - composeTestRule.onNode(hasTextExactly("Background", "2 B")).assertIsDisplayed() - composeTestRule.onNodeWithContentDescription("3 byte").assertIsDisplayed() - composeTestRule.onNodeWithContentDescription("1 byte").assertIsDisplayed() - composeTestRule.onNodeWithContentDescription("2 byte").assertIsDisplayed() + composeTestRule.onNode(hasTextExactly("Total", "3 byte")).assertIsDisplayed() + composeTestRule.onNode(hasTextExactly("Foreground", "1 byte")).assertIsDisplayed() + composeTestRule.onNode(hasTextExactly("Background", "2 byte")).assertIsDisplayed() } private companion object { diff --git a/tests/spa_unit/src/com/android/settings/datausage/lib/DataUsageFormatterTest.kt b/tests/spa_unit/src/com/android/settings/datausage/lib/DataUsageFormatterTest.kt index 071234dcd65..97a6c0f7fd2 100644 --- a/tests/spa_unit/src/com/android/settings/datausage/lib/DataUsageFormatterTest.kt +++ b/tests/spa_unit/src/com/android/settings/datausage/lib/DataUsageFormatterTest.kt @@ -21,7 +21,6 @@ import androidx.test.core.app.ApplicationProvider import androidx.test.ext.junit.runners.AndroidJUnit4 import com.android.settings.datausage.lib.DataUsageFormatter.Companion.getBytesDisplayUnit import com.google.common.truth.Truth.assertThat - import org.junit.Test import org.junit.runner.RunWith @@ -33,26 +32,23 @@ class DataUsageFormatterTest { @Test fun formatDataUsage_0() { - val (displayText, contentDescription) = dataUsageFormatter.formatDataUsage(0) + val displayText = dataUsageFormatter.formatDataUsage(0) - assertThat(displayText).isEqualTo("0 B") - assertThat(contentDescription).isEqualTo("0 byte") + assertThat(displayText).isEqualTo("0 byte") } @Test fun formatDataUsage_1000() { - val (displayText, contentDescription) = dataUsageFormatter.formatDataUsage(1000) + val displayText = dataUsageFormatter.formatDataUsage(1000) assertThat(displayText).isEqualTo("0.98 kB") - assertThat(contentDescription).isEqualTo("0.98 kB") } @Test fun formatDataUsage_2000000() { - val (displayText, contentDescription) = dataUsageFormatter.formatDataUsage(2000000) + val displayText = dataUsageFormatter.formatDataUsage(2000000) assertThat(displayText).isEqualTo("1.91 MB") - assertThat(contentDescription).isEqualTo("1.91 MB") } @Test diff --git a/tests/spa_unit/src/com/android/settings/network/telephony/DataUsagePreferenceControllerTest.kt b/tests/spa_unit/src/com/android/settings/network/telephony/DataUsagePreferenceControllerTest.kt index f4974e9cd8e..f16c9fae017 100644 --- a/tests/spa_unit/src/com/android/settings/network/telephony/DataUsagePreferenceControllerTest.kt +++ b/tests/spa_unit/src/com/android/settings/network/telephony/DataUsagePreferenceControllerTest.kt @@ -143,7 +143,7 @@ class DataUsagePreferenceControllerTest { controller.onViewCreated(TestLifecycleOwner()) waitUntil { preference.isEnabled } - waitUntil { preference.summary?.contains("0 B used") == true } + waitUntil { preference.summary?.contains("0 byte used") == true } } @Test @@ -159,7 +159,7 @@ class DataUsagePreferenceControllerTest { controller.onViewCreated(TestLifecycleOwner()) waitUntil { !preference.isEnabled } - waitUntil { preference.summary?.contains("0 B used") == true } + waitUntil { preference.summary?.contains("0 byte used") == true } } @Test From 2fdbe30929dbb3b3a9cba76cfad978156f376f5a Mon Sep 17 00:00:00 2001 From: Chaohui Wang Date: Thu, 2 Jan 2025 12:54:47 +0800 Subject: [PATCH 03/17] Clean up unused DataUsageSummary.formatUsage Bug: 321861088 Flag: EXEMPT bug fix Test: atest DataUsageSummaryTest Change-Id: Idea8401a81d738272a8f7b23d22c1fbd3feb6903 --- .../settings/datausage/DataUsageSummary.java | 33 ------------------- .../datausage/DataUsageSummaryTest.java | 11 ------- 2 files changed, 44 deletions(-) diff --git a/src/com/android/settings/datausage/DataUsageSummary.java b/src/com/android/settings/datausage/DataUsageSummary.java index dfb35084a12..558730cf78f 100644 --- a/src/com/android/settings/datausage/DataUsageSummary.java +++ b/src/com/android/settings/datausage/DataUsageSummary.java @@ -22,12 +22,7 @@ import android.os.Bundle; import android.os.UserManager; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; -import android.text.BidiFormatter; -import android.text.Spannable; -import android.text.SpannableString; import android.text.TextUtils; -import android.text.format.Formatter; -import android.text.style.RelativeSizeSpan; import android.util.EventLog; import android.util.Log; @@ -211,34 +206,6 @@ public class DataUsageSummary extends DashboardFragment { updateState(); } - @VisibleForTesting - static CharSequence formatUsage(Context context, String template, long usageLevel) { - final float LARGER_SIZE = 1.25f * 1.25f; // (1/0.8)^2 - final float SMALLER_SIZE = 1.0f / LARGER_SIZE; // 0.8^2 - return formatUsage(context, template, usageLevel, LARGER_SIZE, SMALLER_SIZE); - } - - static CharSequence formatUsage(Context context, String template, long usageLevel, - float larger, float smaller) { - final int FLAGS = Spannable.SPAN_INCLUSIVE_INCLUSIVE; - - final Formatter.BytesResult usedResult = Formatter.formatBytes(context.getResources(), - usageLevel, Formatter.FLAG_CALCULATE_ROUNDED | Formatter.FLAG_IEC_UNITS); - final SpannableString enlargedValue = new SpannableString(usedResult.value); - enlargedValue.setSpan(new RelativeSizeSpan(larger), 0, enlargedValue.length(), FLAGS); - - final SpannableString amountTemplate = new SpannableString( - context.getString(com.android.internal.R.string.fileSizeSuffix) - .replace("%1$s", "^1").replace("%2$s", "^2")); - final CharSequence formattedUsage = TextUtils.expandTemplate(amountTemplate, - enlargedValue, usedResult.units); - - final SpannableString fullTemplate = new SpannableString(template); - fullTemplate.setSpan(new RelativeSizeSpan(smaller), 0, fullTemplate.length(), FLAGS); - return TextUtils.expandTemplate(fullTemplate, - BidiFormatter.getInstance().unicodeWrap(formattedUsage.toString())); - } - private void updateState() { PreferenceScreen screen = getPreferenceScreen(); for (int i = 1; i < screen.getPreferenceCount(); i++) { diff --git a/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryTest.java b/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryTest.java index 2a9cca9c669..54e4554802b 100644 --- a/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryTest.java +++ b/tests/robotests/src/com/android/settings/datausage/DataUsageSummaryTest.java @@ -16,8 +16,6 @@ package com.android.settings.datausage; -import static com.google.common.truth.Truth.assertThat; - import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyString; @@ -92,15 +90,6 @@ public class DataUsageSummaryTest { doNothing().when(mDataUsageSummary).addWifiSection(); } - @Test - public void formatUsage_shouldLookLikeFormatFileSize() { - final long usage = 2147483648L; // 2GB - final String formattedUsage = - DataUsageSummary.formatUsage(mContext, "^1", usage).toString(); - final CharSequence formattedInIECUnit = DataUsageUtils.formatDataUsage(mContext, usage); - assertThat(formattedUsage).isEqualTo(formattedInIECUnit); - } - @Test @Config(shadows = ShadowSubscriptionManager.class) public void configuration_withSim_shouldShowMobileAndWifi() { From d3448f3a91b557df4415b6fad7e469c18b626f37 Mon Sep 17 00:00:00 2001 From: Chaohui Wang Date: Thu, 2 Jan 2025 06:32:26 -0800 Subject: [PATCH 04/17] Migrate all data usage format use case Now they are all aligned. Bug: 321861088 Flag: EXEMPT bug fix Test: unit test Change-Id: I1981fd32fd24de7c9eff93e0cd638e862f01b9b9 --- .../datausage/AppDataUsagePreference.java | 3 ++- .../datausage/BillingCycleSettings.java | 5 +++-- .../datausage/ChartDataUsagePreference.java | 9 +++++---- .../datausage/DataUsagePreference.java | 4 +++- .../datausage/DataUsageSummaryPreference.java | 18 ++++++++++-------- .../DataUsageSummaryPreferenceController.kt | 15 +++++++++------ .../settings/datausage/DataUsageUtils.java | 16 ---------------- .../datausage/lib/DataUsageFormatter.kt | 12 ++++++++---- .../settings/datausage/DataUsageUtilsTest.java | 9 --------- ...DataUsageSummaryPreferenceControllerTest.kt | 12 ++++++------ .../app/appinfo/AppDataUsagePreferenceTest.kt | 2 +- 11 files changed, 47 insertions(+), 58 deletions(-) diff --git a/src/com/android/settings/datausage/AppDataUsagePreference.java b/src/com/android/settings/datausage/AppDataUsagePreference.java index 277c9b3fe7e..2d5c76ac777 100644 --- a/src/com/android/settings/datausage/AppDataUsagePreference.java +++ b/src/com/android/settings/datausage/AppDataUsagePreference.java @@ -21,6 +21,7 @@ import android.widget.ProgressBar; import androidx.preference.PreferenceViewHolder; import com.android.settings.R; +import com.android.settings.datausage.lib.DataUsageFormatter; import com.android.settingslib.AppItem; import com.android.settingslib.net.UidDetail; import com.android.settingslib.net.UidDetailProvider; @@ -46,7 +47,7 @@ public class AppDataUsagePreference extends AppPreference { if (item.restricted && item.total <= 0) { setSummary(com.android.settings.R.string.data_usage_app_restricted); } else { - setSummary(DataUsageUtils.formatDataUsage(context, item.total)); + setSummary(new DataUsageFormatter(context).formatDataUsage(item.total)); } mDetail = provider.getUidDetail(item.key, false /* blocking */); if (mDetail != null) { diff --git a/src/com/android/settings/datausage/BillingCycleSettings.java b/src/com/android/settings/datausage/BillingCycleSettings.java index 69577a85574..3f240e65c09 100644 --- a/src/com/android/settings/datausage/BillingCycleSettings.java +++ b/src/com/android/settings/datausage/BillingCycleSettings.java @@ -152,8 +152,9 @@ public class BillingCycleSettings extends DataUsageBaseFragment implements void updatePrefs() { mBillingCycle.setSummary(null); final long warningBytes = services.mPolicyEditor.getPolicyWarningBytes(mNetworkTemplate); + DataUsageFormatter dataUsageFormatter = new DataUsageFormatter(requireContext()); if (warningBytes != WARNING_DISABLED) { - mDataWarning.setSummary(DataUsageUtils.formatDataUsage(getContext(), warningBytes)); + mDataWarning.setSummary(dataUsageFormatter.formatDataUsage(warningBytes)); mDataWarning.setEnabled(true); mEnableDataWarning.setChecked(true); } else { @@ -163,7 +164,7 @@ public class BillingCycleSettings extends DataUsageBaseFragment implements } final long limitBytes = services.mPolicyEditor.getPolicyLimitBytes(mNetworkTemplate); if (limitBytes != LIMIT_DISABLED) { - mDataLimit.setSummary(DataUsageUtils.formatDataUsage(getContext(), limitBytes)); + mDataLimit.setSummary(dataUsageFormatter.formatDataUsage(limitBytes)); mDataLimit.setEnabled(true); mEnableDataLimit.setChecked(true); } else { diff --git a/src/com/android/settings/datausage/ChartDataUsagePreference.java b/src/com/android/settings/datausage/ChartDataUsagePreference.java index 0c7db715813..6a79b7a6fe9 100644 --- a/src/com/android/settings/datausage/ChartDataUsagePreference.java +++ b/src/com/android/settings/datausage/ChartDataUsagePreference.java @@ -20,7 +20,6 @@ import android.net.NetworkPolicy; import android.text.SpannableStringBuilder; import android.text.TextUtils; import android.text.format.DateUtils; -import android.text.format.Formatter; import android.text.style.ForegroundColorSpan; import android.util.AttributeSet; import android.util.DataUnit; @@ -34,9 +33,11 @@ import androidx.preference.PreferenceViewHolder; import com.android.settings.R; import com.android.settings.Utils; +import com.android.settings.datausage.lib.DataUsageFormatter; import com.android.settings.datausage.lib.NetworkCycleChartData; import com.android.settings.datausage.lib.NetworkUsageData; import com.android.settings.widget.UsageView; +import com.android.settingslib.spaprivileged.framework.common.BytesFormatter; import java.util.ArrayList; import java.util.Comparator; @@ -279,10 +280,10 @@ public class ChartDataUsagePreference extends Preference { } private CharSequence getLabel(long bytes, int str, int mLimitColor) { - Formatter.BytesResult result = Formatter.formatBytes(mResources, bytes, - Formatter.FLAG_SHORTER | Formatter.FLAG_IEC_UNITS); + DataUsageFormatter dataUsageFormatter = new DataUsageFormatter(getContext()); + BytesFormatter.Result result = dataUsageFormatter.formatDataUsageWithUnits(bytes); CharSequence label = TextUtils.expandTemplate(getContext().getText(str), - result.value, result.units); + result.getNumber(), result.getUnits()); return new SpannableStringBuilder().append(label, new ForegroundColorSpan(mLimitColor), 0); } diff --git a/src/com/android/settings/datausage/DataUsagePreference.java b/src/com/android/settings/datausage/DataUsagePreference.java index 07368c728eb..010df148a9f 100644 --- a/src/com/android/settings/datausage/DataUsagePreference.java +++ b/src/com/android/settings/datausage/DataUsagePreference.java @@ -28,6 +28,7 @@ import androidx.preference.Preference; import com.android.settings.R; import com.android.settings.core.SubSettingLauncher; +import com.android.settings.datausage.lib.DataUsageFormatter; import com.android.settingslib.net.DataUsageController; public class DataUsagePreference extends Preference implements TemplatePreference { @@ -58,8 +59,9 @@ public class DataUsagePreference extends Preference implements TemplatePreferenc final DataUsageController.DataUsageInfo usageInfo = controller.getDataUsageInfo(mTemplate); setTitle(mTitleRes); + DataUsageFormatter dataUsageFormatter = new DataUsageFormatter(getContext()); setSummary(getContext().getString(R.string.data_usage_template, - DataUsageUtils.formatDataUsage(getContext(), usageInfo.usageLevel), + dataUsageFormatter.formatDataUsage(usageInfo.usageLevel), usageInfo.period)); } final long usageLevel = controller.getHistoricalUsageLevel(template); diff --git a/src/com/android/settings/datausage/DataUsageSummaryPreference.java b/src/com/android/settings/datausage/DataUsageSummaryPreference.java index 6500501b210..92c9163ddc0 100644 --- a/src/com/android/settings/datausage/DataUsageSummaryPreference.java +++ b/src/com/android/settings/datausage/DataUsageSummaryPreference.java @@ -24,7 +24,6 @@ import android.telephony.SubscriptionPlan; import android.text.Spannable; import android.text.SpannableString; import android.text.TextUtils; -import android.text.format.Formatter; import android.text.style.AbsoluteSizeSpan; import android.util.AttributeSet; import android.view.View; @@ -39,7 +38,9 @@ import androidx.preference.Preference; import androidx.preference.PreferenceViewHolder; import com.android.settings.R; +import com.android.settings.datausage.lib.DataUsageFormatter; import com.android.settingslib.Utils; +import com.android.settingslib.spaprivileged.framework.common.BytesFormatter; import com.android.settingslib.utils.StringUtil; import java.util.HashMap; @@ -165,11 +166,12 @@ public class DataUsageSummaryPreference extends Preference { } private void updateDataUsageLabels(PreferenceViewHolder holder) { - TextView usageNumberField = getDataUsed(holder); + DataUsageFormatter dataUsageFormatter = new DataUsageFormatter(getContext()); - final Formatter.BytesResult usedResult = Formatter.formatBytes(getContext().getResources(), - mDataplanUse, Formatter.FLAG_CALCULATE_ROUNDED | Formatter.FLAG_IEC_UNITS); - final SpannableString usageNumberText = new SpannableString(usedResult.value); + TextView usageNumberField = getDataUsed(holder); + final BytesFormatter.Result usedResult = + dataUsageFormatter.formatDataUsageWithUnits(mDataplanUse); + final SpannableString usageNumberText = new SpannableString(usedResult.getNumber()); final int textSize = getContext().getResources().getDimensionPixelSize(R.dimen.usage_number_text_size); usageNumberText.setSpan(new AbsoluteSizeSpan(textSize), 0, usageNumberText.length(), @@ -177,7 +179,7 @@ public class DataUsageSummaryPreference extends Preference { CharSequence template = getContext().getText(R.string.data_used_formatted); CharSequence usageText = - TextUtils.expandTemplate(template, usageNumberText, usedResult.units); + TextUtils.expandTemplate(template, usageNumberText, usedResult.getUnits()); usageNumberField.setText(usageText); final MeasurableLinearLayout layout = getLayout(holder); @@ -188,13 +190,13 @@ public class DataUsageSummaryPreference extends Preference { if (dataRemaining >= 0) { usageRemainingField.setText( TextUtils.expandTemplate(getContext().getText(R.string.data_remaining), - DataUsageUtils.formatDataUsage(getContext(), dataRemaining))); + dataUsageFormatter.formatDataUsage(dataRemaining))); usageRemainingField.setTextColor( Utils.getColorAttr(getContext(), android.R.attr.colorAccent)); } else { usageRemainingField.setText( TextUtils.expandTemplate(getContext().getText(R.string.data_overusage), - DataUsageUtils.formatDataUsage(getContext(), -dataRemaining))); + dataUsageFormatter.formatDataUsage(-dataRemaining))); usageRemainingField.setTextColor( Utils.getColorAttr(getContext(), android.R.attr.colorError)); } diff --git a/src/com/android/settings/datausage/DataUsageSummaryPreferenceController.kt b/src/com/android/settings/datausage/DataUsageSummaryPreferenceController.kt index 6f62c300a84..7a696965109 100644 --- a/src/com/android/settings/datausage/DataUsageSummaryPreferenceController.kt +++ b/src/com/android/settings/datausage/DataUsageSummaryPreferenceController.kt @@ -24,6 +24,7 @@ import android.util.Log import androidx.lifecycle.LifecycleOwner import androidx.preference.PreferenceScreen import com.android.settings.R +import com.android.settings.datausage.lib.DataUsageFormatter import com.android.settings.datausage.lib.DataUsageLib.getMobileTemplate import com.android.settings.datausage.lib.INetworkCycleDataRepository import com.android.settings.datausage.lib.NetworkCycleDataRepository @@ -72,6 +73,8 @@ open class DataUsageSummaryPreferenceController @JvmOverloads constructor( private lateinit var preference: DataUsageSummaryPreference + private val dataUsageFormatter = DataUsageFormatter(mContext) + override fun getAvailabilityStatus(subId: Int) = if (subInfo != null) AVAILABLE else CONDITIONALLY_UNAVAILABLE @@ -120,8 +123,8 @@ open class DataUsageSummaryPreferenceController @JvmOverloads constructor( private fun setDataBarSize(dataBarSize: Long) { preference.setLabels( - DataUsageUtils.formatDataUsage(mContext, /* byteValue = */ 0), - DataUsageUtils.formatDataUsage(mContext, dataBarSize) + dataUsageFormatter.formatDataUsage(/* byteValue = */ 0), + dataUsageFormatter.formatDataUsage(dataBarSize) ) } @@ -129,22 +132,22 @@ open class DataUsageSummaryPreferenceController @JvmOverloads constructor( warningBytes > 0 && limitBytes > 0 -> { TextUtils.expandTemplate( mContext.getText(R.string.cell_data_warning_and_limit), - DataUsageUtils.formatDataUsage(mContext, warningBytes), - DataUsageUtils.formatDataUsage(mContext, limitBytes), + dataUsageFormatter.formatDataUsage(warningBytes), + dataUsageFormatter.formatDataUsage(limitBytes), ) } warningBytes > 0 -> { TextUtils.expandTemplate( mContext.getText(R.string.cell_data_warning), - DataUsageUtils.formatDataUsage(mContext, warningBytes), + dataUsageFormatter.formatDataUsage(warningBytes), ) } limitBytes > 0 -> { TextUtils.expandTemplate( mContext.getText(R.string.cell_data_limit), - DataUsageUtils.formatDataUsage(mContext, limitBytes), + dataUsageFormatter.formatDataUsage(limitBytes), ) } diff --git a/src/com/android/settings/datausage/DataUsageUtils.java b/src/com/android/settings/datausage/DataUsageUtils.java index b73da1c3ada..e32741d037b 100644 --- a/src/com/android/settings/datausage/DataUsageUtils.java +++ b/src/com/android/settings/datausage/DataUsageUtils.java @@ -31,9 +31,6 @@ import android.provider.Settings; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; -import android.text.BidiFormatter; -import android.text.format.Formatter; -import android.text.format.Formatter.BytesResult; import android.util.Log; import com.android.settings.datausage.lib.DataUsageLib; @@ -54,19 +51,6 @@ public final class DataUsageUtils { private DataUsageUtils() { } - /** - * Format byte value to readable string using IEC units. - * - * @deprecated Use {@link com.android.settings.datausage.lib.DataUsageFormatter} instead. - */ - @Deprecated - public static CharSequence formatDataUsage(Context context, long byteValue) { - final BytesResult res = Formatter.formatBytes(context.getResources(), byteValue, - Formatter.FLAG_IEC_UNITS); - return BidiFormatter.getInstance().unicodeWrap(context.getString( - com.android.internal.R.string.fileSizeSuffix, res.value, res.units)); - } - /** * Test if device has an ethernet network connection. */ diff --git a/src/com/android/settings/datausage/lib/DataUsageFormatter.kt b/src/com/android/settings/datausage/lib/DataUsageFormatter.kt index 849ff0dc89c..271be94c97d 100644 --- a/src/com/android/settings/datausage/lib/DataUsageFormatter.kt +++ b/src/com/android/settings/datausage/lib/DataUsageFormatter.kt @@ -18,14 +18,18 @@ package com.android.settings.datausage.lib import android.content.Context import android.content.res.Resources -import android.text.format.Formatter import com.android.settingslib.spaprivileged.framework.common.BytesFormatter -class DataUsageFormatter(private val context: Context) { +class DataUsageFormatter(context: Context) { + + private val bytesFormatter = BytesFormatter(context) /** Formats the data usage. */ fun formatDataUsage(sizeBytes: Long): String = - BytesFormatter(context).format(sizeBytes, BytesFormatter.UseCase.DataUsage) + bytesFormatter.format(sizeBytes, BytesFormatter.UseCase.DataUsage) + + fun formatDataUsageWithUnits(sizeBytes: Long): BytesFormatter.Result = + bytesFormatter.formatWithUnits(sizeBytes, BytesFormatter.UseCase.DataUsage) companion object { /** @@ -35,6 +39,6 @@ class DataUsageFormatter(private val context: Context) { * in Settings, and align with other places in Settings. */ fun Resources.getBytesDisplayUnit(bytes: Long): String = - Formatter.formatBytes(this, bytes, Formatter.FLAG_IEC_UNITS).units + BytesFormatter(this).formatWithUnits(bytes, BytesFormatter.UseCase.DataUsage).units } } diff --git a/tests/robotests/src/com/android/settings/datausage/DataUsageUtilsTest.java b/tests/robotests/src/com/android/settings/datausage/DataUsageUtilsTest.java index a465d742356..f78bb472805 100644 --- a/tests/robotests/src/com/android/settings/datausage/DataUsageUtilsTest.java +++ b/tests/robotests/src/com/android/settings/datausage/DataUsageUtilsTest.java @@ -29,7 +29,6 @@ import android.content.Context; import android.content.pm.PackageManager; import android.net.ConnectivityManager; import android.telephony.TelephonyManager; -import android.util.DataUnit; import org.junit.Before; import org.junit.Test; @@ -74,14 +73,6 @@ public final class DataUsageUtilsTest { assertThat(hasMobileData).isFalse(); } - @Test - public void formatDataUsage_useIECUnit() { - final CharSequence formattedDataUsage = DataUsageUtils.formatDataUsage( - mContext, DataUnit.GIBIBYTES.toBytes(1)); - - assertThat(formattedDataUsage).isEqualTo("1.00 GB"); - } - @Test public void hasEthernet_shouldQueryEthernetSummaryForUser() throws Exception { ShadowPackageManager pm = shadowOf(RuntimeEnvironment.application.getPackageManager()); diff --git a/tests/spa_unit/src/com/android/settings/datausage/DataUsageSummaryPreferenceControllerTest.kt b/tests/spa_unit/src/com/android/settings/datausage/DataUsageSummaryPreferenceControllerTest.kt index 35a1a235bbe..afc196d8a6e 100644 --- a/tests/spa_unit/src/com/android/settings/datausage/DataUsageSummaryPreferenceControllerTest.kt +++ b/tests/spa_unit/src/com/android/settings/datausage/DataUsageSummaryPreferenceControllerTest.kt @@ -182,8 +182,8 @@ class DataUsageSummaryPreferenceControllerTest { val limitInfo = argumentCaptor { verify(preference).setLimitInfo(capture()) }.firstValue.toString() - assertThat(limitInfo).isEqualTo("1 B data warning") - verify(preference).setLabels("0 B", "1 B") + assertThat(limitInfo).isEqualTo("1 byte data warning") + verify(preference).setLabels("0 byte", "1 byte") } @Test @@ -200,8 +200,8 @@ class DataUsageSummaryPreferenceControllerTest { val limitInfo = argumentCaptor { verify(preference).setLimitInfo(capture()) }.firstValue.toString() - assertThat(limitInfo).isEqualTo("1 B data limit") - verify(preference).setLabels("0 B", "1 B") + assertThat(limitInfo).isEqualTo("1 byte data limit") + verify(preference).setLabels("0 byte", "1 byte") } @Test @@ -219,7 +219,7 @@ class DataUsageSummaryPreferenceControllerTest { verify(preference).setLimitInfo(capture()) }.firstValue.toString() assertThat(limitInfo).isEqualTo("512 MB data warning / 1.00 GB data limit") - verify(preference).setLabels("0 B", "1.00 GB") + verify(preference).setLabels("0 byte", "1.00 GB") } @Test @@ -256,7 +256,7 @@ class DataUsageSummaryPreferenceControllerTest { POSITIVE_DATA_PLAN_INFO.dataPlanSize, ) verify(preference).setChartEnabled(true) - verify(preference).setLabels("0 B", "9 B") + verify(preference).setLabels("0 byte", "9 byte") val progress = argumentCaptor { verify(preference).setProgress(capture()) }.firstValue diff --git a/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppDataUsagePreferenceTest.kt b/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppDataUsagePreferenceTest.kt index f70f5d5ad63..d493b66737d 100644 --- a/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppDataUsagePreferenceTest.kt +++ b/tests/spa_unit/src/com/android/settings/spa/app/appinfo/AppDataUsagePreferenceTest.kt @@ -134,7 +134,7 @@ class AppDataUsagePreferenceTest { setContent() - composeTestRule.waitUntilExists(hasText("123 B used since Oct 25, 2022")) + composeTestRule.waitUntilExists(hasText("123 byte used since Oct 25, 2022")) } @Test From 05f8420d875f097c2595fde77a9f15c12863322e Mon Sep 17 00:00:00 2001 From: Johannes Gallmann Date: Fri, 3 Jan 2025 14:30:26 +0000 Subject: [PATCH 05/17] Clean up predictive_back_system_anims flag Bug: 320510464 Test: Presubmit Test: Manual, i.e. verified system animations enabled on device Flag: EXEMPT flag cleanup Change-Id: Ie3b9ecd3355fcf86a1b4f597d45635b3fc794be9 --- .../BackAnimationPreferenceController.java | 94 ---------- .../DevelopmentSettingsDashboardFragment.java | 1 - ...BackAnimationPreferenceControllerTest.java | 173 ------------------ 3 files changed, 268 deletions(-) delete mode 100644 src/com/android/settings/development/BackAnimationPreferenceController.java delete mode 100644 tests/unit/src/com/android/settings/development/BackAnimationPreferenceControllerTest.java diff --git a/src/com/android/settings/development/BackAnimationPreferenceController.java b/src/com/android/settings/development/BackAnimationPreferenceController.java deleted file mode 100644 index f87ee09ef4d..00000000000 --- a/src/com/android/settings/development/BackAnimationPreferenceController.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2017 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.development; - -import static com.android.window.flags.Flags.predictiveBackSystemAnims; - -import android.content.Context; -import android.provider.Settings; - -import androidx.annotation.Nullable; -import androidx.preference.Preference; -import androidx.preference.TwoStatePreference; - -import com.android.internal.annotations.VisibleForTesting; -import com.android.settings.core.PreferenceControllerMixin; -import com.android.settingslib.development.DeveloperOptionsPreferenceController; - -/** - * PreferenceController for enabling/disabling animation related to back button and back gestures. - */ -public class BackAnimationPreferenceController extends DeveloperOptionsPreferenceController - implements Preference.OnPreferenceChangeListener, PreferenceControllerMixin { - - private static final String BACK_NAVIGATION_ANIMATION_KEY = - "back_navigation_animation"; - - private static final int SETTING_VALUE_OFF = 0; - private static final int SETTING_VALUE_ON = 1; - @Nullable private final DevelopmentSettingsDashboardFragment mFragment; - - @VisibleForTesting - BackAnimationPreferenceController(Context context) { - super(context); - mFragment = null; - } - - - public BackAnimationPreferenceController(Context context, - @Nullable DevelopmentSettingsDashboardFragment fragment) { - super(context); - mFragment = fragment; - } - - @Override - public boolean isAvailable() { - return !predictiveBackSystemAnims(); - } - - @Override - public String getPreferenceKey() { - return BACK_NAVIGATION_ANIMATION_KEY; - } - - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - final boolean isEnabled = (Boolean) newValue; - Settings.Global.putInt(mContext.getContentResolver(), - Settings.Global.ENABLE_BACK_ANIMATION, - isEnabled ? SETTING_VALUE_ON : SETTING_VALUE_OFF); - if (mFragment != null && isEnabled) { - BackAnimationPreferenceDialog.show(mFragment); - } - return true; - } - - @Override - public void updateState(Preference preference) { - final int mode = Settings.Global.getInt(mContext.getContentResolver(), - Settings.Global.ENABLE_BACK_ANIMATION, SETTING_VALUE_OFF); - ((TwoStatePreference) mPreference).setChecked(mode != SETTING_VALUE_OFF); - } - - @Override - protected void onDeveloperOptionsSwitchDisabled() { - super.onDeveloperOptionsSwitchDisabled(); - Settings.Global.putInt(mContext.getContentResolver(), - Settings.Global.ENABLE_BACK_ANIMATION, SETTING_VALUE_OFF); - ((TwoStatePreference) mPreference).setChecked(false); - } -} diff --git a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java index 605f3bbcdd8..0f8b50a542b 100644 --- a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java +++ b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java @@ -832,7 +832,6 @@ public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFra controllers.add(new OverlaySettingsPreferenceController(context)); controllers.add(new StylusHandwritingPreferenceController(context)); controllers.add(new IngressRateLimitPreferenceController((context))); - controllers.add(new BackAnimationPreferenceController(context, fragment)); controllers.add(new PhantomProcessPreferenceController(context)); controllers.add(new ForceEnableNotesRolePreferenceController(context)); controllers.add(new GrammaticalGenderPreferenceController(context)); diff --git a/tests/unit/src/com/android/settings/development/BackAnimationPreferenceControllerTest.java b/tests/unit/src/com/android/settings/development/BackAnimationPreferenceControllerTest.java deleted file mode 100644 index 1d93e88b64a..00000000000 --- a/tests/unit/src/com/android/settings/development/BackAnimationPreferenceControllerTest.java +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright (C) 2022 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.development; - -import static com.google.common.truth.Truth.assertThat; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import android.app.Instrumentation; -import android.content.ContentResolver; -import android.content.Context; -import android.database.ContentObserver; -import android.net.Uri; -import android.os.Handler; -import android.os.Looper; -import android.os.UserHandle; -import android.platform.test.annotations.RequiresFlagsDisabled; -import android.platform.test.annotations.RequiresFlagsEnabled; -import android.platform.test.flag.junit.CheckFlagsRule; -import android.platform.test.flag.junit.DeviceFlagsValueProvider; -import android.provider.Settings; - -import androidx.preference.PreferenceManager; -import androidx.preference.PreferenceScreen; -import androidx.preference.SwitchPreference; -import androidx.test.ext.junit.runners.AndroidJUnit4; -import androidx.test.platform.app.InstrumentationRegistry; - -import com.android.window.flags.Flags; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.MockitoAnnotations; - -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -@RunWith(AndroidJUnit4.class) -public class BackAnimationPreferenceControllerTest { - - private static final int SETTING_VALUE_OFF = 0; - private static final int SETTING_VALUE_ON = 1; - - private SwitchPreference mPreference; - - private Context mContext; - private BackAnimationPreferenceController mController; - private Looper mLooper; - - @Rule - public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); - mContext = instrumentation.getTargetContext(); - mController = new BackAnimationPreferenceController(mContext); - mPreference = new SwitchPreference(mContext); - if (Looper.myLooper() == null) { - Looper.prepare(); - } - mLooper = Looper.myLooper(); - - Settings.Global.putInt(mContext.getContentResolver(), - Settings.Global.ENABLE_BACK_ANIMATION, -1); - - final PreferenceManager preferenceManager = new PreferenceManager(mContext); - final PreferenceScreen screen = preferenceManager.createPreferenceScreen(mContext); - mPreference.setKey(mController.getPreferenceKey()); - screen.addPreference(mPreference); - mController.displayPreference(screen); - } - - @Test - @RequiresFlagsEnabled(Flags.FLAG_PREDICTIVE_BACK_SYSTEM_ANIMS) - public void controllerNotAvailable_whenAconfigFlagEnabled() { - assertFalse(mController.isAvailable()); - } - - @Test - @RequiresFlagsDisabled(Flags.FLAG_PREDICTIVE_BACK_SYSTEM_ANIMS) - public void controllerAvailable_whenAconfigFlagDisabled() { - assertTrue(mController.isAvailable()); - } - - @Test - public void onPreferenceChange_switchEnabled_shouldEnableBackAnimations() { - mController.onPreferenceChange(mPreference, true /* new value */); - - final int mode = Settings.Global.getInt(mContext.getContentResolver(), - Settings.Global.ENABLE_BACK_ANIMATION, -1 /* default */); - assertThat(mode).isEqualTo(SETTING_VALUE_ON); - } - - @Test - public void onPreferenceChange_switchDisabled_shouldDisableBackAnimations() { - mController.onPreferenceChange(mPreference, false /* new value */); - - final int mode = Settings.Global.getInt(mContext.getContentResolver(), - Settings.Global.ENABLE_BACK_ANIMATION, -1 /* default */); - assertThat(mode).isEqualTo(SETTING_VALUE_OFF); - } - - @Test - public void updateState_settingEnabled_preferenceShouldBeChecked() { - Settings.Global.putInt(mContext.getContentResolver(), - Settings.Global.ENABLE_BACK_ANIMATION, SETTING_VALUE_ON); - mController.updateState(mPreference); - assertTrue(mPreference.isChecked()); - } - - @Test - public void updateState_settingDisabled_preferenceShouldNotBeChecked() { - Settings.Global.putInt(mContext.getContentResolver(), - Settings.Global.ENABLE_BACK_ANIMATION, SETTING_VALUE_OFF); - - mController.updateState(mPreference); - assertFalse(mPreference.isChecked()); - } - - @Test - public void onDeveloperOptionsSwitchDisabled_shouldDisablePreference() - throws InterruptedException { - ContentResolver contentResolver = mContext.getContentResolver(); - int mode = doAndWaitForSettingChange(() -> mController.onDeveloperOptionsSwitchDisabled(), - contentResolver); - assertThat(mode).isEqualTo(SETTING_VALUE_OFF); - assertFalse(mPreference.isEnabled()); - assertFalse(mPreference.isChecked()); - } - - private int doAndWaitForSettingChange(Runnable runnable, ContentResolver contentResolver) { - CountDownLatch countDownLatch = new CountDownLatch(1); - ContentObserver settingsObserver = - new ContentObserver(new Handler(mLooper)) { - @Override - public void onChange(boolean selfChange, Uri uri) { - countDownLatch.countDown(); - } - }; - contentResolver.registerContentObserver( - Settings.Global.getUriFor(Settings.Global.ENABLE_BACK_ANIMATION), - false, settingsObserver, UserHandle.USER_SYSTEM - ); - runnable.run(); - try { - countDownLatch.await(500, TimeUnit.MILLISECONDS); - } catch (InterruptedException e) { - Assert.fail(e.getMessage()); - } - return Settings.Global.getInt(contentResolver, - Settings.Global.ENABLE_BACK_ANIMATION, -1 /* default */); - } -} From 3eff731e525161a70aeca85197f49db140462e58 Mon Sep 17 00:00:00 2001 From: Yuri Ufimtsev Date: Fri, 20 Dec 2024 14:46:53 +0000 Subject: [PATCH 06/17] Allow to open Content Protection settings externally Test: adb root && adb shell aflags enable android.view.contentprotection.flags.exported_settings_activity_enabled && adb reboot && sleep 60 && adb shell am start -a android.settings.CONTENT_PROTECTION_SETTINGS Bug: 385310040 Flag: android.view.contentprotection.flags.exported_settings_activity_enabled Change-Id: I1a5e33196051de88ceaddb638edab702f762fe5d --- Android.bp | 1 + AndroidManifest.xml | 15 +++++++++++++++ src/com/android/settings/Settings.java | 1 + .../settings/core/gateway/SettingsGateway.java | 4 +++- 4 files changed, 20 insertions(+), 1 deletion(-) diff --git a/Android.bp b/Android.bp index 0a633ac07ce..014284647e7 100644 --- a/Android.bp +++ b/Android.bp @@ -139,6 +139,7 @@ android_library { "android.app.flags-aconfig", "android.provider.flags-aconfig", "android.security.flags-aconfig", + "android.view.contentprotection.flags-aconfig", "keyboard_flags", ], } diff --git a/AndroidManifest.xml b/AndroidManifest.xml index a673920282f..f1727950896 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -5531,6 +5531,21 @@ android:value="true" /> + + + + + + + + + + diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java index e373ccccd1d..91494af29c6 100644 --- a/src/com/android/settings/Settings.java +++ b/src/com/android/settings/Settings.java @@ -528,4 +528,5 @@ public class Settings extends SettingsActivity { public static class HearingDevicesActivity extends SettingsActivity { /* empty */ } public static class HearingDevicesPairingActivity extends SettingsActivity { /* empty */ } public static class ContactsStorageSettingsActivity extends SettingsActivity { /* empty */ } + public static class ContentProtectionSettingsActivity extends SettingsActivity { /* empty */ } } diff --git a/src/com/android/settings/core/gateway/SettingsGateway.java b/src/com/android/settings/core/gateway/SettingsGateway.java index bc2ab68764c..81dc3ad3837 100644 --- a/src/com/android/settings/core/gateway/SettingsGateway.java +++ b/src/com/android/settings/core/gateway/SettingsGateway.java @@ -189,6 +189,7 @@ import com.android.settings.regionalpreferences.RegionPickerFragment; import com.android.settings.regionalpreferences.RegionalPreferencesEntriesFragment; import com.android.settings.regionalpreferences.TemperatureUnitFragment; import com.android.settings.safetycenter.MoreSecurityPrivacyFragment; +import com.android.settings.security.ContentProtectionPreferenceFragment; import com.android.settings.security.LockscreenDashboardFragment; import com.android.settings.security.MemtagPage; import com.android.settings.security.SecurityAdvancedSettings; @@ -415,7 +416,8 @@ public class SettingsGateway { HearingDevicePairingFragment.class.getName(), ZenModesListFragment.class.getName(), ZenModeFragment.class.getName(), - ContactsStorageSettings.class.getName() + ContactsStorageSettings.class.getName(), + ContentProtectionPreferenceFragment.class.getName(), }; public static final String[] SETTINGS_FOR_RESTRICTED = { From 4668c58347648f2c01e517f11cb5b038139f6f6c Mon Sep 17 00:00:00 2001 From: chelseahao Date: Mon, 6 Jan 2025 19:47:56 +0800 Subject: [PATCH 07/17] Fix play/pause button. Test: atest Bug: 385844038 Flag: com.android.settingslib.flags.enable_le_audio_sharing Change-Id: I2007f5d4ade3254f2eeb6e5fa6ed677772083376 --- .../audiosharing/audiostreams/AudioStreamMediaService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamMediaService.java b/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamMediaService.java index 5d26352674f..322fd3cad19 100644 --- a/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamMediaService.java +++ b/src/com/android/settings/connecteddevice/audiosharing/audiostreams/AudioStreamMediaService.java @@ -77,7 +77,7 @@ public class AudioStreamMediaService extends Service { private static final int ZERO_PLAYBACK_SPEED = 0; private final PlaybackState.Builder mPlayStatePlayingBuilder = new PlaybackState.Builder() - .setActions(PlaybackState.ACTION_PAUSE | PlaybackState.ACTION_SEEK_TO) + .setActions(PlaybackState.ACTION_PLAY_PAUSE | PlaybackState.ACTION_SEEK_TO) .setState( PlaybackState.STATE_PLAYING, STATIC_PLAYBACK_POSITION, @@ -88,7 +88,7 @@ public class AudioStreamMediaService extends Service { com.android.settings.R.drawable.ic_clear); private final PlaybackState.Builder mPlayStatePausingBuilder = new PlaybackState.Builder() - .setActions(PlaybackState.ACTION_PLAY | PlaybackState.ACTION_SEEK_TO) + .setActions(PlaybackState.ACTION_PLAY_PAUSE | PlaybackState.ACTION_SEEK_TO) .setState( PlaybackState.STATE_PAUSED, STATIC_PLAYBACK_POSITION, From c1b478c9cb3b576fe4dcbe2c5377e9ab6d28f764 Mon Sep 17 00:00:00 2001 From: Victor Li Date: Sun, 5 Jan 2025 19:39:07 -0800 Subject: [PATCH 08/17] Set audiostreams service exported=true with BLUETOOTH_PRIVILEGED permission. Bug: 387887193 Change-Id: Ie80d8ad9ae3d169eda04d1f4cc87da71c34cbd44 --- AndroidManifest.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 32f786a12e2..65b62bfbb0e 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -5477,7 +5477,8 @@ android:name="com.android.settings.connecteddevice.audiosharing.audiostreams.AudioStreamMediaService" android:foregroundServiceType="mediaPlayback" android:enabled="true" - android:exported="false" /> + android:exported="true" + android:permission="android.permission.BLUETOOTH_PRIVILEGED" /> From c3426d0a871c958a048c5267ecab2160f1215758 Mon Sep 17 00:00:00 2001 From: YuhanYang Date: Fri, 13 Dec 2024 00:59:11 +0000 Subject: [PATCH 09/17] Add preference toggle for mouse scrolling acceleration Bug: 383555305 Bug: 384795606 Test: Local DUT with aconfig flags enabled, verified settings appears and is togglable. Verified toggle affects scrolling acceleration. Flag: com.android.hardware.input.mouse_scrolling_acceleration Change-Id: Ibba2bb1c3cb57b98ad34a5851bae7b9d73e48d74 --- res/values/strings.xml | 3 + res/xml/mouse_settings.xml | 5 + res/xml/touchpad_and_mouse_settings.xml | 6 + ...llingAccelerationPreferenceController.java | 57 ++++++++ ...gAccelerationPreferenceControllerTest.java | 122 ++++++++++++++++++ 5 files changed, 193 insertions(+) create mode 100644 src/com/android/settings/inputmethod/MouseScrollingAccelerationPreferenceController.java create mode 100644 tests/robotests/src/com/android/settings/inputmethod/MouseScrollingAccelerationPreferenceControllerTest.java diff --git a/res/values/strings.xml b/res/values/strings.xml index 762288cc6f3..0b3330b17e3 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -4675,6 +4675,9 @@ Mouse reverse scrolling Scroll up to move the page down + + + Controlled scrolling Swap left and right buttons diff --git a/res/xml/mouse_settings.xml b/res/xml/mouse_settings.xml index 0abfdd0c364..dbd87111802 100644 --- a/res/xml/mouse_settings.xml +++ b/res/xml/mouse_settings.xml @@ -37,4 +37,9 @@ android:title="@string/mouse_pointer_acceleration" android:summary="@string/mouse_pointer_acceleration_summary" settings:controller="com.android.settings.inputmethod.MousePointerAccelerationPreferenceController" /> + + diff --git a/res/xml/touchpad_and_mouse_settings.xml b/res/xml/touchpad_and_mouse_settings.xml index c470a729ccb..bc9f8427e6f 100644 --- a/res/xml/touchpad_and_mouse_settings.xml +++ b/res/xml/touchpad_and_mouse_settings.xml @@ -75,6 +75,12 @@ settings:controller="com.android.settings.inputmethod.MouseSwapPrimaryButtonPreferenceController" android:order="47"/> + + Date: Tue, 7 Jan 2025 00:53:16 +0000 Subject: [PATCH 10/17] a11y: Initialize skeleton for autoclick indicator related settings Screenshot: http://screen/5wWt8Tvr9K3fuoi.png Change-Id: Iaf07e738d64e0e22caf7571a7529cccbf3079f87 Bug: b/383901288 Test: ToggleAutoclickCursorAreaSizeControllerTest Flag: com.android.server.accessibility.enable_autoclick_indicator --- res/values/strings.xml | 6 + res/xml/accessibility_autoclick_settings.xml | 9 ++ ...ggleAutoclickCursorAreaSizeController.java | 101 +++++++++++++++++ ...AutoclickCursorAreaSizeControllerTest.java | 103 ++++++++++++++++++ 4 files changed, 219 insertions(+) create mode 100644 src/com/android/settings/accessibility/ToggleAutoclickCursorAreaSizeController.java create mode 100644 tests/robotests/src/com/android/settings/accessibility/ToggleAutoclickCursorAreaSizeControllerTest.java diff --git a/res/values/strings.xml b/res/values/strings.xml index 4d843fb85cf..9eed075ab8a 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -5584,6 +5584,12 @@ Longer Auto click time + + + Cursor area size + + + Adjust the autoclick ring indicator area size Vibration & haptics diff --git a/res/xml/accessibility_autoclick_settings.xml b/res/xml/accessibility_autoclick_settings.xml index 3a1bcd3aa05..72371f3e993 100644 --- a/res/xml/accessibility_autoclick_settings.xml +++ b/res/xml/accessibility_autoclick_settings.xml @@ -76,6 +76,15 @@ settings:searchable="false" settings:controller="com.android.settings.accessibility.ToggleAutoclickCustomSeekbarController"/> + + Date: Mon, 16 Dec 2024 22:04:36 +0000 Subject: [PATCH 11/17] Support Double Tap Power to open camera via config resource "Quickly open camera" screen was previously replaced by the "Double Tap Power Button" screen and accessible only if the feature flag android.service.quickaccesswallet.launch_wallet_option_on_power_double_tap was disabled. This CL introduces the possibility to set, via a config resource, "Quickly open camera" as the double tap power gesture screen. Test: atest DoubleTapPowerSettingsTest Test: atest DoubleTapPowerPreferenceControllerTest Test: atest DoubleTapPowerSettingsUtilsTest Test: manually modified config and verified screen and gesture behavior change Flag: android.service.quickaccesswallet.launch_wallet_option_on_power_double_tap Bug: 384794943 Change-Id: I5ab4422da09fa90848c66a41829327494080b5a2 Change-Id: I8e04cac3999a7ed99a611ef084c54bc07a5505dc --- ...TapPowerForCameraPreferenceController.java | 3 +- ...TapPowerForWalletPreferenceController.java | 3 +- ...apPowerMainSwitchPreferenceController.java | 3 +- .../DoubleTapPowerPreferenceController.java | 26 +++- .../gestures/DoubleTapPowerSettings.java | 18 ++- .../gestures/DoubleTapPowerSettingsUtils.java | 40 +++-- ...owerForCameraPreferenceControllerTest.java | 12 +- ...owerForWalletPreferenceControllerTest.java | 12 +- ...werMainSwitchPreferenceControllerTest.java | 9 +- ...oubleTapPowerPreferenceControllerTest.java | 145 +++++++++++++----- .../gestures/DoubleTapPowerSettingsTest.java | 56 ++++++- .../DoubleTapPowerSettingsUtilsTest.java | 70 +++++---- 12 files changed, 285 insertions(+), 112 deletions(-) diff --git a/src/com/android/settings/gestures/DoubleTapPowerForCameraPreferenceController.java b/src/com/android/settings/gestures/DoubleTapPowerForCameraPreferenceController.java index 0c7c65a7ffa..77a8a9b64f9 100644 --- a/src/com/android/settings/gestures/DoubleTapPowerForCameraPreferenceController.java +++ b/src/com/android/settings/gestures/DoubleTapPowerForCameraPreferenceController.java @@ -65,7 +65,8 @@ public class DoubleTapPowerForCameraPreferenceController extends BasePreferenceC @Override public int getAvailabilityStatus() { - if (!DoubleTapPowerSettingsUtils.isDoubleTapPowerButtonGestureAvailable(mContext)) { + if (!DoubleTapPowerSettingsUtils + .isMultiTargetDoubleTapPowerButtonGestureAvailable(mContext)) { return UNSUPPORTED_ON_DEVICE; } return DoubleTapPowerSettingsUtils.isDoubleTapPowerButtonGestureEnabled(mContext) diff --git a/src/com/android/settings/gestures/DoubleTapPowerForWalletPreferenceController.java b/src/com/android/settings/gestures/DoubleTapPowerForWalletPreferenceController.java index 56dda4d4953..9efeb9c3304 100644 --- a/src/com/android/settings/gestures/DoubleTapPowerForWalletPreferenceController.java +++ b/src/com/android/settings/gestures/DoubleTapPowerForWalletPreferenceController.java @@ -65,7 +65,8 @@ public class DoubleTapPowerForWalletPreferenceController extends BasePreferenceC @Override public int getAvailabilityStatus() { - if (!DoubleTapPowerSettingsUtils.isDoubleTapPowerButtonGestureAvailable(mContext)) { + if (!DoubleTapPowerSettingsUtils + .isMultiTargetDoubleTapPowerButtonGestureAvailable(mContext)) { return UNSUPPORTED_ON_DEVICE; } return DoubleTapPowerSettingsUtils.isDoubleTapPowerButtonGestureEnabled(mContext) diff --git a/src/com/android/settings/gestures/DoubleTapPowerMainSwitchPreferenceController.java b/src/com/android/settings/gestures/DoubleTapPowerMainSwitchPreferenceController.java index 3eb18eb931d..4a6d328b59e 100644 --- a/src/com/android/settings/gestures/DoubleTapPowerMainSwitchPreferenceController.java +++ b/src/com/android/settings/gestures/DoubleTapPowerMainSwitchPreferenceController.java @@ -57,7 +57,8 @@ public class DoubleTapPowerMainSwitchPreferenceController @Override public int getAvailabilityStatus() { - return DoubleTapPowerSettingsUtils.isDoubleTapPowerButtonGestureAvailable(mContext) + return DoubleTapPowerSettingsUtils + .isMultiTargetDoubleTapPowerButtonGestureAvailable(mContext) ? AVAILABLE : UNSUPPORTED_ON_DEVICE; } diff --git a/src/com/android/settings/gestures/DoubleTapPowerPreferenceController.java b/src/com/android/settings/gestures/DoubleTapPowerPreferenceController.java index 686d64cf1f5..ee3f5f01718 100644 --- a/src/com/android/settings/gestures/DoubleTapPowerPreferenceController.java +++ b/src/com/android/settings/gestures/DoubleTapPowerPreferenceController.java @@ -18,6 +18,8 @@ package com.android.settings.gestures; import static android.provider.Settings.Secure.CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED; +import static com.android.settings.gestures.DoubleTapPowerSettingsUtils.DOUBLE_TAP_POWER_DISABLED_MODE; + import android.content.Context; import android.content.SharedPreferences; import android.provider.Settings; @@ -37,7 +39,8 @@ public class DoubleTapPowerPreferenceController extends BasePreferenceController public static boolean isSuggestionComplete(Context context, SharedPreferences prefs) { return !isGestureAvailable(context) - || prefs.getBoolean(DoubleTapPowerSettings.PREF_KEY_SUGGESTION_COMPLETE, false); + || prefs.getBoolean(DoubleTapPowerSettings.PREF_KEY_SUGGESTION_COMPLETE, + false); } private static boolean isGestureAvailable(@NonNull Context context) { @@ -46,7 +49,10 @@ public class DoubleTapPowerPreferenceController extends BasePreferenceController .getBoolean( com.android.internal.R.bool.config_cameraDoubleTapPowerGestureEnabled); } - return DoubleTapPowerSettingsUtils.isDoubleTapPowerButtonGestureAvailable(context); + return context.getResources() + .getInteger( + com.android.internal.R.integer.config_doubleTapPowerGestureMode) + != DOUBLE_TAP_POWER_DISABLED_MODE; } @Override @@ -56,7 +62,9 @@ public class DoubleTapPowerPreferenceController extends BasePreferenceController @Override public void displayPreference(@NonNull PreferenceScreen screen) { - if (!android.service.quickaccesswallet.Flags.launchWalletOptionOnPowerDoubleTap()) { + if (!android.service.quickaccesswallet.Flags.launchWalletOptionOnPowerDoubleTap() + || !DoubleTapPowerSettingsUtils + .isMultiTargetDoubleTapPowerButtonGestureAvailable(mContext)) { final Preference preference = screen.findPreference(getPreferenceKey()); if (preference != null) { preference.setTitle(R.string.double_tap_power_for_camera_title); @@ -68,12 +76,14 @@ public class DoubleTapPowerPreferenceController extends BasePreferenceController @Override @NonNull public CharSequence getSummary() { - if (!android.service.quickaccesswallet.Flags.launchWalletOptionOnPowerDoubleTap()) { + if (!android.service.quickaccesswallet.Flags.launchWalletOptionOnPowerDoubleTap() + || !DoubleTapPowerSettingsUtils + .isMultiTargetDoubleTapPowerButtonGestureAvailable(mContext)) { final boolean isCameraDoubleTapPowerGestureEnabled = Settings.Secure.getInt( - mContext.getContentResolver(), - CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, - DoubleTapPowerToOpenCameraPreferenceController.ON) + mContext.getContentResolver(), + CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, + DoubleTapPowerToOpenCameraPreferenceController.ON) == DoubleTapPowerToOpenCameraPreferenceController.ON; return mContext.getText( isCameraDoubleTapPowerGestureEnabled @@ -85,7 +95,7 @@ public class DoubleTapPowerPreferenceController extends BasePreferenceController mContext.getText(com.android.settings.R.string.gesture_setting_on); final CharSequence actionString = DoubleTapPowerSettingsUtils.isDoubleTapPowerButtonGestureForCameraLaunchEnabled( - mContext) + 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); diff --git a/src/com/android/settings/gestures/DoubleTapPowerSettings.java b/src/com/android/settings/gestures/DoubleTapPowerSettings.java index 076f23fa660..892eb4a5422 100644 --- a/src/com/android/settings/gestures/DoubleTapPowerSettings.java +++ b/src/com/android/settings/gestures/DoubleTapPowerSettings.java @@ -39,9 +39,11 @@ public class DoubleTapPowerSettings extends DashboardFragment { public static final String PREF_KEY_SUGGESTION_COMPLETE = "pref_double_tap_power_suggestion_complete"; + private Context mContext; @Override public void onAttach(Context context) { + mContext = context; super.onAttach(context); SuggestionFeatureProvider suggestionFeatureProvider = FeatureFactory.getFeatureFactory().getSuggestionFeatureProvider(); @@ -61,7 +63,15 @@ public class DoubleTapPowerSettings extends DashboardFragment { @Override protected int getPreferenceScreenResId() { - return android.service.quickaccesswallet.Flags.launchWalletOptionOnPowerDoubleTap() + return getDoubleTapPowerSettingsResId(mContext); + } + + private static int getDoubleTapPowerSettingsResId(Context context) { + if (!android.service.quickaccesswallet.Flags.launchWalletOptionOnPowerDoubleTap()) { + return R.xml.double_tap_power_to_open_camera_settings; + } + return DoubleTapPowerSettingsUtils + .isMultiTargetDoubleTapPowerButtonGestureAvailable(context) ? R.xml.double_tap_power_settings : R.xml.double_tap_power_to_open_camera_settings; } @@ -73,11 +83,7 @@ public class DoubleTapPowerSettings extends DashboardFragment { 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; + sir.xmlResId = getDoubleTapPowerSettingsResId(context); return List.of(sir); } }; diff --git a/src/com/android/settings/gestures/DoubleTapPowerSettingsUtils.java b/src/com/android/settings/gestures/DoubleTapPowerSettingsUtils.java index a1bf9cbd48c..6347c0f48c5 100644 --- a/src/com/android/settings/gestures/DoubleTapPowerSettingsUtils.java +++ b/src/com/android/settings/gestures/DoubleTapPowerSettingsUtils.java @@ -29,6 +29,16 @@ import com.android.internal.R; /** Common code for double tap power settings shared between controllers. */ final class DoubleTapPowerSettingsUtils { + /** Configuration value indicating double tap power button gesture is disabled. */ + static final int DOUBLE_TAP_POWER_DISABLED_MODE = 0; + /** Configuration value indicating double tap power button gesture should launch camera. */ + static final int DOUBLE_TAP_POWER_LAUNCH_CAMERA_MODE = 1; + /** + * Configuration value indicating double tap power button gesture should launch one of many + * target actions. + */ + static final int DOUBLE_TAP_POWER_MULTI_TARGET_MODE = 2; + /** Setting storing whether the double tap power button gesture is enabled. */ private static final String DOUBLE_TAP_POWER_BUTTON_GESTURE_ENABLED = Settings.Secure.DOUBLE_TAP_POWER_BUTTON_GESTURE_ENABLED; @@ -52,19 +62,23 @@ final class DoubleTapPowerSettingsUtils { /** * @return true if double tap power button gesture is available. */ - public static boolean isDoubleTapPowerButtonGestureAvailable(@NonNull Context context) { - return context.getResources().getBoolean(R.bool.config_doubleTapPowerGestureEnabled); + public static boolean isMultiTargetDoubleTapPowerButtonGestureAvailable( + @NonNull Context context) { + return context.getResources() + .getInteger( + R.integer.config_doubleTapPowerGestureMode) + == DOUBLE_TAP_POWER_MULTI_TARGET_MODE; } /** * Gets double tap power button gesture enable or disable flag from Settings provider. * - * @return true if double tap on the power button gesture is currently enabled. * @param context App context + * @return true if double tap on the power button gesture is currently enabled. */ public static boolean isDoubleTapPowerButtonGestureEnabled(@NonNull Context context) { return Settings.Secure.getInt( - context.getContentResolver(), DOUBLE_TAP_POWER_BUTTON_GESTURE_ENABLED, ON) + context.getContentResolver(), DOUBLE_TAP_POWER_BUTTON_GESTURE_ENABLED, ON) == ON; } @@ -72,7 +86,7 @@ final class DoubleTapPowerSettingsUtils { * Sets double tap power button gesture enable or disable flag to Settings provider. * * @param context App context - * @param enable enable or disable double tap power button gesture. + * @param enable enable or disable double tap power button gesture. * @return {@code true} if the setting is updated. */ public static boolean setDoubleTapPowerButtonGestureEnabled( @@ -84,19 +98,19 @@ final class DoubleTapPowerSettingsUtils { } /** - * @return true if double tap on the power button gesture for camera launch is currently - * enabled. * @param context App context + * @return true if double tap on the power button gesture for camera launch is currently + * enabled. */ public static boolean isDoubleTapPowerButtonGestureForCameraLaunchEnabled( @NonNull Context context) { return Settings.Secure.getInt( - context.getContentResolver(), - DOUBLE_TAP_POWER_BUTTON_GESTURE_TARGET_ACTION, - context.getResources() - .getInteger( - com.android.internal.R.integer - .config_defaultDoubleTapPowerGestureAction)) + context.getContentResolver(), + DOUBLE_TAP_POWER_BUTTON_GESTURE_TARGET_ACTION, + context.getResources() + .getInteger( + com.android.internal.R.integer + .config_doubleTapPowerGestureMultiTargetDefaultAction)) == DOUBLE_TAP_POWER_BUTTON_CAMERA_LAUNCH_VALUE; } diff --git a/tests/robotests/src/com/android/settings/gestures/DoubleTapPowerForCameraPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/DoubleTapPowerForCameraPreferenceControllerTest.java index cc710ec29e6..1647a9c1862 100644 --- a/tests/robotests/src/com/android/settings/gestures/DoubleTapPowerForCameraPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/gestures/DoubleTapPowerForCameraPreferenceControllerTest.java @@ -16,6 +16,9 @@ package com.android.settings.gestures; +import static com.android.settings.gestures.DoubleTapPowerSettingsUtils.DOUBLE_TAP_POWER_DISABLED_MODE; +import static com.android.settings.gestures.DoubleTapPowerSettingsUtils.DOUBLE_TAP_POWER_MULTI_TARGET_MODE; + import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.mock; @@ -72,7 +75,8 @@ public class DoubleTapPowerForCameraPreferenceControllerTest { @Test public void getAvailabilityStatus_setDoubleTapPowerGestureNotAvailable_preferenceUnsupported() { - when(mResources.getBoolean(R.bool.config_doubleTapPowerGestureEnabled)).thenReturn(false); + when(mResources.getInteger(R.integer.config_doubleTapPowerGestureMode)).thenReturn( + DOUBLE_TAP_POWER_DISABLED_MODE); assertThat(mController.getAvailabilityStatus()) .isEqualTo(BasePreferenceController.UNSUPPORTED_ON_DEVICE); @@ -80,7 +84,8 @@ public class DoubleTapPowerForCameraPreferenceControllerTest { @Test public void getAvailabilityStatus_setDoubleTapPowerButtonDisabled_preferenceDisabled() { - when(mResources.getBoolean(R.bool.config_doubleTapPowerGestureEnabled)).thenReturn(true); + when(mResources.getInteger(R.integer.config_doubleTapPowerGestureMode)).thenReturn( + DOUBLE_TAP_POWER_MULTI_TARGET_MODE); DoubleTapPowerSettingsUtils.setDoubleTapPowerButtonGestureEnabled(mContext, false); assertThat(mController.getAvailabilityStatus()) @@ -89,7 +94,8 @@ public class DoubleTapPowerForCameraPreferenceControllerTest { @Test public void getAvailabilityStatus_setDoubleTapPowerCameraLaunchEnabled_preferenceEnabled() { - when(mResources.getBoolean(R.bool.config_doubleTapPowerGestureEnabled)).thenReturn(true); + when(mResources.getInteger(R.integer.config_doubleTapPowerGestureMode)).thenReturn( + DOUBLE_TAP_POWER_MULTI_TARGET_MODE); DoubleTapPowerSettingsUtils.setDoubleTapPowerButtonGestureEnabled(mContext, true); assertThat(mController.getAvailabilityStatus()) diff --git a/tests/robotests/src/com/android/settings/gestures/DoubleTapPowerForWalletPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/DoubleTapPowerForWalletPreferenceControllerTest.java index c86a82edd0d..60b35102d99 100644 --- a/tests/robotests/src/com/android/settings/gestures/DoubleTapPowerForWalletPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/gestures/DoubleTapPowerForWalletPreferenceControllerTest.java @@ -16,6 +16,9 @@ package com.android.settings.gestures; +import static com.android.settings.gestures.DoubleTapPowerSettingsUtils.DOUBLE_TAP_POWER_DISABLED_MODE; +import static com.android.settings.gestures.DoubleTapPowerSettingsUtils.DOUBLE_TAP_POWER_MULTI_TARGET_MODE; + import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.mock; @@ -74,7 +77,8 @@ public class DoubleTapPowerForWalletPreferenceControllerTest { @Test public void getAvailabilityStatus_setDoubleTapPowerGestureNotAvailable_preferenceUnsupported() { - when(mResources.getBoolean(R.bool.config_doubleTapPowerGestureEnabled)).thenReturn(false); + when(mResources.getInteger(R.integer.config_doubleTapPowerGestureMode)).thenReturn( + DOUBLE_TAP_POWER_DISABLED_MODE); assertThat(mController.getAvailabilityStatus()) .isEqualTo(BasePreferenceController.UNSUPPORTED_ON_DEVICE); @@ -82,7 +86,8 @@ public class DoubleTapPowerForWalletPreferenceControllerTest { @Test public void getAvailabilityStatus_setDoubleTapPowerButtonDisabled_preferenceDisabled() { - when(mResources.getBoolean(R.bool.config_doubleTapPowerGestureEnabled)).thenReturn(true); + when(mResources.getInteger(R.integer.config_doubleTapPowerGestureMode)).thenReturn( + DOUBLE_TAP_POWER_MULTI_TARGET_MODE); DoubleTapPowerSettingsUtils.setDoubleTapPowerButtonGestureEnabled(mContext, false); assertThat(mController.getAvailabilityStatus()) @@ -91,7 +96,8 @@ public class DoubleTapPowerForWalletPreferenceControllerTest { @Test public void getAvailabilityStatus_setDoubleTapPowerWalletLaunchEnabled_preferenceEnabled() { - when(mResources.getBoolean(R.bool.config_doubleTapPowerGestureEnabled)).thenReturn(true); + when(mResources.getInteger(R.integer.config_doubleTapPowerGestureMode)).thenReturn( + DOUBLE_TAP_POWER_MULTI_TARGET_MODE); DoubleTapPowerSettingsUtils.setDoubleTapPowerButtonGestureEnabled(mContext, true); assertThat(mController.getAvailabilityStatus()) diff --git a/tests/robotests/src/com/android/settings/gestures/DoubleTapPowerMainSwitchPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/DoubleTapPowerMainSwitchPreferenceControllerTest.java index 502e52ec6c3..5d9656c466b 100644 --- a/tests/robotests/src/com/android/settings/gestures/DoubleTapPowerMainSwitchPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/gestures/DoubleTapPowerMainSwitchPreferenceControllerTest.java @@ -16,6 +16,9 @@ package com.android.settings.gestures; +import static com.android.settings.gestures.DoubleTapPowerSettingsUtils.DOUBLE_TAP_POWER_DISABLED_MODE; +import static com.android.settings.gestures.DoubleTapPowerSettingsUtils.DOUBLE_TAP_POWER_MULTI_TARGET_MODE; + import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.mock; @@ -54,7 +57,8 @@ public class DoubleTapPowerMainSwitchPreferenceControllerTest { @Test public void getAvailabilityStatus_setDoubleTapPowerGestureAvailable_preferenceEnabled() { - when(mResources.getBoolean(R.bool.config_doubleTapPowerGestureEnabled)).thenReturn(true); + when(mResources.getInteger(R.integer.config_doubleTapPowerGestureMode)).thenReturn( + DOUBLE_TAP_POWER_MULTI_TARGET_MODE); assertThat(mController.getAvailabilityStatus()) .isEqualTo(BasePreferenceController.AVAILABLE); @@ -62,7 +66,8 @@ public class DoubleTapPowerMainSwitchPreferenceControllerTest { @Test public void getAvailabilityStatus_setDoubleTapPowerGestureUnavailable_preferenceUnsupported() { - when(mResources.getBoolean(R.bool.config_doubleTapPowerGestureEnabled)).thenReturn(false); + when(mResources.getInteger(R.integer.config_doubleTapPowerGestureMode)).thenReturn( + DOUBLE_TAP_POWER_DISABLED_MODE); assertThat(mController.getAvailabilityStatus()) .isEqualTo(BasePreferenceController.UNSUPPORTED_ON_DEVICE); diff --git a/tests/robotests/src/com/android/settings/gestures/DoubleTapPowerPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/gestures/DoubleTapPowerPreferenceControllerTest.java index 17b03f355bf..b2ff5a65b59 100644 --- a/tests/robotests/src/com/android/settings/gestures/DoubleTapPowerPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/gestures/DoubleTapPowerPreferenceControllerTest.java @@ -20,6 +20,9 @@ import static android.provider.Settings.Secure.CAMERA_DOUBLE_TAP_POWER_GESTURE_D 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.DoubleTapPowerSettingsUtils.DOUBLE_TAP_POWER_DISABLED_MODE; +import static com.android.settings.gestures.DoubleTapPowerSettingsUtils.DOUBLE_TAP_POWER_LAUNCH_CAMERA_MODE; +import static com.android.settings.gestures.DoubleTapPowerSettingsUtils.DOUBLE_TAP_POWER_MULTI_TARGET_MODE; import static com.android.settings.gestures.DoubleTapPowerToOpenCameraPreferenceController.OFF; import static com.android.settings.gestures.DoubleTapPowerToOpenCameraPreferenceController.ON; @@ -58,7 +61,8 @@ import org.robolectric.annotation.Config; @Config(shadows = SettingsShadowResources.class) public class DoubleTapPowerPreferenceControllerTest { - @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); + @Rule + public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); private Context mContext; private ContentResolver mContentResolver; private DoubleTapPowerPreferenceController mController; @@ -83,18 +87,30 @@ public class DoubleTapPowerPreferenceControllerTest { @Test @EnableFlags(Flags.FLAG_LAUNCH_WALLET_OPTION_ON_POWER_DOUBLE_TAP) - public void isAvailable_flagEnabled_configIsTrue_returnsTrue() { + public void isAvailable_flagEnabled_configIsMultiTargetMode_returnsTrue() { SettingsShadowResources.overrideResource( - com.android.internal.R.bool.config_doubleTapPowerGestureEnabled, Boolean.TRUE); + com.android.internal.R.integer.config_doubleTapPowerGestureMode, + DOUBLE_TAP_POWER_MULTI_TARGET_MODE); assertThat(mController.isAvailable()).isTrue(); } @Test @EnableFlags(Flags.FLAG_LAUNCH_WALLET_OPTION_ON_POWER_DOUBLE_TAP) - public void isAvailable_flagEnabled_configIsFalse_returnsFalse() { + public void isAvailable_flagEnabled_configIsCameraLaunchMode_returnsTrue() { SettingsShadowResources.overrideResource( - com.android.internal.R.bool.config_doubleTapPowerGestureEnabled, Boolean.FALSE); + com.android.internal.R.integer.config_doubleTapPowerGestureMode, + DOUBLE_TAP_POWER_LAUNCH_CAMERA_MODE); + + assertThat(mController.isAvailable()).isTrue(); + } + + @Test + @EnableFlags(Flags.FLAG_LAUNCH_WALLET_OPTION_ON_POWER_DOUBLE_TAP) + public void isAvailable_flagEnabled_configIsDisabledMode_returnsFalse() { + SettingsShadowResources.overrideResource( + com.android.internal.R.integer.config_doubleTapPowerGestureMode, + DOUBLE_TAP_POWER_DISABLED_MODE); assertThat(mController.isAvailable()).isFalse(); } @@ -121,18 +137,20 @@ public class DoubleTapPowerPreferenceControllerTest { @Test @EnableFlags(Flags.FLAG_LAUNCH_WALLET_OPTION_ON_POWER_DOUBLE_TAP) - public void isSuggestionCompleted_enableFlag_doubleTapPower_trueWhenNotAvailable() { + public void isSuggestionCompleted_flagEnabled_configIsMultiTargetMode_trueWhenNotAvailable() { SettingsShadowResources.overrideResource( - com.android.internal.R.bool.config_doubleTapPowerGestureEnabled, false); + com.android.internal.R.integer.config_doubleTapPowerGestureMode, + DOUBLE_TAP_POWER_DISABLED_MODE); assertThat(isSuggestionComplete(mContext, null /* prefs */)).isTrue(); } @Test @EnableFlags(Flags.FLAG_LAUNCH_WALLET_OPTION_ON_POWER_DOUBLE_TAP) - public void isSuggestionCompleted_enableFlag_doubleTapPower_falseWhenNotVisited() { + public void isSuggestionCompleted_enableFlag_configIsMultiTargetMode_falseWhenNotVisited() { SettingsShadowResources.overrideResource( - com.android.internal.R.bool.config_doubleTapPowerGestureEnabled, true); + com.android.internal.R.integer.config_doubleTapPowerGestureMode, + DOUBLE_TAP_POWER_MULTI_TARGET_MODE); // No stored value in shared preferences if not visited yet. final SharedPreferences prefs = new SuggestionFeatureProviderImpl().getSharedPrefs(mContext); @@ -142,9 +160,10 @@ public class DoubleTapPowerPreferenceControllerTest { @Test @EnableFlags(Flags.FLAG_LAUNCH_WALLET_OPTION_ON_POWER_DOUBLE_TAP) - public void isSuggestionCompleted_enableFlag_doubleTapPower_trueWhenVisited() { + public void isSuggestionCompleted_enableFlag_configIsMultiTargetMode_trueWhenVisited() { SettingsShadowResources.overrideResource( - com.android.internal.R.bool.config_doubleTapPowerGestureEnabled, true); + com.android.internal.R.integer.config_doubleTapPowerGestureMode, + DOUBLE_TAP_POWER_MULTI_TARGET_MODE); // No stored value in shared preferences if not visited yet. final SharedPreferences prefs = new SuggestionFeatureProviderImpl().getSharedPrefs(mContext); @@ -189,13 +208,30 @@ public class DoubleTapPowerPreferenceControllerTest { @Test @DisableFlags(Flags.FLAG_LAUNCH_WALLET_OPTION_ON_POWER_DOUBLE_TAP) - public void displayPreference_flagDisabled_doubleTapPowerLegacyTitleIsDisplayed() { + public void displayPreference_flagDisabled_cameraLaunchTitleIsDisplayed() { mController.displayPreference(mScreen); assertThat( - TextUtils.equals( - mPreference.getTitle(), - mContext.getText(R.string.double_tap_power_for_camera_title))) + TextUtils.equals( + mPreference.getTitle(), + mContext.getText(R.string.double_tap_power_for_camera_title))) + .isTrue(); + } + + @Test + @EnableFlags(Flags.FLAG_LAUNCH_WALLET_OPTION_ON_POWER_DOUBLE_TAP) + public void + displayPreference_flagEnabled_configIsCameraLaunchMode_cameraLaunchTitleIsDisplayed() { + SettingsShadowResources.overrideResource( + com.android.internal.R.integer.config_doubleTapPowerGestureMode, + DOUBLE_TAP_POWER_LAUNCH_CAMERA_MODE); + + mController.displayPreference(mScreen); + + assertThat( + TextUtils.equals( + mPreference.getTitle(), + mContext.getText(R.string.double_tap_power_for_camera_title))) .isTrue(); } @@ -206,9 +242,9 @@ public class DoubleTapPowerPreferenceControllerTest { Settings.Secure.putInt(mContentResolver, CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, ON); assertThat( - TextUtils.equals( - mController.getSummary(), - mContext.getText(R.string.gesture_setting_on))) + TextUtils.equals( + mController.getSummary(), + mContext.getText(R.string.gesture_setting_on))) .isTrue(); } @@ -219,9 +255,42 @@ public class DoubleTapPowerPreferenceControllerTest { Settings.Secure.putInt(mContentResolver, CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, OFF); assertThat( - TextUtils.equals( - mController.getSummary(), - mContext.getText(R.string.gesture_setting_off))) + 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_configIsCameraLaunchMode_returnsOn() { + // Set the setting to be enabled. + Settings.Secure.putInt(mContentResolver, CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, ON); + SettingsShadowResources.overrideResource( + com.android.internal.R.integer.config_doubleTapPowerGestureMode, + DOUBLE_TAP_POWER_LAUNCH_CAMERA_MODE); + + assertThat( + TextUtils.equals( + mController.getSummary(), + mContext.getText(R.string.gesture_setting_on))) + .isTrue(); + } + + @Test + @EnableFlags(Flags.FLAG_LAUNCH_WALLET_OPTION_ON_POWER_DOUBLE_TAP) + public void + getSummary_flagEnabled_doubleTapPowerDisabled_configIsCameraLaunchMode_returnsOff() { + // Set the setting to be disabled. + Settings.Secure.putInt(mContentResolver, CAMERA_DOUBLE_TAP_POWER_GESTURE_DISABLED, OFF); + SettingsShadowResources.overrideResource( + com.android.internal.R.integer.config_doubleTapPowerGestureMode, + DOUBLE_TAP_POWER_LAUNCH_CAMERA_MODE); + + assertThat( + TextUtils.equals( + mController.getSummary(), + mContext.getText(R.string.gesture_setting_off))) .isTrue(); } @@ -233,9 +302,9 @@ public class DoubleTapPowerPreferenceControllerTest { mContentResolver, DOUBLE_TAP_POWER_BUTTON_GESTURE_ENABLED, 0 /* OFF */); assertThat( - TextUtils.equals( - mController.getSummary(), - mContext.getText(R.string.gesture_setting_off))) + TextUtils.equals( + mController.getSummary(), + mContext.getText(R.string.gesture_setting_off))) .isTrue(); } @@ -248,13 +317,13 @@ public class DoubleTapPowerPreferenceControllerTest { 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)))) + 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(); } @@ -267,13 +336,13 @@ public class DoubleTapPowerPreferenceControllerTest { 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)))) + 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 7d4f52e67a2..40c13806fd6 100644 --- a/tests/robotests/src/com/android/settings/gestures/DoubleTapPowerSettingsTest.java +++ b/tests/robotests/src/com/android/settings/gestures/DoubleTapPowerSettingsTest.java @@ -16,6 +16,9 @@ package com.android.settings.gestures; +import static com.android.settings.gestures.DoubleTapPowerSettingsUtils.DOUBLE_TAP_POWER_LAUNCH_CAMERA_MODE; +import static com.android.settings.gestures.DoubleTapPowerSettingsUtils.DOUBLE_TAP_POWER_MULTI_TARGET_MODE; + import static com.google.common.truth.Truth.assertThat; import android.platform.test.annotations.DisableFlags; @@ -25,6 +28,7 @@ import android.provider.SearchIndexableResource; import android.service.quickaccesswallet.Flags; import com.android.settings.R; +import com.android.settings.testutils.shadow.SettingsShadowResources; import org.junit.Before; import org.junit.Rule; @@ -32,13 +36,16 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; import java.util.List; +@Config(shadows = SettingsShadowResources.class) @RunWith(RobolectricTestRunner.class) public class DoubleTapPowerSettingsTest { - @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); + @Rule + public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); private DoubleTapPowerSettings mSettings; @Before @@ -48,10 +55,29 @@ public class DoubleTapPowerSettingsTest { @Test @EnableFlags(Flags.FLAG_LAUNCH_WALLET_OPTION_ON_POWER_DOUBLE_TAP) - public void getPreferenceScreenResId_flagEnabled_returnsFlagEnabledResId() { + public void + getPreferenceScreenResId_flagEnabled_configIsMultiTargetMode_returnsMultiTargetResId() { + SettingsShadowResources.overrideResource( + com.android.internal.R.integer.config_doubleTapPowerGestureMode, + DOUBLE_TAP_POWER_MULTI_TARGET_MODE); + mSettings.onAttach(RuntimeEnvironment.getApplication()); + assertThat(mSettings.getPreferenceScreenResId()).isEqualTo(R.xml.double_tap_power_settings); } + @Test + @EnableFlags(Flags.FLAG_LAUNCH_WALLET_OPTION_ON_POWER_DOUBLE_TAP) + public void + getPreferenceScreenResId_flagEnabled_configIsCameraMode_returnsCameraLaunchResId() { + SettingsShadowResources.overrideResource( + com.android.internal.R.integer.config_doubleTapPowerGestureMode, + DOUBLE_TAP_POWER_LAUNCH_CAMERA_MODE); + mSettings.onAttach(RuntimeEnvironment.getApplication()); + + assertThat(mSettings.getPreferenceScreenResId()).isEqualTo( + R.xml.double_tap_power_to_open_camera_settings); + } + @Test @DisableFlags(Flags.FLAG_LAUNCH_WALLET_OPTION_ON_POWER_DOUBLE_TAP) public void getPreferenceScreenResId_flagDisabled_returnsFlagDisabledResId() { @@ -61,7 +87,12 @@ public class DoubleTapPowerSettingsTest { @Test @EnableFlags(Flags.FLAG_LAUNCH_WALLET_OPTION_ON_POWER_DOUBLE_TAP) - public void testSearchIndexProvider_flagEnabled_shouldIndexFlagEnabledResource() { + public void + testSearchIndexProvider_flagEnabled_configIsMultiTargetMode_indexMultiTargetResId() { + SettingsShadowResources.overrideResource( + com.android.internal.R.integer.config_doubleTapPowerGestureMode, + DOUBLE_TAP_POWER_MULTI_TARGET_MODE); + final List indexRes = DoubleTapPowerSettings.SEARCH_INDEX_DATA_PROVIDER.getXmlResourcesToIndex( RuntimeEnvironment.getApplication(), true /* enabled */); @@ -70,9 +101,26 @@ public class DoubleTapPowerSettingsTest { assertThat(indexRes.get(0).xmlResId).isEqualTo(R.xml.double_tap_power_settings); } + @Test + @EnableFlags(Flags.FLAG_LAUNCH_WALLET_OPTION_ON_POWER_DOUBLE_TAP) + public void + testSearchIndexProvider_flagEnabled_configIsCameraLaunchMode_indexCameraLaunchResId() { + SettingsShadowResources.overrideResource( + com.android.internal.R.integer.config_doubleTapPowerGestureMode, + DOUBLE_TAP_POWER_LAUNCH_CAMERA_MODE); + + 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); + } + @Test @DisableFlags(Flags.FLAG_LAUNCH_WALLET_OPTION_ON_POWER_DOUBLE_TAP) - public void testSearchIndexProvider_flagDisabled_shouldIndexFlagDisabledResource() { + public void testSearchIndexProvider_flagDisabled_indexFlagDisabledResource() { final List indexRes = DoubleTapPowerSettings.SEARCH_INDEX_DATA_PROVIDER.getXmlResourcesToIndex( RuntimeEnvironment.getApplication(), true /* enabled */); diff --git a/tests/robotests/src/com/android/settings/gestures/DoubleTapPowerSettingsUtilsTest.java b/tests/robotests/src/com/android/settings/gestures/DoubleTapPowerSettingsUtilsTest.java index 817f198a5b2..401a848ed0c 100644 --- a/tests/robotests/src/com/android/settings/gestures/DoubleTapPowerSettingsUtilsTest.java +++ b/tests/robotests/src/com/android/settings/gestures/DoubleTapPowerSettingsUtilsTest.java @@ -16,6 +16,8 @@ package com.android.settings.gestures; +import static com.android.settings.gestures.DoubleTapPowerSettingsUtils.DOUBLE_TAP_POWER_DISABLED_MODE; +import static com.android.settings.gestures.DoubleTapPowerSettingsUtils.DOUBLE_TAP_POWER_MULTI_TARGET_MODE; import static com.android.settings.gestures.DoubleTapPowerSettingsUtils.OFF; import static com.android.settings.gestures.DoubleTapPowerSettingsUtils.ON; @@ -55,18 +57,22 @@ public class DoubleTapPowerSettingsUtilsTest { } @Test - public void isDoubleTapPowerButtonGestureAvailable_setAvailable_returnsTrue() { - when(mResources.getBoolean(R.bool.config_doubleTapPowerGestureEnabled)).thenReturn(true); + public void isMultiTargetDoubleTapPowerButtonGestureAvailable_setAvailable_returnsTrue() { + when(mResources.getInteger(R.integer.config_doubleTapPowerGestureMode)).thenReturn( + DOUBLE_TAP_POWER_MULTI_TARGET_MODE); - assertThat(DoubleTapPowerSettingsUtils.isDoubleTapPowerButtonGestureAvailable(mContext)) + assertThat(DoubleTapPowerSettingsUtils.isMultiTargetDoubleTapPowerButtonGestureAvailable( + mContext)) .isTrue(); } @Test - public void isDoubleTapPowerButtonGestureAvailable_setUnavailable_returnsFalse() { - when(mResources.getBoolean(R.bool.config_doubleTapPowerGestureEnabled)).thenReturn(false); + public void isMultiTargetDoubleTapPowerButtonGestureAvailable_setUnavailable_returnsFalse() { + when(mResources.getInteger(R.integer.config_doubleTapPowerGestureMode)).thenReturn( + DOUBLE_TAP_POWER_DISABLED_MODE); - assertThat(DoubleTapPowerSettingsUtils.isDoubleTapPowerButtonGestureAvailable(mContext)) + assertThat(DoubleTapPowerSettingsUtils.isMultiTargetDoubleTapPowerButtonGestureAvailable( + mContext)) .isFalse(); } @@ -103,10 +109,10 @@ public class DoubleTapPowerSettingsUtilsTest { DoubleTapPowerSettingsUtils.setDoubleTapPowerButtonGestureEnabled(mContext, true); assertThat( - Settings.Secure.getInt( - mContext.getContentResolver(), - Settings.Secure.DOUBLE_TAP_POWER_BUTTON_GESTURE_ENABLED, - OFF)) + Settings.Secure.getInt( + mContext.getContentResolver(), + Settings.Secure.DOUBLE_TAP_POWER_BUTTON_GESTURE_ENABLED, + OFF)) .isEqualTo(ON); } @@ -115,10 +121,10 @@ public class DoubleTapPowerSettingsUtilsTest { DoubleTapPowerSettingsUtils.setDoubleTapPowerButtonGestureEnabled(mContext, false); assertThat( - Settings.Secure.getInt( - mContext.getContentResolver(), - Settings.Secure.DOUBLE_TAP_POWER_BUTTON_GESTURE_ENABLED, - ON)) + Settings.Secure.getInt( + mContext.getContentResolver(), + Settings.Secure.DOUBLE_TAP_POWER_BUTTON_GESTURE_ENABLED, + ON)) .isEqualTo(OFF); } @@ -130,8 +136,8 @@ public class DoubleTapPowerSettingsUtilsTest { DOUBLE_TAP_POWER_BUTTON_CAMERA_LAUNCH_VALUE); assertThat( - DoubleTapPowerSettingsUtils - .isDoubleTapPowerButtonGestureForCameraLaunchEnabled(mContext)) + DoubleTapPowerSettingsUtils + .isDoubleTapPowerButtonGestureForCameraLaunchEnabled(mContext)) .isTrue(); } @@ -144,32 +150,32 @@ public class DoubleTapPowerSettingsUtilsTest { DOUBLE_TAP_POWER_BUTTON_WALLET_LAUNCH_VALUE); assertThat( - DoubleTapPowerSettingsUtils - .isDoubleTapPowerButtonGestureForCameraLaunchEnabled(mContext)) + DoubleTapPowerSettingsUtils + .isDoubleTapPowerButtonGestureForCameraLaunchEnabled(mContext)) .isFalse(); } @Test public void isDoubleTapPowerButtonGestureForCameraLaunchEnabled_defaultSetToCamera_returnsTrue() { - when(mResources.getInteger(R.integer.config_defaultDoubleTapPowerGestureAction)) + when(mResources.getInteger(R.integer.config_doubleTapPowerGestureMultiTargetDefaultAction)) .thenReturn(DOUBLE_TAP_POWER_BUTTON_CAMERA_LAUNCH_VALUE); assertThat( - DoubleTapPowerSettingsUtils - .isDoubleTapPowerButtonGestureForCameraLaunchEnabled(mContext)) + DoubleTapPowerSettingsUtils + .isDoubleTapPowerButtonGestureForCameraLaunchEnabled(mContext)) .isTrue(); } @Test public void isDoubleTapPowerButtonGestureForCameraLaunchEnabled_defaultNotCamera_returnsFalse() { - when(mResources.getInteger(R.integer.config_defaultDoubleTapPowerGestureAction)) + when(mResources.getInteger(R.integer.config_doubleTapPowerGestureMultiTargetDefaultAction)) .thenReturn(DOUBLE_TAP_POWER_BUTTON_WALLET_LAUNCH_VALUE); assertThat( - DoubleTapPowerSettingsUtils - .isDoubleTapPowerButtonGestureForCameraLaunchEnabled(mContext)) + DoubleTapPowerSettingsUtils + .isDoubleTapPowerButtonGestureForCameraLaunchEnabled(mContext)) .isFalse(); } @@ -180,10 +186,10 @@ public class DoubleTapPowerSettingsUtilsTest { assertThat(result).isTrue(); assertThat( - Settings.Secure.getInt( - mContext.getContentResolver(), - Settings.Secure.DOUBLE_TAP_POWER_BUTTON_GESTURE, - DOUBLE_TAP_POWER_BUTTON_WALLET_LAUNCH_VALUE)) + Settings.Secure.getInt( + mContext.getContentResolver(), + Settings.Secure.DOUBLE_TAP_POWER_BUTTON_GESTURE, + DOUBLE_TAP_POWER_BUTTON_WALLET_LAUNCH_VALUE)) .isEqualTo(DOUBLE_TAP_POWER_BUTTON_CAMERA_LAUNCH_VALUE); } @@ -194,10 +200,10 @@ public class DoubleTapPowerSettingsUtilsTest { assertThat(result).isTrue(); assertThat( - Settings.Secure.getInt( - mContext.getContentResolver(), - Settings.Secure.DOUBLE_TAP_POWER_BUTTON_GESTURE, - DOUBLE_TAP_POWER_BUTTON_CAMERA_LAUNCH_VALUE)) + Settings.Secure.getInt( + mContext.getContentResolver(), + Settings.Secure.DOUBLE_TAP_POWER_BUTTON_GESTURE, + DOUBLE_TAP_POWER_BUTTON_CAMERA_LAUNCH_VALUE)) .isEqualTo(DOUBLE_TAP_POWER_BUTTON_WALLET_LAUNCH_VALUE); } } From cc22175481f833c98ed7235077002c3c6e20a29b Mon Sep 17 00:00:00 2001 From: Kangping Dong Date: Tue, 7 Jan 2025 13:35:44 +0800 Subject: [PATCH 12/17] [Thread] update the link for "Learn More about Thread" The latest link to the help center doc is finalized in b/387356147 Bug: 387356147 Change-Id: Ia3caf2dc78b4cd41d9d046cb072268ac63cdd65e --- res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/values/strings.xml b/res/values/strings.xml index 2d5a671506b..d574f862f4a 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -12726,7 +12726,7 @@ Learn more about Thread - https://developers.home.google.com + https://support.google.com/android?p=thread_toggle Camera access From 205c81ed3a461d4393bca986b7a53252d2855978 Mon Sep 17 00:00:00 2001 From: Ze Li Date: Tue, 7 Jan 2025 14:38:04 +0800 Subject: [PATCH 13/17] [Temp bonding] Hide rename button from device details page for temp bond device Test: com.android.settings.bluetooth.AdvancedBluetoothDetailsHeaderControllerTest Bug: 362859132 Flag: com.android.settingslib.flags.enable_temporary_bond_devices_ui Change-Id: I22d54c322029c606425c8f48b091ad1b53e100de --- ...ancedBluetoothDetailsHeaderController.java | 4 +++- ...neralBluetoothDetailsHeaderController.java | 22 +++++++++++-------- ...AudioBluetoothDetailsHeaderController.java | 4 +++- ...dBluetoothDetailsHeaderControllerTest.java | 20 +++++++++++++++++ 4 files changed, 39 insertions(+), 11 deletions(-) diff --git a/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderController.java b/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderController.java index d8e834dfbf8..ab0ed45d5e9 100644 --- a/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderController.java +++ b/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderController.java @@ -331,7 +331,9 @@ public class AdvancedBluetoothDetailsHeaderController extends BasePreferenceCont MAIN_DEVICE_ID); } }); - if (Flags.enableBluetoothDeviceDetailsPolish()) { + boolean isTempBond = com.android.settingslib.flags.Flags.enableTemporaryBondDevicesUi() + && BluetoothUtils.isTemporaryBondDevice(mCachedDevice.getDevice()); + if (Flags.enableBluetoothDeviceDetailsPolish() && !isTempBond) { ImageButton renameButton = mLayoutPreference.findViewById(R.id.rename_button); renameButton.setVisibility(View.VISIBLE); renameButton.setOnClickListener(view -> { diff --git a/src/com/android/settings/bluetooth/GeneralBluetoothDetailsHeaderController.java b/src/com/android/settings/bluetooth/GeneralBluetoothDetailsHeaderController.java index 57a10278190..2ef8fc07721 100644 --- a/src/com/android/settings/bluetooth/GeneralBluetoothDetailsHeaderController.java +++ b/src/com/android/settings/bluetooth/GeneralBluetoothDetailsHeaderController.java @@ -89,15 +89,19 @@ public class GeneralBluetoothDetailsHeaderController extends BluetoothDetailsCon if (summary != null) { summary.setText(mCachedDevice.getConnectionSummary()); } - ImageButton renameButton = mLayoutPreference.findViewById(R.id.rename_button); - renameButton.setVisibility(View.VISIBLE); - renameButton.setOnClickListener( - view -> { - RemoteDeviceNameDialogFragment.newInstance(mCachedDevice) - .show( - mFragment.getFragmentManager(), - RemoteDeviceNameDialogFragment.TAG); - }); + boolean isTempBond = com.android.settingslib.flags.Flags.enableTemporaryBondDevicesUi() + && BluetoothUtils.isTemporaryBondDevice(mCachedDevice.getDevice()); + if (!isTempBond) { + ImageButton renameButton = mLayoutPreference.findViewById(R.id.rename_button); + renameButton.setVisibility(View.VISIBLE); + renameButton.setOnClickListener( + view -> { + RemoteDeviceNameDialogFragment.newInstance(mCachedDevice) + .show( + mFragment.getFragmentManager(), + RemoteDeviceNameDialogFragment.TAG); + }); + } } @Override diff --git a/src/com/android/settings/bluetooth/LeAudioBluetoothDetailsHeaderController.java b/src/com/android/settings/bluetooth/LeAudioBluetoothDetailsHeaderController.java index 4c7c98eb48f..df24452d3ac 100644 --- a/src/com/android/settings/bluetooth/LeAudioBluetoothDetailsHeaderController.java +++ b/src/com/android/settings/bluetooth/LeAudioBluetoothDetailsHeaderController.java @@ -168,7 +168,9 @@ public class LeAudioBluetoothDetailsHeaderController extends BasePreferenceContr if (mLayoutPreference == null || mCachedDevice == null) { return; } - if (Flags.enableBluetoothDeviceDetailsPolish()) { + boolean isTempBond = com.android.settingslib.flags.Flags.enableTemporaryBondDevicesUi() + && BluetoothUtils.isTemporaryBondDevice(mCachedDevice.getDevice()); + if (Flags.enableBluetoothDeviceDetailsPolish() && !isTempBond) { ImageButton renameButton = mLayoutPreference.findViewById(R.id.rename_button); renameButton.setVisibility(View.VISIBLE); renameButton.setOnClickListener(view -> { diff --git a/tests/robotests/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderControllerTest.java b/tests/robotests/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderControllerTest.java index fc1df5a0f69..53a8f5d2cdd 100644 --- a/tests/robotests/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderControllerTest.java +++ b/tests/robotests/src/com/android/settings/bluetooth/AdvancedBluetoothDetailsHeaderControllerTest.java @@ -79,9 +79,12 @@ public class AdvancedBluetoothDetailsHeaderControllerTest { private static final int LOW_BATTERY_LEVEL_THRESHOLD = 15; private static final int BATTERY_LEVEL_5 = 5; private static final int BATTERY_LEVEL_50 = 50; + private static final int METADATA_FAST_PAIR_CUSTOMIZED_FIELDS = 25; private static final String ICON_URI = "content://test.provider/icon.png"; private static final String MAC_ADDRESS = "04:52:C7:0B:D8:3C"; private static final String DEVICE_SUMMARY = "test summary"; + private static final String TEMP_BOND_METADATA = + "le_audio_sharing"; private Context mContext; @@ -531,6 +534,23 @@ public class AdvancedBluetoothDetailsHeaderControllerTest { assertThat(button.getVisibility()).isEqualTo(View.VISIBLE); } + @Test + @EnableFlags({Flags.FLAG_ENABLE_BLUETOOTH_DEVICE_DETAILS_POLISH, + com.android.settingslib.flags.Flags.FLAG_ENABLE_TEMPORARY_BOND_DEVICES_UI}) + public void temporaryBondDevice_renameButtonNotShown() { + when(mBluetoothDevice.getMetadata(BluetoothDevice.METADATA_IS_UNTETHERED_HEADSET)) + .thenReturn("true".getBytes()); + when(mBluetoothDevice.getMetadata(METADATA_FAST_PAIR_CUSTOMIZED_FIELDS)) + .thenReturn(TEMP_BOND_METADATA.getBytes()); + Set cacheBluetoothDevices = new HashSet<>(); + when(mCachedDevice.getMemberDevice()).thenReturn(cacheBluetoothDevices); + + mController.onStart(); + + ImageButton button = mLayoutPreference.findViewById(R.id.rename_button); + assertThat(button.getVisibility()).isEqualTo(View.GONE); + } + private void assertBatteryPredictionVisible(LinearLayout linearLayout, int visible) { final TextView textView = linearLayout.findViewById(R.id.bt_battery_prediction); assertThat(textView.getVisibility()).isEqualTo(visible); From 929056c3772e00e663982b7ac642a0cc39473152 Mon Sep 17 00:00:00 2001 From: shaoweishen Date: Mon, 16 Dec 2024 08:14:37 +0000 Subject: [PATCH 14/17] [Touchpad and Mouse] Sync strings and prefs Sync texts and preferences arrangement in Touchpad and Mouse related pages. Bug: 377602364 Test: atest SettingsRoboTests Flag: com.android.settings.keyboard.keyboard_and_touchpad_a11y_new_page_enabled Change-Id: I64179cc1a6ab1080160923c2d7d861537991ef97 --- res/values/strings.xml | 40 ++++++------ .../accessibility_pointer_and_touchpad.xml | 61 ++++++++++--------- res/xml/mouse_settings.xml | 22 +++++++ res/xml/touchpad_settings.xml | 13 ++++ 4 files changed, 91 insertions(+), 45 deletions(-) diff --git a/res/values/strings.xml b/res/values/strings.xml index fcdb2d8a0f1..ee09f9efc77 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -4672,14 +4672,14 @@ Use your keyboard to control the pointer - Mouse reverse scrolling + Reverse scrolling - Scroll up to move the page down + Content moves up when you scroll down Controlled scrolling - Swap left and right buttons + Swap primary mouse button Use the left mouse button as your right @@ -4726,9 +4726,13 @@ Tap to click - Tap dragging + Tap and drag to move items - Tap and drag your finger on the touchpad to move objects + Double-tap an item, hold down on the second tap, and then drag the item to move it + + Touchpad gestures + + Customize individual touchpad navigation gestures Reverse scrolling @@ -4738,9 +4742,9 @@ Click in the bottom right corner of the touchpad for more options - Pointer speed + Cursor speed - Use three finger tap + Customise 3-finger tap Pointer color @@ -4876,7 +4880,7 @@ Pointer speed - Pointer scale + Cursor size Decrease pointer scale @@ -5027,21 +5031,23 @@ Display Color and motion - - Pointer & touchpad accessibility + + Cursor & touchpad accessibility - Pointer color, pointer size & more + Size, color, type - Pointer color customization + Cursor color + + Cursor - Touchpad + Touchpad - Use system gestures + Use 3- or 4-finger gestures - When turned off, 3- or 4-finger gestures are ignored + When turned off, your touchpad will ignore 3- or 4-finger gestures - touchpad, trackpad, swipe + touchpad, trackpad, swipe Color contrast @@ -5531,7 +5537,7 @@ enter settings - Autoclick (dwell timing) + Autoclick (Dwell timing) About autoclick (dwell timing) diff --git a/res/xml/accessibility_pointer_and_touchpad.xml b/res/xml/accessibility_pointer_and_touchpad.xml index a46c8572bb5..01e95f5e34b 100644 --- a/res/xml/accessibility_pointer_and_touchpad.xml +++ b/res/xml/accessibility_pointer_and_touchpad.xml @@ -1,5 +1,4 @@ - - - - - - + android:title="@string/accessibility_pointer_title"> - + + + + + + + + android:title="@string/accessibility_touchpad_system_gestures_enable_title" + settings:keywords="@string/keywords_accessibility_touchpad_system_gestures_enable" /> diff --git a/res/xml/mouse_settings.xml b/res/xml/mouse_settings.xml index dbd87111802..a25d516edbe 100644 --- a/res/xml/mouse_settings.xml +++ b/res/xml/mouse_settings.xml @@ -20,6 +20,12 @@ xmlns:settings="http://schemas.android.com/apk/res-auto" android:title="@string/mouse_settings"> + + + + + + diff --git a/res/xml/touchpad_settings.xml b/res/xml/touchpad_settings.xml index cc9b42ccac7..d3b81573fab 100644 --- a/res/xml/touchpad_settings.xml +++ b/res/xml/touchpad_settings.xml @@ -47,6 +47,13 @@ settings:controller="com.android.settings.inputmethod.TrackpadTapDraggingPreferenceController" android:order="35"/> + + + + From 5f63dd0fdbb9b9ca3e302f34d30fe0664fa43e16 Mon Sep 17 00:00:00 2001 From: Zoey Chen Date: Tue, 7 Jan 2025 11:14:57 +0000 Subject: [PATCH 15/17] [Settings] Refactor: Add App language layout Bug: 388199937 Test: manual Flag: EXEMPT refactor Change-Id: I4062bfe0e882a40fb55fbf0b2164b558fe83328b --- res/xml/app_language_picker.xml | 51 +++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 res/xml/app_language_picker.xml diff --git a/res/xml/app_language_picker.xml b/res/xml/app_language_picker.xml new file mode 100644 index 00000000000..be61aa7bb5a --- /dev/null +++ b/res/xml/app_language_picker.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + From e0036fc8b26a5d5470992f90d6e2260b57ddc9ac Mon Sep 17 00:00:00 2001 From: Kasia Krejszeff Date: Tue, 7 Jan 2025 01:44:12 +0000 Subject: [PATCH 16/17] Remove nested ScrollView in the PrivateSpaceEducation screen. It is not needed for the scrolling to work -- GlifLayout from the SUW library generates a ScrollView. Additional ScrollView causes Talkback to interpret it as a separate item and read out contents of its all children. See b/379256039. Video before: https://drive.google.com/file/d/1H3k5AxlIdgAA15PHUQ9tVq5AechziA4Z/view?usp=sharing&resourcekey=0-ozeQsQSS5jubL0pZ5FAZHA Video after: https://drive.google.com/file/d/1W_ODgQhbQS6Xf_57A4TcYeJbqMJxYF16/view?usp=sharing&resourcekey=0-zQ0_p3qlIxpBL3rB5SC4vQ In the before video, talkback is highlighting and (the green frames) and reading out the whole "How it works" section in addition to each element separately. After the fix it only highlights elements separately. Bug: 379256039 Test: Manually testesd and presubmit. Flag: EXEMPT bugfix Change-Id: Idf6772b8772c54c1907d3a12617fcd03451af41b --- res/layout/private_space_education_screen.xml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/res/layout/private_space_education_screen.xml b/res/layout/private_space_education_screen.xml index 3afe7f97ed9..5a34939ac66 100644 --- a/res/layout/private_space_education_screen.xml +++ b/res/layout/private_space_education_screen.xml @@ -24,10 +24,6 @@ app:sucHeaderText="@string/private_space_setup_title" app:sudDescriptionText="@string/private_space_hide_apps_summary" android:icon="@drawable/ic_private_space_icon"> - - From 6e89c83c9d1204abde111a3883e4a6668e0679ae Mon Sep 17 00:00:00 2001 From: Wenyu Zhang Date: Tue, 7 Jan 2025 07:00:14 -0800 Subject: [PATCH 17/17] a11y: Fix Android Lint Add NonNull annotation. Fix Android Lint in http://ag/31174874. Bug: b/383901288 Change-Id: Ibe296525ebdc298b3b23b8df51bd58218e20b777 Test: ToggleAutoclickCursorAreaSizeControllerTest Flag: com.android.server.accessibility.enable_autoclick_indicator --- .../ToggleAutoclickCursorAreaSizeController.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/com/android/settings/accessibility/ToggleAutoclickCursorAreaSizeController.java b/src/com/android/settings/accessibility/ToggleAutoclickCursorAreaSizeController.java index 26c0e66c79a..4fde38fd0bb 100644 --- a/src/com/android/settings/accessibility/ToggleAutoclickCursorAreaSizeController.java +++ b/src/com/android/settings/accessibility/ToggleAutoclickCursorAreaSizeController.java @@ -21,6 +21,7 @@ import static android.content.Context.MODE_PRIVATE; import android.content.Context; import android.content.SharedPreferences; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.lifecycle.Lifecycle; import androidx.lifecycle.LifecycleObserver; @@ -42,7 +43,8 @@ public class ToggleAutoclickCursorAreaSizeController extends SliderPreferenceCon private final SharedPreferences mSharedPreferences; - public ToggleAutoclickCursorAreaSizeController(Context context, String preferenceKey) { + public ToggleAutoclickCursorAreaSizeController(@NonNull Context context, + @NonNull String preferenceKey) { super(context, preferenceKey); mSharedPreferences = context.getSharedPreferences(context.getPackageName(), MODE_PRIVATE); } @@ -62,7 +64,7 @@ public class ToggleAutoclickCursorAreaSizeController extends SliderPreferenceCon } @Override - public void displayPreference(PreferenceScreen screen) { + public void displayPreference(@NonNull PreferenceScreen screen) { super.displayPreference(screen); } @@ -73,7 +75,7 @@ public class ToggleAutoclickCursorAreaSizeController extends SliderPreferenceCon @Override public void onSharedPreferenceChanged( - SharedPreferences sharedPreferences, @Nullable String key) { + @NonNull SharedPreferences sharedPreferences, @Nullable String key) { // TODO(b/383901288): Update slider. }