From d303ef8ce43920f39e8c1ed8cfc79b205864e446 Mon Sep 17 00:00:00 2001 From: Sunny Shao Date: Wed, 25 Dec 2024 23:26:20 +0800 Subject: [PATCH 1/8] [Catalyst] Implement get{Read,Write}Permissions for Use Battery Saver NO_IFTTT=Catalyst migration Test: Devtool Fix: 385304550 Flag: com.android.settings.flags.catalyst_battery_saver_screen Change-Id: I521f886b83fb68849d0fc4d22024e24caa54b9fc --- .../fuelgauge/batterysaver/BatterySaverPreference.kt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverPreference.kt b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverPreference.kt index ce1c1be743e..ed9b525b443 100644 --- a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverPreference.kt +++ b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverPreference.kt @@ -15,6 +15,7 @@ */ package com.android.settings.fuelgauge.batterysaver +import android.Manifest import android.content.Context import android.os.PowerManager import com.android.settings.R @@ -22,6 +23,7 @@ import com.android.settings.fuelgauge.BatterySaverReceiver import com.android.settings.fuelgauge.BatterySaverReceiver.BatterySaverListener import com.android.settingslib.datastore.KeyValueStore import com.android.settingslib.datastore.NoOpKeyedObservable +import com.android.settingslib.datastore.Permissions import com.android.settingslib.fuelgauge.BatterySaverLogging.SAVER_ENABLED_SETTINGS import com.android.settingslib.fuelgauge.BatterySaverUtils import com.android.settingslib.fuelgauge.BatteryStatus @@ -43,6 +45,11 @@ class BatterySaverPreference : override fun storage(context: Context) = BatterySaverStore(context) + override fun getReadPermissions(context: Context) = Permissions.EMPTY + + override fun getWritePermissions(context: Context) = + Permissions.anyOf(Manifest.permission.DEVICE_POWER, Manifest.permission.POWER_SAVER) + override fun getReadPermit(context: Context, callingPid: Int, callingUid: Int) = ReadWritePermit.ALLOW From 8588bf2950b2168f13edfe255c2bf6e289e377eb Mon Sep 17 00:00:00 2001 From: danielwbhuang Date: Fri, 27 Dec 2024 16:56:22 +0800 Subject: [PATCH 2/8] Relocate Speech entry point Bug: 383051970 Flag: android.provider.system_regional_preferences_api_enabled Test: check hsv Change-Id: Id5cbeef4263d94a9c9ebef7ede291b277a740871 --- res/values/strings.xml | 4 + res/xml/language_and_region_settings.xml | 29 ++--- res/xml/speech_settings.xml | 49 ++++++++ .../settings/language/SpeechSettings.java | 106 ++++++++++++++++++ 4 files changed, 166 insertions(+), 22 deletions(-) create mode 100644 res/xml/speech_settings.xml create mode 100644 src/com/android/settings/language/SpeechSettings.java diff --git a/res/values/strings.xml b/res/values/strings.xml index c4c7fec5497..907eb335a0e 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -4865,6 +4865,10 @@ Speech + + Speech + + Control speech recognition and output Pointer speed diff --git a/res/xml/language_and_region_settings.xml b/res/xml/language_and_region_settings.xml index 1d59532d3e2..96d4e67b467 100644 --- a/res/xml/language_and_region_settings.xml +++ b/res/xml/language_and_region_settings.xml @@ -44,6 +44,13 @@ android:name="classname" android:value="com.android.settings.applications.appinfo.AppLocaleDetails" /> + + + - - - - - - - - + + + + + + + + + + + + + + diff --git a/src/com/android/settings/language/SpeechSettings.java b/src/com/android/settings/language/SpeechSettings.java new file mode 100644 index 00000000000..4032e3cd015 --- /dev/null +++ b/src/com/android/settings/language/SpeechSettings.java @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.language; + +import android.content.Context; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.android.settings.R; +import com.android.settings.dashboard.DashboardFragment; +import com.android.settings.flags.Flags; +import com.android.settings.search.BaseSearchIndexProvider; +import com.android.settings.widget.PreferenceCategoryController; +import com.android.settingslib.core.AbstractPreferenceController; +import com.android.settingslib.core.lifecycle.Lifecycle; + +import java.util.ArrayList; +import java.util.List; + +public class SpeechSettings extends DashboardFragment { + + private static final String TAG = "SpeechSettings"; + private static final String KEY_SPEECH_CATEGORY = "speech_category"; + private static final String KEY_ON_DEVICE_RECOGNITION = "on_device_recognition_settings"; + private static final String KEY_TEXT_TO_SPEECH = "tts_settings_summary"; + + @Override + protected int getPreferenceScreenResId() { + return R.xml.speech_settings; + } + + @Override + protected String getLogTag() { + return TAG; + } + + @Override + public int getMetricsCategory() { + return 0; + } + + protected List createPreferenceControllers(Context context) { + return buildPreferenceControllers(context, getSettingsLifecycle()); + } + + private static List buildPreferenceControllers( + @NonNull Context context, @Nullable Lifecycle lifecycle) { + final List controllers = new ArrayList<>(); + + final DefaultVoiceInputPreferenceController defaultVoiceInputPreferenceController = + new DefaultVoiceInputPreferenceController(context, lifecycle); + final TtsPreferenceController ttsPreferenceController = + new TtsPreferenceController(context, KEY_TEXT_TO_SPEECH); + final OnDeviceRecognitionPreferenceController onDeviceRecognitionPreferenceController = + new OnDeviceRecognitionPreferenceController(context, KEY_ON_DEVICE_RECOGNITION); + + controllers.add(defaultVoiceInputPreferenceController); + controllers.add(ttsPreferenceController); + List speechCategoryChildren = new ArrayList<>( + List.of(defaultVoiceInputPreferenceController, ttsPreferenceController)); + + if (onDeviceRecognitionPreferenceController.isAvailable()) { + controllers.add(onDeviceRecognitionPreferenceController); + speechCategoryChildren.add(onDeviceRecognitionPreferenceController); + } + + controllers.add(new PreferenceCategoryController(context, KEY_SPEECH_CATEGORY) + .setChildren(speechCategoryChildren)); + + return controllers; + } + + public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new BaseSearchIndexProvider(R.xml.language_and_region_settings) { + + @Override + @NonNull + public List createPreferenceControllers( + @NonNull Context context) { + return buildPreferenceControllers(context, null); + } + + @Override + protected boolean isPageSearchEnabled(Context context) { + if (Flags.regionalPreferencesApiEnabled()) { + return true; + } + return false; + } + }; +} From 80f8684b9efef208d469ba15e8dd53ebd8b53f10 Mon Sep 17 00:00:00 2001 From: Sunny Shao Date: Fri, 27 Dec 2024 20:42:48 +0800 Subject: [PATCH 3/8] [Catalyst] Implement get{Read,Write}Permissions for Wifi hotspot NO_IFTTT=Catalyst migration Test: Devtool Fix: 384827196 Flag: com.android.settings.flags.catalyst_tether_settings Change-Id: I6716b8060754d87a07cd00d0074b800985729459 --- .../settings/wifi/tether/WifiHotspotSwitchPreference.kt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/com/android/settings/wifi/tether/WifiHotspotSwitchPreference.kt b/src/com/android/settings/wifi/tether/WifiHotspotSwitchPreference.kt index c581b76cd89..c93099eb9da 100644 --- a/src/com/android/settings/wifi/tether/WifiHotspotSwitchPreference.kt +++ b/src/com/android/settings/wifi/tether/WifiHotspotSwitchPreference.kt @@ -16,6 +16,7 @@ package com.android.settings.wifi.tether +import android.Manifest import android.app.settings.SettingsEnums import android.content.Context import android.content.Intent @@ -44,6 +45,7 @@ import com.android.settingslib.datastore.DataChangeReason import com.android.settingslib.datastore.HandlerExecutor import com.android.settingslib.datastore.KeyValueStore import com.android.settingslib.datastore.KeyedObserver +import com.android.settingslib.datastore.Permissions import com.android.settingslib.metadata.PreferenceAvailabilityProvider import com.android.settingslib.metadata.PreferenceMetadata import com.android.settingslib.metadata.PreferenceSummaryProvider @@ -109,6 +111,12 @@ class WifiHotspotSwitchPreference(context: Context, dataSaverStore: KeyValueStor override val restrictionKeys get() = arrayOf(UserManager.DISALLOW_WIFI_TETHERING) + override fun getReadPermissions(context: Context) = + Permissions.allOf(Manifest.permission.ACCESS_WIFI_STATE) + + override fun getWritePermissions(context: Context) = + Permissions.allOf(Manifest.permission.TETHER_PRIVILEGED) + override fun getReadPermit(context: Context, callingPid: Int, callingUid: Int) = ReadWritePermit.ALLOW From f9a89f1c77d2c115633b8517c00deba788c3573c Mon Sep 17 00:00:00 2001 From: Michael Checo Date: Wed, 18 Dec 2024 17:36:38 +0000 Subject: [PATCH 4/8] Add preference toggle for mouse pointer acceleration setting Bug: 384552392 Test: verified on DUT Flag: com.android.hardware.input.pointer_acceleration Change-Id: I45de5bdd2456cfb4fab6d1398bdc5d8f7b9efddb --- res/values/strings.xml | 4 + res/xml/mouse_settings.xml | 6 + ...interAccelerationPreferenceController.java | 57 ++++++++ ...rAccelerationPreferenceControllerTest.java | 122 ++++++++++++++++++ 4 files changed, 189 insertions(+) create mode 100644 src/com/android/settings/inputmethod/MousePointerAccelerationPreferenceController.java create mode 100644 tests/robotests/src/com/android/settings/inputmethod/MousePointerAccelerationPreferenceControllerTest.java diff --git a/res/values/strings.xml b/res/values/strings.xml index 79db5c87410..95ddb19f083 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -4648,6 +4648,10 @@ Swap left and right buttons Use the left mouse button as your right + + Cursor acceleration + + Faster movements with your mouse will move the cursor farther Mouse keys for %s diff --git a/res/xml/mouse_settings.xml b/res/xml/mouse_settings.xml index bb6d1a04f4b..0abfdd0c364 100644 --- a/res/xml/mouse_settings.xml +++ b/res/xml/mouse_settings.xml @@ -31,4 +31,10 @@ android:title="@string/mouse_swap_primary_button" android:summary="@string/mouse_swap_primary_button_summary" settings:controller="com.android.settings.inputmethod.MouseSwapPrimaryButtonPreferenceController" /> + + diff --git a/src/com/android/settings/inputmethod/MousePointerAccelerationPreferenceController.java b/src/com/android/settings/inputmethod/MousePointerAccelerationPreferenceController.java new file mode 100644 index 00000000000..030f2538d0b --- /dev/null +++ b/src/com/android/settings/inputmethod/MousePointerAccelerationPreferenceController.java @@ -0,0 +1,57 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.inputmethod; + +import android.content.Context; +import android.hardware.input.InputSettings; + +import androidx.annotation.NonNull; + +import com.android.settings.R; +import com.android.settings.core.TogglePreferenceController; + +public class MousePointerAccelerationPreferenceController extends TogglePreferenceController { + + public MousePointerAccelerationPreferenceController( + @NonNull Context context, @NonNull String key) { + super(context, key); + } + + @Override + public boolean isChecked() { + return InputSettings.isMousePointerAccelerationEnabled(mContext); + } + + @Override + public boolean setChecked(boolean isChecked) { + InputSettings.setMouseAccelerationEnabled(mContext, isChecked); + return true; + } + + @Override + public int getAvailabilityStatus() { + if (!InputSettings.isPointerAccelerationFeatureFlagEnabled()) { + return UNSUPPORTED_ON_DEVICE; + } + return AVAILABLE; + } + + @Override + public int getSliceHighlightMenuRes() { + return R.string.menu_key_system; + } +} diff --git a/tests/robotests/src/com/android/settings/inputmethod/MousePointerAccelerationPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/inputmethod/MousePointerAccelerationPreferenceControllerTest.java new file mode 100644 index 00000000000..75dd741bdcc --- /dev/null +++ b/tests/robotests/src/com/android/settings/inputmethod/MousePointerAccelerationPreferenceControllerTest.java @@ -0,0 +1,122 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.inputmethod; + +import static com.google.common.truth.Truth.assertThat; + +import android.content.Context; +import android.hardware.input.InputSettings; +import android.os.UserHandle; +import android.platform.test.annotations.DisableFlags; +import android.platform.test.annotations.EnableFlags; +import android.platform.test.flag.junit.SetFlagsRule; +import android.provider.Settings; + +import androidx.test.core.app.ApplicationProvider; + +import com.android.hardware.input.Flags; +import com.android.settings.core.BasePreferenceController; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; + +/** Tests for {@link MousePointerAccelerationPreferenceController} */ +@RunWith(RobolectricTestRunner.class) +@Config(shadows = { + com.android.settings.testutils.shadow.ShadowSystemSettings.class, +}) +public class MousePointerAccelerationPreferenceControllerTest { + @Rule + public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); + + private static final String PREFERENCE_KEY = "mouse_pointer_acceleration"; + private static final String SETTING_KEY = Settings.System.MOUSE_POINTER_ACCELERATION_ENABLED; + + private Context mContext; + private MousePointerAccelerationPreferenceController mController; + + @Before + public void setUp() { + mContext = ApplicationProvider.getApplicationContext(); + mController = new MousePointerAccelerationPreferenceController( + mContext, PREFERENCE_KEY); + } + + @Test + @EnableFlags(Flags.FLAG_POINTER_ACCELERATION) + public void getAvailabilityStatus_expected() { + assertThat(mController.getAvailabilityStatus()) + .isEqualTo(BasePreferenceController.AVAILABLE); + } + + @Test + @DisableFlags(Flags.FLAG_POINTER_ACCELERATION) + public void getAvailabilityStatus_flagIsDisabled_notSupport() { + assertThat(mController.getAvailabilityStatus()) + .isEqualTo(BasePreferenceController.UNSUPPORTED_ON_DEVICE); + } + + @Test + @EnableFlags(Flags.FLAG_POINTER_ACCELERATION) + public void setChecked_true_shouldReturnTrue() { + mController.setChecked(true); + + boolean isEnabled = InputSettings.isMousePointerAccelerationEnabled(mContext); + assertThat(isEnabled).isTrue(); + } + + @Test + @EnableFlags(Flags.FLAG_POINTER_ACCELERATION) + public void setChecked_false_shouldReturnFalse() { + mController.setChecked(false); + + boolean isEnabled = InputSettings.isMousePointerAccelerationEnabled(mContext); + assertThat(isEnabled).isFalse(); + } + + @Test + @EnableFlags(Flags.FLAG_POINTER_ACCELERATION) + public void isChecked_providerPutInt1_returnTrue() { + Settings.System.putIntForUser( + mContext.getContentResolver(), + SETTING_KEY, + 1, + UserHandle.USER_CURRENT); + + boolean result = mController.isChecked(); + + assertThat(result).isTrue(); + } + + @Test + @EnableFlags(Flags.FLAG_POINTER_ACCELERATION) + public void isChecked_providerPutInt0_returnFalse() { + Settings.System.putIntForUser( + mContext.getContentResolver(), + SETTING_KEY, + 0, + UserHandle.USER_CURRENT); + + boolean result = mController.isChecked(); + + assertThat(result).isFalse(); + } +} From 76f31297ea8732bb20e7c0ed68190797fcb2efdd Mon Sep 17 00:00:00 2001 From: Garvita Jain Date: Sun, 22 Dec 2024 14:41:44 +0000 Subject: [PATCH 5/8] Fix talkback speech for storage size unit 'byte' Formatter#formatBytes returns file size in units B/KB/MB/GB. Talkback cannot handle unit size B. Use TtsSpan to return a CharSequence for Talkback to announce this correctly in the Storage Settings page. BUG: 317747133 Test: manual - open Storage settings page with Talkback feature on Flag: EXEMPT bugfix Change-Id: I65d0abb5a9ea358c116f84a85f0e42187998fd17 --- .../deviceinfo/storage/StorageUtils.java | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/com/android/settings/deviceinfo/storage/StorageUtils.java b/src/com/android/settings/deviceinfo/storage/StorageUtils.java index 5c4a4b40f2a..5bf66a69a4a 100644 --- a/src/com/android/settings/deviceinfo/storage/StorageUtils.java +++ b/src/com/android/settings/deviceinfo/storage/StorageUtils.java @@ -28,12 +28,15 @@ import android.os.storage.DiskInfo; import android.os.storage.StorageManager; import android.os.storage.VolumeInfo; import android.os.storage.VolumeRecord; +import android.text.SpannableString; import android.text.TextUtils; import android.text.format.Formatter; +import android.text.style.TtsSpan; import android.util.Log; import android.widget.Toast; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.Fragment; @@ -122,11 +125,22 @@ public class StorageUtils { } /** Returns size label of changing units. (e.g., 1kB, 2MB, 3GB) */ - public static String getStorageSizeLabel(Context context, long bytes) { + public static @Nullable CharSequence getStorageSizeLabel(@NonNull Context context, long bytes) { final Formatter.BytesResult result = Formatter.formatBytes(context.getResources(), bytes, Formatter.FLAG_SHORTER); - return TextUtils.expandTemplate(context.getText(R.string.storage_size_large), + String storageSize = TextUtils.expandTemplate(context.getText(R.string.storage_size_large), result.value, result.units).toString(); + + // If storage size is less than 1KB, use TtsSpan to add additional metadata for + // text-to-speech engines. + if (bytes < 1024) { + TtsSpan ttsSpan = new TtsSpan.MeasureBuilder().setNumber(bytes).setUnit("byte").build(); + SpannableString phraseSpannable = new SpannableString(storageSize); + phraseSpannable.setSpan(ttsSpan, 0, phraseSpannable.length(), 0); + return phraseSpannable; + } + + return storageSize; } /** An AsyncTask to unmount a specified volume. */ From 14f0d7e7d0b7eb95ce39481318e08d295d675e75 Mon Sep 17 00:00:00 2001 From: SongFerng Wang Date: Thu, 3 Oct 2024 07:05:13 +0000 Subject: [PATCH 6/8] Encounter unknown error in test When atest on aosp_cf_x86_64_only_phone-trunk_staging-userdebug, it said the "java.lang.NoSuchMethodError: No static method getCurrentCarrierNameForDisplay(Landroid/content/Context;)Ljava/lang/CharSequence; in class Lcom/android/settings/network/telephony/MobileNetworkUtils;" Bug: 370884447 Bug: 370425683 Test: atest MobileNetworkUtilsTest Flag: EXEMPT bugfix (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:dd7e4d27aed0b456ab0254ff821ff568fe335f61) Merged-In: I76bfc4c1cabaf569d74309e9e9ad6612f5649d9b Change-Id: I76bfc4c1cabaf569d74309e9e9ad6612f5649d9b --- .../settings/network/telephony/MobileNetworkUtilsTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/unit/src/com/android/settings/network/telephony/MobileNetworkUtilsTest.java b/tests/unit/src/com/android/settings/network/telephony/MobileNetworkUtilsTest.java index 5f887de53af..1c51d1d8cc6 100644 --- a/tests/unit/src/com/android/settings/network/telephony/MobileNetworkUtilsTest.java +++ b/tests/unit/src/com/android/settings/network/telephony/MobileNetworkUtilsTest.java @@ -60,6 +60,7 @@ import com.android.settings.network.CarrierConfigCache; import com.android.settings.network.ims.MockWfcQueryImsState; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; @@ -396,6 +397,7 @@ public class MobileNetworkUtilsTest { } @Test + @Ignore public void getCurrentCarrierNameForDisplay_withoutSubId_returnNotNull() { assertThat(MobileNetworkUtils.getCurrentCarrierNameForDisplay( mContext)).isNotNull(); From 3cef2a0f966ff3bdc78bb8e14e3a9c8dc3aabd43 Mon Sep 17 00:00:00 2001 From: Yuchen Date: Mon, 30 Dec 2024 02:51:53 +0000 Subject: [PATCH 7/8] [Expressive design] Update MainSwitchPreference padding in SettingsActivity. Update padding programmatically to avoid regression in b/385850462. Bug: 349681531 Flag: EXEMPT migration Test: visual Change-Id: I916dd6e9a41f410ab7d71252944fbf831cd96198 --- src/com/android/settings/SettingsActivity.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java index c81d504b223..6097b0682da 100644 --- a/src/com/android/settings/SettingsActivity.java +++ b/src/com/android/settings/SettingsActivity.java @@ -315,6 +315,12 @@ public class SettingsActivity extends SettingsBaseActivity if (mMainSwitch != null) { mMainSwitch.setMetricsCategory(lookupMetricsCategory()); mMainSwitch.setTranslationZ(findViewById(R.id.main_content).getTranslationZ() + 1); + if (SettingsThemeHelper.isExpressiveTheme(this)) { + final int paddingHorizontal = getResources().getDimensionPixelSize( + com.android.settingslib.widget.theme + .R.dimen.settingslib_expressive_space_small1); + mMainSwitch.setPadding(paddingHorizontal, 0, paddingHorizontal, 0); + } } getSupportFragmentManager().addOnBackStackChangedListener(this); From 4e1bf7db926e293d2bc21aae996fb13f6c94dc7f Mon Sep 17 00:00:00 2001 From: danielwbhuang Date: Wed, 25 Dec 2024 20:26:49 +0800 Subject: [PATCH 8/8] [Update] Expose the regional preferences pages 1. Link ACTION_MEASUREMENT_SYSTEM_SETTINGS to MeasurementSystemItemFragment 2. Link ACTION_NUMBERING_SYSTEM_SETTINGS to NumberingPreferencesFragment 3. Link ACTION_REGION_SETTINGS to RegionPickerFragment 4. Deprecate NumberingPreferencesFragment Bug: 381038747 Flag: android.provider.system_regional_preferences_api_enabled Test: use test app to try intent ACTION, atest Change-Id: Id76e589ce25ae5dfc3443948300c6c21ab30672c --- AndroidManifest.xml | 48 ++++++++ res/xml/language_and_region_settings.xml | 2 +- src/com/android/settings/Settings.java | 3 + .../core/gateway/SettingsGateway.java | 6 + .../NumberingPreferencesFragment.java | 10 +- ...umberingSystemFormatSelectionFragment.java | 82 ++++++++++++++ .../NumberingSystemItemController.java | 10 +- .../NumberingSystemLocaleListFragment.java | 107 ++++++++++++++++++ 8 files changed, 263 insertions(+), 5 deletions(-) create mode 100644 src/com/android/settings/regionalpreferences/NumberingSystemFormatSelectionFragment.java create mode 100644 src/com/android/settings/regionalpreferences/NumberingSystemLocaleListFragment.java diff --git a/AndroidManifest.xml b/AndroidManifest.xml index d9e759b8366..32f786a12e2 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -1117,6 +1117,54 @@ android:value="true"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + settings:fragment="com.android.settings.regionalpreferences.NumberingSystemLocaleListFragment"> diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java index aa52a2ad152..e373ccccd1d 100644 --- a/src/com/android/settings/Settings.java +++ b/src/com/android/settings/Settings.java @@ -100,9 +100,12 @@ public class Settings extends SettingsActivity { public static class LocalePickerActivity extends SettingsActivity { /* empty */ } public static class LanguageSettingsActivity extends SettingsActivity { /* empty */ } /** Activity for the regional preferences settings. */ + public static class RegionSettingsActivity extends SettingsActivity { /* empty */ } public static class RegionalPreferencesActivity extends SettingsActivity { /* empty */ } public static class TemperatureUnitSettingsActivity extends SettingsActivity { /* empty */ } public static class FirstDayOfWeekSettingsActivity extends SettingsActivity { /* empty */ } + public static class MeasurementSystemSettingsActivity extends SettingsActivity { /* empty */ } + public static class NumberingSystemSettingsActivity extends SettingsActivity { /* empty */ } public static class KeyboardSettingsActivity extends SettingsActivity { /* empty */ } /** Activity for the navigation mode settings. */ public static class NavigationModeSettingsActivity extends SettingsActivity { /* empty */ } diff --git a/src/com/android/settings/core/gateway/SettingsGateway.java b/src/com/android/settings/core/gateway/SettingsGateway.java index eeecdd54844..bc2ab68764c 100644 --- a/src/com/android/settings/core/gateway/SettingsGateway.java +++ b/src/com/android/settings/core/gateway/SettingsGateway.java @@ -183,6 +183,9 @@ import com.android.settings.privatespace.delete.PrivateSpaceDeleteFragment; import com.android.settings.privatespace.delete.PrivateSpaceDeletionProgressFragment; import com.android.settings.privatespace.onelock.PrivateSpaceBiometricSettings; import com.android.settings.regionalpreferences.FirstDayOfWeekItemFragment; +import com.android.settings.regionalpreferences.MeasurementSystemItemFragment; +import com.android.settings.regionalpreferences.NumberingSystemLocaleListFragment; +import com.android.settings.regionalpreferences.RegionPickerFragment; import com.android.settings.regionalpreferences.RegionalPreferencesEntriesFragment; import com.android.settings.regionalpreferences.TemperatureUnitFragment; import com.android.settings.safetycenter.MoreSecurityPrivacyFragment; @@ -396,9 +399,12 @@ public class SettingsGateway { ColorAndMotionFragment.class.getName(), ColorContrastFragment.class.getName(), LongBackgroundTasksDetails.class.getName(), + RegionPickerFragment.class.getName(), RegionalPreferencesEntriesFragment.class.getName(), TemperatureUnitFragment.class.getName(), FirstDayOfWeekItemFragment.class.getName(), + MeasurementSystemItemFragment.class.getName(), + NumberingSystemLocaleListFragment.class.getName(), BatteryInfoFragment.class.getName(), UserAspectRatioDetails.class.getName(), ScreenTimeoutSettings.class.getName(), diff --git a/src/com/android/settings/regionalpreferences/NumberingPreferencesFragment.java b/src/com/android/settings/regionalpreferences/NumberingPreferencesFragment.java index 1c5015fe7b0..8a9840f9f87 100644 --- a/src/com/android/settings/regionalpreferences/NumberingPreferencesFragment.java +++ b/src/com/android/settings/regionalpreferences/NumberingPreferencesFragment.java @@ -32,8 +32,14 @@ import java.util.ArrayList; import java.util.List; import java.util.Locale; -/** Provides options of numbering system to each language. */ -public class NumberingPreferencesFragment extends DashboardFragment { +/** + * Provides options of numbering system to each language. + * + * @deprecated Use {@link NumberingSystemLocaleListFragment} instead. + */ +@Deprecated +public class NumberingPreferencesFragment extends DashboardFragment { + /** Initializes variables. */ @VisibleForTesting String initTitle() { diff --git a/src/com/android/settings/regionalpreferences/NumberingSystemFormatSelectionFragment.java b/src/com/android/settings/regionalpreferences/NumberingSystemFormatSelectionFragment.java new file mode 100644 index 00000000000..bbe14b6a4ad --- /dev/null +++ b/src/com/android/settings/regionalpreferences/NumberingSystemFormatSelectionFragment.java @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.regionalpreferences; + +import android.app.settings.SettingsEnums; +import android.content.Context; +import android.os.Bundle; +import android.util.Log; + +import androidx.annotation.NonNull; + +import com.android.internal.app.LocaleHelper; +import com.android.settings.R; +import com.android.settings.dashboard.DashboardFragment; +import com.android.settingslib.core.AbstractPreferenceController; + +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +/** Provides options of numbering system to each language. */ +public class NumberingSystemFormatSelectionFragment extends DashboardFragment { + + @Override + public void onCreate(@NonNull Bundle icicle) { + super.onCreate(icicle); + getActivity().setTitle(initTitle()); + } + + /** + * Get a list of {@link AbstractPreferenceController} for this fragment. + */ + @Override + protected List createPreferenceControllers(Context context) { + NumberingSystemItemController controller = + new NumberingSystemItemController(context, getArguments()); + controller.setParentFragment(this); + List listControllers = new ArrayList<>(); + listControllers.add(controller); + return listControllers; + } + + @Override + protected int getPreferenceScreenResId() { + return R.xml.regional_preference_numbering_system_page; + } + + @Override + protected String getLogTag() { + return NumberingSystemFormatSelectionFragment.class.getSimpleName(); + } + + @Override + public int getMetricsCategory() { + return SettingsEnums.NUMBERING_SYSTEM_NUMBER_FORMAT_SELECTION_PREFERENCE; + } + + private String initTitle() { + String selectedLanguage = getArguments().getString( + NumberingSystemItemController.KEY_SELECTED_LANGUAGE, ""); + if (selectedLanguage.isEmpty()) { + Log.w(getLogTag(), "No selected language."); + return ""; + } + Locale locale = Locale.forLanguageTag(selectedLanguage); + return LocaleHelper.getDisplayName(locale.stripExtensions(), locale, true); + } +} diff --git a/src/com/android/settings/regionalpreferences/NumberingSystemItemController.java b/src/com/android/settings/regionalpreferences/NumberingSystemItemController.java index 9f0c4041ebf..fe0a088f8bf 100644 --- a/src/com/android/settings/regionalpreferences/NumberingSystemItemController.java +++ b/src/com/android/settings/regionalpreferences/NumberingSystemItemController.java @@ -34,6 +34,7 @@ import com.android.internal.app.LocaleStore; import com.android.settings.core.BasePreferenceController; import com.android.settings.core.SubSettingLauncher; import com.android.settings.dashboard.DashboardFragment; +import com.android.settings.flags.Flags; import com.android.settings.overlay.FeatureFactory; import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; import com.android.settingslib.widget.SelectorWithWidgetPreference; @@ -158,10 +159,15 @@ public class NumberingSystemItemController extends BasePreferenceController { extra.putString(RegionalPreferencesEntriesFragment.ARG_KEY_REGIONAL_PREFERENCE, ARG_VALUE_NUMBERING_SYSTEM_SELECT); extra.putString(KEY_SELECTED_LANGUAGE, selectedLanguage); + + String destinationFragment = NumberingPreferencesFragment.class.getName(); + if (Flags.regionalPreferencesApiEnabled()) { + destinationFragment = NumberingSystemFormatSelectionFragment.class.getName(); + } new SubSettingLauncher(preference.getContext()) - .setDestination(NumberingPreferencesFragment.class.getName()) + .setDestination(destinationFragment) .setSourceMetricsCategory( - SettingsEnums.NUMBERING_SYSTEM_LANGUAGE_SELECTION_PREFERENCE) + SettingsEnums.NUMBERING_SYSTEM_LANGUAGE_SELECTION_PREFERENCE) .setArguments(extra) .launch(); } diff --git a/src/com/android/settings/regionalpreferences/NumberingSystemLocaleListFragment.java b/src/com/android/settings/regionalpreferences/NumberingSystemLocaleListFragment.java new file mode 100644 index 00000000000..6a39b23241c --- /dev/null +++ b/src/com/android/settings/regionalpreferences/NumberingSystemLocaleListFragment.java @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.regionalpreferences; + +import static android.provider.Settings.ACTION_NUMBERING_SYSTEM_SETTINGS; + +import android.app.Activity; +import android.app.settings.SettingsEnums; +import android.content.Context; +import android.os.Bundle; +import android.os.LocaleList; + +import androidx.annotation.NonNull; + +import com.android.internal.app.LocaleStore; +import com.android.settings.R; +import com.android.settings.dashboard.DashboardFragment; +import com.android.settingslib.core.AbstractPreferenceController; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Set; + +/** Provides locale list for numbering system settings. */ +public class NumberingSystemLocaleListFragment extends DashboardFragment { + + @Override + public void onCreate(@NonNull Bundle icicle) { + super.onCreate(icicle); + + if (isEmptyNumberingSystemLocale()) { + getActivity().setResult(Activity.RESULT_CANCELED); + finish(); + } + + if (getIntent().getAction().equals(ACTION_NUMBERING_SYSTEM_SETTINGS)) { + // TODO: Generically log action. + } + + getActivity().setTitle(R.string.numbers_preferences_title); + getActivity().setResult(Activity.RESULT_OK); + } + + /** + * Get a list of {@link AbstractPreferenceController} for this fragment. + */ + @Override + protected List createPreferenceControllers(Context context) { + NumberingSystemItemController controller = + new NumberingSystemItemController(context, getExtraData()); + controller.setParentFragment(this); + List listControllers = new ArrayList<>(); + listControllers.add(controller); + return listControllers; + } + + @Override + protected int getPreferenceScreenResId() { + return R.xml.regional_preference_numbering_system_page; + } + + @Override + protected String getLogTag() { + return NumberingSystemLocaleListFragment.class.getSimpleName(); + } + + @Override + public int getMetricsCategory() { + return SettingsEnums.NUMBERING_SYSTEM_LANGUAGE_SELECTION_PREFERENCE; + } + + private static boolean isEmptyNumberingSystemLocale() { + LocaleList localeList = LocaleList.getDefault(); + Set localesHasNumberingSystems = new HashSet<>(); + for (int i = 0; i < localeList.size(); i++) { + Locale locale = localeList.get(i); + LocaleStore.LocaleInfo localeInfo = LocaleStore.getLocaleInfo(locale); + if (localeInfo.hasNumberingSystems()) { + localesHasNumberingSystems.add(locale); + } + } + return localesHasNumberingSystems.isEmpty(); + } + + private static Bundle getExtraData() { + Bundle extra = new Bundle(); + extra.putString(RegionalPreferencesEntriesFragment.ARG_KEY_REGIONAL_PREFERENCE, + NumberingSystemItemController.ARG_VALUE_LANGUAGE_SELECT); + return extra; + } +}