From 7038405f14b5a8ecec6fe11ffdbdb3602b833869 Mon Sep 17 00:00:00 2001 From: Annemarie Apple Date: Tue, 16 Apr 2024 02:42:51 +0000 Subject: [PATCH 1/8] Add READ_SYSTEM_GRAMMATICAL_GENDER to Settings app Change-Id: I9b6cbb55f7da836762a7f8fc795322c85e08f9ee Flag: EXEMPT XML Bug: 335025399 --- AndroidManifest.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 2b2a1b82490..964e114dbf8 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -148,6 +148,7 @@ + Date: Thu, 18 Apr 2024 21:27:24 +0800 Subject: [PATCH 2/8] Restrict WifiAPITest - Disable Wi-Fi functions below if user has DISALLOW_CHANGE_WIFI_STATE - disableNetwork - disconnect - enableNetwork Bug: 290612834 Flag: None Test: Manual testing Change-Id: I7435b30381401b10fa82b25fb245b1ed12bf3ade --- .../android/settings/wifi/WifiAPITest.java | 31 ++++++++++++++++--- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/src/com/android/settings/wifi/WifiAPITest.java b/src/com/android/settings/wifi/WifiAPITest.java index c8bcf7fe173..89538751685 100644 --- a/src/com/android/settings/wifi/WifiAPITest.java +++ b/src/com/android/settings/wifi/WifiAPITest.java @@ -18,7 +18,10 @@ package com.android.settings.wifi; import static android.content.Context.WIFI_SERVICE; +import static com.android.settingslib.wifi.WifiEnterpriseRestrictionUtils.isChangeWifiStateAllowed; + import android.app.settings.SettingsEnums; +import android.content.Context; import android.content.DialogInterface; import android.net.wifi.WifiManager; import android.os.Bundle; @@ -38,7 +41,7 @@ import com.android.settings.SettingsPreferenceFragment; public class WifiAPITest extends SettingsPreferenceFragment implements Preference.OnPreferenceClickListener { - private static final String TAG = "WifiAPITest"; + private static final String TAG = "WifiAPITest+++"; private int netid; //============================ @@ -69,18 +72,38 @@ public class WifiAPITest extends SettingsPreferenceFragment implements @Override public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { + Context context = getContext(); + if (context == null) { + return; + } addPreferencesFromResource(R.xml.wifi_api_test); + boolean isChangeWifiStateAllowed = isChangeWifiStateAllowed(context); final PreferenceScreen preferenceScreen = getPreferenceScreen(); mWifiDisconnect = (Preference) preferenceScreen.findPreference(KEY_DISCONNECT); - mWifiDisconnect.setOnPreferenceClickListener(this); + if (mWifiDisconnect != null) { + mWifiDisconnect.setEnabled(isChangeWifiStateAllowed); + if (isChangeWifiStateAllowed) { + mWifiDisconnect.setOnPreferenceClickListener(this); + } + } mWifiDisableNetwork = (Preference) preferenceScreen.findPreference(KEY_DISABLE_NETWORK); - mWifiDisableNetwork.setOnPreferenceClickListener(this); + if (mWifiDisableNetwork != null) { + mWifiDisableNetwork.setEnabled(isChangeWifiStateAllowed); + if (isChangeWifiStateAllowed) { + mWifiDisableNetwork.setOnPreferenceClickListener(this); + } + } mWifiEnableNetwork = (Preference) preferenceScreen.findPreference(KEY_ENABLE_NETWORK); - mWifiEnableNetwork.setOnPreferenceClickListener(this); + if (mWifiEnableNetwork != null) { + mWifiEnableNetwork.setEnabled(isChangeWifiStateAllowed); + if (isChangeWifiStateAllowed) { + mWifiEnableNetwork.setOnPreferenceClickListener(this); + } + } } From 4f5920c3f58f0afb9cccef9162e57f2e587b04f6 Mon Sep 17 00:00:00 2001 From: Chaohui Wang Date: Fri, 19 Apr 2024 16:00:03 +0800 Subject: [PATCH 3/8] Not include user input in regex Check prefix and remove prefix first, to avoid include user input in the regex to fix. Fix: 335136289 Test: manual - on SIMs Test: unit test Change-Id: Iff4dcfc3662c744d00b586d05e64b4f5fe33a0d8 --- .../android/settings/network/SubscriptionUtil.java | 13 +++++++------ .../settings/network/SubscriptionUtilTest.java | 8 ++++++++ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/com/android/settings/network/SubscriptionUtil.java b/src/com/android/settings/network/SubscriptionUtil.java index 56381e263b3..9277417dea4 100644 --- a/src/com/android/settings/network/SubscriptionUtil.java +++ b/src/com/android/settings/network/SubscriptionUtil.java @@ -75,8 +75,9 @@ public class SubscriptionUtil { static final String SUB_ID = "sub_id"; @VisibleForTesting static final String KEY_UNIQUE_SUBSCRIPTION_DISPLAYNAME = "unique_subscription_displayName"; - private static final String REGEX_DISPLAY_NAME_PREFIXES = "^"; - private static final String REGEX_DISPLAY_NAME_SUFFIXES = "\\s[0-9]+"; + private static final String REGEX_DISPLAY_NAME_SUFFIX = "\\s[0-9]+"; + private static final Pattern REGEX_DISPLAY_NAME_SUFFIX_PATTERN = + Pattern.compile(REGEX_DISPLAY_NAME_SUFFIX); private static List sAvailableResultsForTesting; private static List sActiveResultsForTesting; @@ -460,12 +461,12 @@ public class SubscriptionUtil { @VisibleForTesting static boolean isValidCachedDisplayName(String cachedDisplayName, String originalName) { - if (TextUtils.isEmpty(cachedDisplayName) || TextUtils.isEmpty(originalName)) { + if (TextUtils.isEmpty(cachedDisplayName) || TextUtils.isEmpty(originalName) + || !cachedDisplayName.startsWith(originalName)) { return false; } - String regex = REGEX_DISPLAY_NAME_PREFIXES + originalName + REGEX_DISPLAY_NAME_SUFFIXES; - Pattern pattern = Pattern.compile(regex); - Matcher matcher = pattern.matcher(cachedDisplayName); + String displayNameSuffix = cachedDisplayName.substring(originalName.length()); + Matcher matcher = REGEX_DISPLAY_NAME_SUFFIX_PATTERN.matcher(displayNameSuffix); return matcher.matches(); } diff --git a/tests/unit/src/com/android/settings/network/SubscriptionUtilTest.java b/tests/unit/src/com/android/settings/network/SubscriptionUtilTest.java index 6df281a5db2..46c281f1267 100644 --- a/tests/unit/src/com/android/settings/network/SubscriptionUtilTest.java +++ b/tests/unit/src/com/android/settings/network/SubscriptionUtilTest.java @@ -635,6 +635,14 @@ public class SubscriptionUtilTest { assertThat(SubscriptionUtil.isValidCachedDisplayName(cacheString, originalName)).isFalse(); } + @Test + public void isValidCachedDisplayName_withBrackets_noCrash() { + String originalName = "originalName("; + String cacheString = "originalName( 1234"; + + assertThat(SubscriptionUtil.isValidCachedDisplayName(cacheString, originalName)).isTrue(); + } + @Test public void isConnectedToWifi_hasWiFi_returnTrue() { addNetworkTransportType(NetworkCapabilities.TRANSPORT_WIFI); From 07335514c4bbdab83be422cfe3748f8b82f2964c Mon Sep 17 00:00:00 2001 From: Chaohui Wang Date: Wed, 17 Apr 2024 15:23:32 +0800 Subject: [PATCH 4/8] Create AppDataUsageSummaryController Content description for usage will be added later. Bug: 318780411 Test: manual - on AppDataUsage Test: unit test Change-Id: I3990218395dfd7553554346ea8ef00368ba57589 --- res/xml/app_data_usage.xml | 28 +------ .../settings/datausage/AppDataUsage.java | 31 ++------ .../AppDataUsageSummaryController.kt | 77 +++++++++++++++++++ .../settings/datausage/AppDataUsageTest.java | 31 -------- .../AppDataUsageSummaryControllerTest.kt | 65 ++++++++++++++++ 5 files changed, 151 insertions(+), 81 deletions(-) create mode 100644 src/com/android/settings/datausage/AppDataUsageSummaryController.kt create mode 100644 tests/spa_unit/src/com/android/settings/datausage/AppDataUsageSummaryControllerTest.kt diff --git a/res/xml/app_data_usage.xml b/res/xml/app_data_usage.xml index 034015cbb72..88f60ef6ca7 100644 --- a/res/xml/app_data_usage.xml +++ b/res/xml/app_data_usage.xml @@ -24,31 +24,9 @@ android:key="cycle" settings:controller="com.android.settings.datausage.AppDataUsageCycleController" /> - - - - - - - - - + mPackages = new ArraySet<>(); - private Preference mTotalUsage; - private Preference mForegroundUsage; - private Preference mBackgroundUsage; private RestrictedSwitchPreference mRestrictBackground; private Drawable mIcon; @@ -139,10 +132,6 @@ public class AppDataUsage extends DataUsageBaseFragment implements OnPreferenceC } } - mTotalUsage = findPreference(KEY_TOTAL_USAGE); - mForegroundUsage = findPreference(KEY_FOREGROUND_USAGE); - mBackgroundUsage = findPreference(KEY_BACKGROUND_USAGE); - final List uidList = getAppUidList(mAppItem.uids); initCycle(uidList); @@ -255,15 +244,17 @@ public class AppDataUsage extends DataUsageBaseFragment implements OnPreferenceC @VisibleForTesting void initCycle(List uidList) { - var controller = use(AppDataUsageCycleController.class); + var cycleController = use(AppDataUsageCycleController.class); + var summaryController = use(AppDataUsageSummaryController.class); var repository = new AppDataUsageDetailsRepository(mContext, mTemplate, mCycles, uidList); - controller.init(repository, data -> { - bindData(data); + cycleController.init(repository, data -> { + mIsLoading = false; + summaryController.update(data); return Unit.INSTANCE; }); if (mCycles != null) { Log.d(TAG, "setInitialCycles: " + mCycles + " " + mSelectedCycle); - controller.setInitialCycles(mCycles, mSelectedCycle); + cycleController.setInitialCycles(mCycles, mSelectedCycle); } } @@ -314,16 +305,6 @@ public class AppDataUsage extends DataUsageBaseFragment implements OnPreferenceC } } - @VisibleForTesting - void bindData(@NonNull NetworkUsageDetailsData data) { - mIsLoading = false; - mTotalUsage.setSummary(DataUsageUtils.formatDataUsage(mContext, data.getTotalUsage())); - mForegroundUsage.setSummary( - DataUsageUtils.formatDataUsage(mContext, data.getForegroundUsage())); - mBackgroundUsage.setSummary( - DataUsageUtils.formatDataUsage(mContext, data.getBackgroundUsage())); - } - private boolean getAppRestrictBackground() { final int uid = mAppItem.key; final int uidPolicy = services.mPolicyManager.getUidPolicy(uid); diff --git a/src/com/android/settings/datausage/AppDataUsageSummaryController.kt b/src/com/android/settings/datausage/AppDataUsageSummaryController.kt new file mode 100644 index 00000000000..a764c1d6cfe --- /dev/null +++ b/src/com/android/settings/datausage/AppDataUsageSummaryController.kt @@ -0,0 +1,77 @@ +/* + * 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.datausage + +import android.content.Context +import androidx.compose.foundation.layout.Column +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.res.stringResource +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.android.settings.R +import com.android.settings.datausage.lib.NetworkUsageDetailsData +import com.android.settings.spa.preference.ComposePreferenceController +import com.android.settingslib.spa.widget.preference.Preference +import com.android.settingslib.spa.widget.preference.PreferenceModel +import com.android.settingslib.spaprivileged.framework.compose.placeholder +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.map + +class AppDataUsageSummaryController(context: Context, preferenceKey: String) : + ComposePreferenceController(context, preferenceKey) { + + private val dataFlow = MutableStateFlow(NetworkUsageDetailsData.AllZero) + + private val totalUsageFlow = dataFlow.map { + DataUsageUtils.formatDataUsage(mContext, it.totalUsage).toString() + } + + private val foregroundUsageFlow = dataFlow.map { + DataUsageUtils.formatDataUsage(mContext, it.foregroundUsage).toString() + } + + private val backgroundUsageFlow = dataFlow.map { + DataUsageUtils.formatDataUsage(mContext, it.backgroundUsage).toString() + } + + override fun getAvailabilityStatus() = AVAILABLE + + fun update(data: NetworkUsageDetailsData) { + dataFlow.value = data + } + + @Composable + override fun Content() { + Column { + val totalUsage by totalUsageFlow.collectAsStateWithLifecycle(placeholder()) + val foregroundUsage by foregroundUsageFlow.collectAsStateWithLifecycle(placeholder()) + val backgroundUsage by backgroundUsageFlow.collectAsStateWithLifecycle(placeholder()) + Preference(object : PreferenceModel { + override val title = stringResource(R.string.total_size_label) + override val summary = { totalUsage } + }) + Preference(object : PreferenceModel { + override val title = stringResource(R.string.data_usage_label_foreground) + override val summary = { foregroundUsage } + }) + Preference(object : PreferenceModel { + override val title = stringResource(R.string.data_usage_label_background) + override val summary = { backgroundUsage } + }) + } + } +} diff --git a/tests/robotests/src/com/android/settings/datausage/AppDataUsageTest.java b/tests/robotests/src/com/android/settings/datausage/AppDataUsageTest.java index 1d841fa2505..4b8c9de5349 100644 --- a/tests/robotests/src/com/android/settings/datausage/AppDataUsageTest.java +++ b/tests/robotests/src/com/android/settings/datausage/AppDataUsageTest.java @@ -42,16 +42,13 @@ import android.os.Bundle; import android.os.Process; import android.telephony.SubscriptionManager; import android.util.ArraySet; -import android.util.Range; import androidx.fragment.app.FragmentActivity; -import androidx.preference.Preference; import androidx.preference.PreferenceManager; import androidx.preference.PreferenceScreen; import androidx.recyclerview.widget.RecyclerView; import com.android.settings.applications.AppInfoBase; -import com.android.settings.datausage.lib.NetworkUsageDetailsData; import com.android.settings.testutils.FakeFeatureFactory; import com.android.settings.testutils.shadow.ShadowDataUsageUtils; import com.android.settings.testutils.shadow.ShadowEntityHeaderController; @@ -252,34 +249,6 @@ public class AppDataUsageTest { verify(unrestrictedDataPref).setDisabledByAdmin(any(EnforcedAdmin.class)); } - @Test - public void bindData_shouldUpdateUsageSummary() { - mFragment = spy(new TestFragment()); - final Context context = RuntimeEnvironment.application; - ReflectionHelpers.setField(mFragment, "mContext", context); - final long backgroundBytes = 1234L; - final long foregroundBytes = 5678L; - final NetworkUsageDetailsData appUsage = new NetworkUsageDetailsData( - new Range<>(1L, 2L), - backgroundBytes + foregroundBytes, - foregroundBytes, - backgroundBytes - ); - final Preference backgroundPref = mock(Preference.class); - ReflectionHelpers.setField(mFragment, "mBackgroundUsage", backgroundPref); - final Preference foregroundPref = mock(Preference.class); - ReflectionHelpers.setField(mFragment, "mForegroundUsage", foregroundPref); - final Preference totalPref = mock(Preference.class); - ReflectionHelpers.setField(mFragment, "mTotalUsage", totalPref); - - mFragment.bindData(appUsage); - - verify(totalPref).setSummary( - DataUsageUtils.formatDataUsage(context, backgroundBytes + foregroundBytes)); - verify(backgroundPref).setSummary(DataUsageUtils.formatDataUsage(context, backgroundBytes)); - verify(foregroundPref).setSummary(DataUsageUtils.formatDataUsage(context, foregroundBytes)); - } - @Test @Config(shadows = {ShadowDataUsageUtils.class, ShadowSubscriptionManager.class, ShadowFragment.class}) diff --git a/tests/spa_unit/src/com/android/settings/datausage/AppDataUsageSummaryControllerTest.kt b/tests/spa_unit/src/com/android/settings/datausage/AppDataUsageSummaryControllerTest.kt new file mode 100644 index 00000000000..584295649aa --- /dev/null +++ b/tests/spa_unit/src/com/android/settings/datausage/AppDataUsageSummaryControllerTest.kt @@ -0,0 +1,65 @@ +/* + * 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.datausage + +import android.content.Context +import android.util.Range +import androidx.compose.ui.test.assertIsDisplayed +import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.onNodeWithText +import androidx.test.core.app.ApplicationProvider +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.android.settings.datausage.lib.NetworkUsageDetailsData +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class AppDataUsageSummaryControllerTest { + + @get:Rule + val composeTestRule = createComposeRule() + + private val context: Context = ApplicationProvider.getApplicationContext() + + private val controller = AppDataUsageSummaryController(context, TEST_KEY) + + @Test + fun summary() { + val appUsage = NetworkUsageDetailsData( + range = Range(1L, 2L), + totalUsage = BACKGROUND_BYTES + FOREGROUND_BYTES, + foregroundUsage = FOREGROUND_BYTES, + backgroundUsage = BACKGROUND_BYTES, + ) + + controller.update(appUsage) + composeTestRule.setContent { + controller.Content() + } + + composeTestRule.onNodeWithText("6.75 kB").assertIsDisplayed() + composeTestRule.onNodeWithText("5.54 kB").assertIsDisplayed() + composeTestRule.onNodeWithText("1.21 kB").assertIsDisplayed() + } + + private companion object { + const val TEST_KEY = "test_key" + const val BACKGROUND_BYTES = 1234L + const val FOREGROUND_BYTES = 5678L + } +} From e49cffe60f8397a1a07053fd955447b2a646d52c Mon Sep 17 00:00:00 2001 From: Bill Yi Date: Mon, 22 Apr 2024 01:31:27 -0700 Subject: [PATCH 5/8] Import translations. DO NOT MERGE ANYWHERE Auto-generated-cl: translation import Change-Id: Ia29286a18eaeca72bdbff24b8709e5d42a778df4 --- res/values-da/strings.xml | 6 +++--- res/values-de/strings.xml | 4 ++-- res/values-es/strings.xml | 2 +- res/values-et/strings.xml | 4 ++-- res/values-fr-rCA/strings.xml | 2 +- res/values-fr/strings.xml | 2 +- res/values-kk/strings.xml | 2 +- res/values-kn/strings.xml | 12 ++++++------ res/values-mr/strings.xml | 2 +- res/values-ne/strings.xml | 8 ++++---- res/values-or/strings.xml | 2 +- res/values-pl/strings.xml | 2 +- res/values-pt-rBR/strings.xml | 12 ++++++------ res/values-pt/strings.xml | 12 ++++++------ res/values-sl/strings.xml | 2 +- res/values-uz/strings.xml | 2 +- 16 files changed, 38 insertions(+), 38 deletions(-) diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml index 5f30373d4b0..d8c173478f1 100644 --- a/res/values-da/strings.xml +++ b/res/values-da/strings.xml @@ -1483,15 +1483,15 @@ "Vil du nulstille?" "Gendannelse af netværk er ikke tilgængeligt for denne bruger" "Netværksindstillingerne er blevet nulstillet" - "eSIM-kort kunne ikke ryddes" - "Noget gik galt, og dine eSIM-kort blev ikke ryddet.\n\nGenstart din enhed, og prøv igen." + "eSIM kunne ikke ryddes" + "Noget gik galt, og dine eSIM blev ikke ryddet.\n\nGenstart din enhed, og prøv igen." "Ryd alle data (gendan fabriksindstillinger)" "Ryd alle data (gendan fabriksindstillinger)"
  • "Musik"
  • \n
  • "Billeder"
  • \n
  • "Andre brugerdata"
  • "eSIM"
  • \n\n"Dette opsiger ikke automatisk dit mobilabonnement." "Alle dine personlige oplysninger og downloadede apps slettes. Denne handling kan ikke fortrydes." - "Alle dine personlige oplysninger, bl.a. downloadede apps og eSIM-kort, slettes. Denne handling kan ikke fortrydes." + "Alle dine personlige oplysninger, bl.a. downloadede apps og eSIM, slettes. Denne handling kan ikke fortrydes." "Vil du rydde alle data?" "Det er ikke muligt for denne bruger at gendanne fabriksindstillingerne" "Rydder" diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml index cf12e4bfa34..3f17d380cad 100644 --- a/res/values-de/strings.xml +++ b/res/values-de/strings.xml @@ -2084,7 +2084,7 @@ "Zum Öffnen mit zwei Fingern auf das Display doppeltippen" "Zum Öffnen Touch-Geste verwenden" "Touch-Geste für Bedienungshilfen verwenden" - "Wenn du diese Funktion verwenden möchtest, tippe unten auf dem Display auf die Schaltfläche \"Bedienungshilfen\" %s.\n\nWenn du zwischen den Funktionen wechseln möchtest, halte diese Schaltfläche gedrückt." + "Wenn du diese Funktion verwenden möchtest, tippe unten auf dem Display auf die Schaltfläche „Bedienungshilfen“ %s.\n\nWenn du zwischen den Funktionen wechseln möchtest, halte diese Schaltfläche gedrückt." "Tippe zum Verwenden dieser Funktion auf dem Display auf die Schaltfläche „Bedienungshilfen“." "Wenn du diese Funktion verwenden möchtest, halte beide Lautstärketasten gedrückt." "Tippe dreimal auf das Display, um die Vergrößerung zu starten oder zu beenden." @@ -2102,7 +2102,7 @@ "Mit drei Fingern nach oben wischen" "Auf Schaltfläche „Bedienungshilfen“ tippen" "Touch-Geste für Bedienungshilfen verwenden" - "Tippe unten auf dem Bildschirm auf die Schaltfläche \"Bedienungshilfen\" %s.\n\nWenn du zwischen den Funktionen wechseln möchtest, halte diese Schaltfläche gedrückt." + "Tippe unten auf dem Bildschirm auf die Schaltfläche „Bedienungshilfen“ %s.\n\nWenn du zwischen den Funktionen wechseln möchtest, halte diese Schaltfläche gedrückt." "Wische vom unteren Bildschirmrand mit zwei Fingern nach oben.\n\nWenn du zwischen den Funktionen wechseln möchtest, wische mit zwei Fingern über das Display nach oben und halte." "Wische vom unteren Bildschirmrand mit drei Fingern nach oben.\n\nWenn du zwischen den Funktionen wechseln möchtest, wische mit drei Fingern über das Display nach oben und halte." "Weitere Optionen" diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml index fb1669b8e50..e9f49e56809 100644 --- a/res/values-es/strings.xml +++ b/res/values-es/strings.xml @@ -2109,7 +2109,7 @@ "Más información sobre %1$s" "Mantener teclas de volumen" "mantener pulsadas las teclas de volumen" - "Mantén pulsadas las dos teclas de volumen" + "Mantén pulsadas las dos teclas de volumen." "Toca dos veces la pantalla con dos dedos" "tocar dos veces la pantalla con dos dedos" "Toca la pantalla {0,number,integer} veces rápidamente con dos dedos" diff --git a/res/values-et/strings.xml b/res/values-et/strings.xml index 12fe0f06e34..c179c7faf97 100644 --- a/res/values-et/strings.xml +++ b/res/values-et/strings.xml @@ -2757,7 +2757,7 @@ "Andmed ja sünkroonimine" "Parooli muutmine" "Konto seaded" - "Eemalda konto" + "Konto eemaldamine" "Konto lisamine" "Kas eemaldada konto?" "Administraator on selle muudatuse keelanud" @@ -5028,7 +5028,7 @@ "Ülekandega ei saa liituda" "Kuulamise alustamiseks paigutage QR-kood allpool keskele" "QR-kood ei ole sobilik vorming" - "Konvertimine eSIM-iks" + "Teisendamine eSIM-iks" "eSIM-i ülekandmine teise seadmesse" "{count,plural, =1{# rakendus}other{# rakendust}}" "Taustal installitud rakendused" diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml index 1abe842dcee..e25b905ec73 100644 --- a/res/values-fr-rCA/strings.xml +++ b/res/values-fr-rCA/strings.xml @@ -2232,7 +2232,7 @@ "Pour l\'application prise en charge seulement" "Taille et style des sous-titres" "Taille du texte : %1$s" - "Autres options" + "Plus d\'options" "Personnalisez la taille et le style des sous-titres pour les rendre plus faciles à lire" "Ces préférences de sous-titres ne sont pas prises en charge par toutes les applications multimédias" "bouton d\'accessibilité" diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml index 3ee499632bf..cf55c84bec5 100644 --- a/res/values-fr/strings.xml +++ b/res/values-fr/strings.xml @@ -2109,7 +2109,7 @@ "En savoir plus sur %1$s" "Maintenir enfoncés les boutons de volume" "maintenir enfoncés les boutons de volume" - "Appuyer de manière prolongée sur les deux boutons de volume" + "Appuyez de manière prolongée sur les deux boutons de volume" "Appui double à deux doigts sur l\'écran" "appui double à deux doigts sur l\'écran" "Appuyer rapidement sur l\'écran {0,number,integer} fois avec deux doigts" diff --git a/res/values-kk/strings.xml b/res/values-kk/strings.xml index 9101259109d..3f73321042f 100644 --- a/res/values-kk/strings.xml +++ b/res/values-kk/strings.xml @@ -594,7 +594,7 @@ "Қолданбаларды орнату"\n"Құпия кеңістігіңізде жеке Play Store болады, сондықтан қолданбаларды оңай орната аласыз." "Құпия кеңістік құлыпталып тұрған кезде, ондағы қолданбалар \"Рұқсаттарды басқару\" бөлімінде, құпиялық тақтасында және басқа параметрлерде көрсетілмейді.\n\nҚұпия кеңістікті жаңа құрылғыға көшіруге болмайды. Оны басқа құрылғыда пайдаланғыңыз келсе, жаңасын орнатуыңыз керек.\n\nҚұрылғыңызды компьютерге жалғаған немесе оған зиянды қолданбалар орнатқан кез келген адам құпия кеңістігіңізге кіре алады." "Құпия кеңістік реттеліп жатыр…" - "Құпия кеңістік құлыптаулы кезде, ондағы қолданбалардан келетін хабарландырулар жасырылады" + "Құлыптаулы құпия кеңістік қолданбаларының хабарландырулары жасырылады" "Құпия кеңістікті жасырып, автоматты құлыптау функциясын орнатыңыз" "Қажетті қолданбалар құпия кеңістікке орнатылып қойған" "Құпия кеңістікті реттеу мүмкін болмады" diff --git a/res/values-kn/strings.xml b/res/values-kn/strings.xml index b3c87618754..0905a9a93f8 100644 --- a/res/values-kn/strings.xml +++ b/res/values-kn/strings.xml @@ -269,7 +269,7 @@ "ಸ್ಕ್ರೀನ್ ಟೈಮ್‌ಔಟ್ ನಂತರ ಲಾಕ್ ಮಾಡಿ" "%1$s ಅವಧಿ ಮೀರಿದ ನಂತರ" "ಅವಧಿ ಮೀರಿದ ತತ್‌ಕ್ಷಣವೇ, %1$s ಅವರಿಂದ ಅನ್‌ಲಾಕ್ ಮಾಡದ ಹೊರತು" - "%2$s ಇದನ್ನು ಅನ್‌ಲಾಕ್ ಮಾಡಿ ಇರಿಸಿದ ಸಂದರ್ಭವನ್ನು ಹೊರತುಪಡಿಸಿ, ಬೇರೆ ಸಂದರ್ಭಗಳಲ್ಲಿ ಅವಧಿ ಮೀರಿದ ನಂತರ %1$s" + "%2$s ಮೂಲಕ ಅನ್‌ಲಾಕ್ ಮಾಡಿ ಇರಿಸಿದ ಸಂದರ್ಭವನ್ನು ಹೊರತುಪಡಿಸಿ, ಬೇರೆ ಸಂದರ್ಭಗಳಲ್ಲಿ ಅವಧಿ ಮೀರಿದ ನಂತರ %1$s" "ಲಾಕ್ ಸ್ಕ್ರೀನ್‌ಗೆ ಪಠ್ಯ ಸೇರಿಸಿ" "ಯಾವುದೂ ಇಲ್ಲ" "ಉದಾ. ಜೋ ಅವರ Android." @@ -660,7 +660,7 @@ "ಸ್ವಯಂ-ದೃಢೀಕರಣವನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಲು ಸಾಧನದ ಪಿನ್ ನಮೂದಿಸಿ" "ಸ್ವಯಂ-ದೃಢೀಕರಣವನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲು ಸಾಧನದ ಪಿನ್ ನಮೂದಿಸಿ" "ಸ್ಕ್ರೀನ್ ಲಾಕ್" - "ಕೆಲಸದ ಪ್ರೊಫೈಲ್ ಲಾಕ್" + "ಉದ್ಯೋಗ ಪ್ರೊಫೈಲ್ ಲಾಕ್" "ಯಾವುದೂ ಇಲ್ಲ" "ಸ್ವೈಪ್" "ಪ್ಯಾಟರ್ನ್" @@ -1676,7 +1676,7 @@ "ಪರದೆಯನ್ನು ಅನ್‌ಲಾಕ್ ಮಾಡಲು ಪ್ಯಾಟರ್ನ್ ಅನ್ನು ಚಿತ್ರಿಸಬೇಕು" "ಪ್ಯಾಟರ್ನ್ ಕಾಣಿಸುವಂತೆ ಮಾಡಿ" "ವರ್ಧಿತ ಪಿನ್ ಗೌಪ್ಯತೆ" - "PIN ನಮೂದಿಸುವಾಗ ಅನಿಮೇಷನ್‌ಗಳನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ" + "ಪಿನ್ ನಮೂದಿಸುವಾಗ ಅನಿಮೇಷನ್‌ಗಳನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ" "ಪ್ರೊಫೈಲ್ ಪ್ಯಾಟರ್ನ್ ಕಾಣಿಸುವಂತೆ ಮಾಡಿ" "ಟ್ಯಾಪ್ ಮಾಡಿದಾಗ ವೈಬ್ರೇಟ್‌ ಆಗು" "ಪವರ್ ಬಟನ್ ಲಾಕ್ ಆಗುತ್ತದೆ" @@ -1689,7 +1689,7 @@ "ಕೆಲಸದ ಪ್ರೊಫೈಲ್ ಭದ್ರತೆ" "ಕೆಲಸದ ಪ್ರೊಫೈಲ್ ಸ್ಕ್ರೀನ್ ಲಾಕ್" "ಒಂದು ಲಾಕ್ ಬಳಸಿ" - "ಕೆಲಸದ ಪ್ರೊಫೈಲ್ ಮತ್ತು ಸಾಧನ ಪರದೆಗೆ ಒಂದು ಲಾಕ್ ಬಳಸಿ" + "ಉದ್ಯೋಗ ಪ್ರೊಫೈಲ್ ಮತ್ತು ಸಾಧನ ಸ್ಕ್ರೀನ್‌ಗೆ ಒಂದು ಲಾಕ್ ಬಳಸಿ" "ಒಂದು ಲಾಕ್ ಬಳಸುವುದೇ?" "ನಿಮ್ಮ ಸಾಧನವು ನಿಮ್ಮ ಕೆಲಸದ ಪ್ರೊಫೈಲ್‌ನ ಪರದೆ ಲಾಕ್ ಅನ್ನು ಬಳಸುತ್ತದೆ. ಕೆಲಸದ ಕಾರ್ಯನೀತಿಗಳು ಎರಡೂ ಲಾಕ್‌ಗಳಿಗೆ ಅನ್ವಯಿಸುತ್ತವೆ." "ನಿಮ್ಮ ಕೆಲಸದ ಪ್ರೊಫೈಲ್ ಲಾಕ್ ನಿಮ್ಮ ಸಂಸ್ಥೆಯ ಭದ್ರತೆ ಅವಶ್ಯಕತೆಗಳನ್ನು ಪೂರೈಸುವುದಿಲ್ಲ. ನೀವು ಸಾಧನ ಪರದೆ ಮತ್ತು ನಿಮ್ಮ ಕೆಲಸದ ಪ್ರೊಫೈಲ್‌ಗೆ ಒಂದೇ ಲಾಕ್ ಅನ್ನು ನೀವು ಬಳಸಬಹುದು, ಆದರೆ ಯಾವುದೇ ಕೆಲಸದ ಲಾಕ್ ನೀತಿಗಳು ಅನ್ವಯಿಸುತ್ತವೆ." @@ -3409,7 +3409,7 @@ "ಲಾಕ್ ಸ್ಕ್ರೀನ್‌ ಸ್ಕಿಪ್ ಮಾಡಿ" "ಅನ್‌ಲಾಕ್‌ನ ಬಳಿಕ, ನೇರವಾಗಿ ಕೊನೆಯದಾಗಿ ಬಳಸಿದ ಸ್ಕ್ರೀನ್‌ಗೆ ಹೋಗಿ. ಲಾಕ್‌ಸ್ಕ್ರೀನ್‌ನಲ್ಲಿ ನೋಟಿಫಿಕೇಶನ್‌ಗಳು ಕಾಣುವುದಿಲ್ಲ. ಅವನ್ನು ನೋಡಲು ಮೇಲಿನಿಂದ ಕೆಳಕ್ಕೆ ಸ್ವೈಪ್ ಮಾಡಿ." "ಲಾಕ್ ಸ್ಕ್ರೀನ್, ಲಾಕ್‌ಸ್ಕ್ರೀನ್, ಸ್ಕಿಪ್ ಮಾಡಿ, ಬೈಪಾಸ್" - "ಕೆಲಸದ ಪ್ರೊಫೈಲ್ ಅನ್ನು ಲಾಕ್ ಮಾಡಿದಾಗ" + "ಉದ್ಯೋಗ ಪ್ರೊಫೈಲ್ ಅನ್ನು ಲಾಕ್ ಮಾಡಿದಾಗ" "ಲಾಕ್ ಸ್ಕ್ರೀನ್‌ನಲ್ಲಿ ಹೊಸ ಅಧಿಸೂಚನೆಗಳನ್ನು ಮಾತ್ರ ತೋರಿಸಿ" "ಲಾಕ್ ಸ್ಕ್ರೀನ್‌ನಿಂದ ಈ ಹಿಂದೆಯೇ ವೀಕ್ಷಿಸಿರುವ ಅಧಿಸೂಚನೆಗಳನ್ನು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ತೆಗೆದುಹಾಕಿ" "ಲಾಕ್‌ ಸ್ಕ್ರೀನ್ ಮೇಲೆ ನೋಟಿಫಿಕೇಶನ್‌ಗಳು" @@ -3722,7 +3722,7 @@ "ಆ್ಯಪ್ ಅನ್ನು ಪಿನ್ ಮಾಡಿದಾಗ, ಪಿನ್ ಮಾಡಲಾದ ಆ್ಯಪ್ ಇತರ ಆ್ಯಪ್‌ಗಳನ್ನು ತೆರೆಯಬಹುದು ಮತ್ತು ವೈಯಕ್ತಿಕ ಡೇಟಾಗೆ ಆ್ಯಕ್ಸೆಸ್ ದೊರಕಬಹುದು. \n\nಆ್ಯಪ್ ಪಿನ್ನಿಂಗ್ ಅನ್ನು ಬಳಸಲು: \n{0,number,integer}. ಆ್ಯಪ್ ಪಿನ್ನಿಂಗ್ ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಲು \n{1,number,integer}. ಸಮಗ್ರ ನೋಟವನ್ನು ತೆರೆಯಿರಿ \n{2,number,integer}. ಸ್ಕ್ರೀನ್‌ನ ಮೇಲ್ಭಾಗದಲ್ಲಿರುವ ಆ್ಯಪ್ ಐಕಾನ್ ಅನ್ನು ಟ್ಯಾಪ್ ಮಾಡಿ, ನಂತರ ಪಿನ್ ಅನ್ನು ಟ್ಯಾಪ್ ಮಾಡಿ" "ಆ್ಯಪ್ ಅನ್ನು ಪಿನ್ ಮಾಡಿದಾಗ, ಪಿನ್ ಮಾಡಲಾದ ಆ್ಯಪ್ ಇತರ ಆ್ಯಪ್‌ಗಳನ್ನು ತೆರೆಯಬಹುದು ಮತ್ತು ವೈಯಕ್ತಿಕ ಡೇಟಾಗೆ ಆ್ಯಕ್ಸೆಸ್ ದೊರಕಬಹುದು. \n\nನಿಮ್ಮ ಸಾಧನವನ್ನು ಇತರರೊಂದಿಗೆ ಸುರಕ್ಷಿತವಾಗಿ ಹಂಚಿಕೊಳ್ಳಲು ನೀವು ಬಯಸಿದರೆ, ಅದರ ಬದಲಿಗೆ ಅತಿಥಿ ಪ್ರೊಫೈಲ್ ಬಳಸಲು ಪ್ರಯತ್ನಿಸಿ. \n\nಆ್ಯಪ್ ಪಿನ್ನಿಂಗ್ ಅನ್ನು ಬಳಸಲು: \n{0,number,integer}. ಆ್ಯಪ್ ಪಿನ್ನಿಂಗ್ ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಲು \n{1,number,integer}. ಸಮಗ್ರ ನೋಟವನ್ನು ತೆರೆಯಿರಿ \n{2,number,integer}. ಸ್ಕ್ರೀನ್‌ನ ಮೇಲ್ಭಾಗದಲ್ಲಿರುವ ಆ್ಯಪ್ ಐಕಾನ್ ಅನ್ನು ಟ್ಯಾಪ್ ಮಾಡಿ, ನಂತರ ಪಿನ್ ಅನ್ನು ಟ್ಯಾಪ್ ಮಾಡಿ" "ಆ್ಯಪ್ ಅನ್ನು ಪಿನ್ ಮಾಡಿರುವಾಗ: \n\n• ವೈಯಕ್ತಿಕ ಡೇಟಾವನ್ನು ಪ್ರವೇಶಿಸಬಹುದು \n (ಉದಾ, ಸಂಪರ್ಕಗಳು ಮತ್ತು ಇಮೇಲ್ ಕಂಟೆಂಟ್‍) \n• ಪಿನ್ ಮಾಡಿದ ಆ್ಯಪ್ ಇತರೆ ಆ್ಯಪ್‌ಗಳನ್ನು ತೆರೆಯಬಹುದು\n\nನಿಮ್ಮ ವಿಶ್ವಾಸಾರ್ಹ ಜನರೊಂದಿಗೆ ಮಾತ್ರ ಆ್ಯಪ್ ಪಿನ್ನಿಂಗ್ ಬಳಸಿ." - "ಅನ್‌ಪಿನ್ ಮಾಡಲು ಅನ್‌ಲಾಕ್ ಪ್ಯಾಟರ್ನ್ ಕೇಳು" + "ಅನ್‌ಪಿನ್ ಮಾಡಲು ಅನ್‌ಲಾಕ್ ಪ್ಯಾಟರ್ನ್ ಕೇಳಿ" "ಅನ್‌ಪಿನ್‌ ಮಾಡಲು ಪಿನ್‌ ಕೇಳಿ" "ಅನ್‌ಪಿನ್ ಮಾಡಲು ಪಾಸ್‌ವರ್ಡ್ ಕೇಳು" "ಅನ್‌ಪಿನ್ ಮಾಡುವಾಗ ಸಾಧನ ಲಾಕ್ ಮಾಡು" diff --git a/res/values-mr/strings.xml b/res/values-mr/strings.xml index 04a4e3122d9..5d7cc720cb8 100644 --- a/res/values-mr/strings.xml +++ b/res/values-mr/strings.xml @@ -4169,7 +4169,7 @@ "तुमचे शोध आणि इनकमिंग कॉल कदाचित तुमच्या आयटी ॲडमिनला दृश्यमान असू शकतात" "क्रॉस-प्रोफाइल कॅलेंडर" "तुमच्या वैयक्तिक कॅलेंडरवर कार्य इव्हेंट दाखवा" - "work app बंद असतात तेव्हा ती थांबवलेली असतात आणि अ‍ॅक्सेस केली जाऊ शकत नाहीत किंवा तुम्हाला सूचना पाठवू शकत नाहीत" + "work app बंद असतात तेव्हा ती थांबवलेली असतात आणि अ‍ॅक्सेस केली जाऊ शकत नाहीत किंवा तुम्हाला नोटिफिकेशन पाठवू शकत नाहीत" "स्टोरेज व्यवस्थापित करा" "स्टोरेज स्थान मोकळे करण्यात मदत करण्यासाठी, स्टोरेज व्यवस्थापक तुमच्या डिव्हाइस वरून बॅक अप घेतलेले फोटो आणि व्हिडिओ काढतो." "फोटो आणि व्हिडिओ काढा" diff --git a/res/values-ne/strings.xml b/res/values-ne/strings.xml index 390a107ad61..b6a9fd31ed8 100644 --- a/res/values-ne/strings.xml +++ b/res/values-ne/strings.xml @@ -3288,7 +3288,7 @@ "ध्वनि र कम्पनलाई म्यूट गर्नुहोस्" "स्क्रिन अन नगर्नुहोस्‌" "बत्तीलाई धिपधिपाउन नदिनुहोस्" - "स्क्रिनमा सूचना नदेखाइयोस्" + "स्क्रिनमा सूचना नदेखाउनुहोस्" "स्क्रीनको शीर्षमा रहेको स्ट्याटस बारका आइकनहरू लुकाउनुहोस्" "एप आइकनमा नोटिफिकेसन डट लुकाउनुहोस्‌" "सूचना आउँदा अन नगर्नुहोस्" @@ -3396,7 +3396,7 @@ "केही वार्तालापहरू तैरने आइकनका रूपमा अन्य एपमाथि देखिने छन्" "सबै वार्तालापहरू बबलको रूपमा देखाउन दिइयोस्" "छानिएका वार्तालापहरू बबलको रूपमा देखाउनुहोस्" - "कुनै पनि वार्तालाप बबलको रूपमा नदेखाइयोस्" + "कुनै पनि वार्तालाप बबलको रूपमा नदेखाउनुहोस्" "वार्तालापहरू" "निम्नबाहेकका सबै वार्तालापहरू बबलको रूपमा देखिन सक्छन्" "यस वार्तालापका हकमा बबल निष्क्रिय पार्नुहोस्" @@ -3416,14 +3416,14 @@ "वार्तालाप, डिफल्ट र साइलेन्ट मोड देखाउनुहोस्" "सबै वार्तालाप देखाउनुहोस्" "साइलेन्ट वार्तालाप तथा सूचनाहरू लुकाउनुहोस्" - "कुनै पनि सूचना नदेखाइयोस्" + "कुनै पनि सूचना नदेखाउनुहोस्" "संवेदनशील सूचनाहरू" "लक हुँदा संवेदनशील जानकारी देखाउनुहोस्" "कार्य प्रोफाइलसम्धी संवेदनशील सूचनाहरू" "लक हुँदा कार्य प्रोफाइलको संवेदनशील जानकारी देखाउनुहोस्" "सबै सूचना देखाउनुहोस्" "अनलक गरिँदा मात्र संवेदनशील जानकारी देखाउनुहोस्" - "कुनै सूचना नदेखाइयोस्" + "कुनै सूचना नदेखाउनुहोस्" "तपाईं आफ्नो लक स्क्रिनमा के कुरा देखाउन चाहनुहुन्छ?" "लक स्क्रिन" "कार्यसम्बन्धी सबै सूचना देखाउनुहोस्" diff --git a/res/values-or/strings.xml b/res/values-or/strings.xml index cc08079f295..7d66886a17b 100644 --- a/res/values-or/strings.xml +++ b/res/values-or/strings.xml @@ -2109,7 +2109,7 @@ "%1$s ବିଷୟରେ ଅଧିକ ଜାଣନ୍ତୁ" "ଭଲ୍ୟୁମ କୀ\'କୁ ଧରି ରଖନ୍ତୁ" "ଭଲ୍ୟୁମ କୀ\'କୁ ଧରି ରଖନ୍ତୁ" - "ଉଭୟ ଭଲ୍ୟୁମ୍ କୀ’କୁ ଦବାଇ ଧରି ରଖନ୍ତୁ" + "ଉଭୟ ଭଲ୍ୟୁମ କୀ’କୁ ଦବାଇ ଧରି ରଖନ୍ତୁ" "ସ୍କ୍ରିନକୁ ଦୁଇଟି-ଆଙ୍ଗୁଠିରେ ଦୁଇଥର-ଟାପ କରନ୍ତୁ" "ସ୍କ୍ରିନକୁ ଦୁଇଟି-ଆଙ୍ଗୁଠିରେ ଦୁଇଥର-ଟାପ କରନ୍ତୁ" "ଦୁଇଟି ଆଙ୍ଗୁଠିରେ ସ୍କ୍ରିନକୁ ଶୀଘ୍ର {0,number,integer} ଥର ଟାପ କରନ୍ତୁ" diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml index 1fa99c4c807..26d3701a605 100644 --- a/res/values-pl/strings.xml +++ b/res/values-pl/strings.xml @@ -2159,7 +2159,7 @@ "Balans dźwięku" "Lewy" "Prawy" - "Domyślny" + "Domyślnie" "10 sekund" "30 sekund" "1 minuta" diff --git a/res/values-pt-rBR/strings.xml b/res/values-pt-rBR/strings.xml index dd4ad70c707..d5245d2514f 100644 --- a/res/values-pt-rBR/strings.xml +++ b/res/values-pt-rBR/strings.xml @@ -2084,13 +2084,13 @@ "Tocar duas vezes na tela com dois dedos para abrir" "Usar gesto para abrir" "Usar o gesto de acessibilidade" - "Para usar esse recurso, toque no botão de acessibilidade %s na parte inferior da tela.\n\nPara alternar entre os recursos, toque no botão de acessibilidade e o pressione." + "Para usar esse recurso, toque no botão de acessibilidade %s na parte inferior da tela.\n\nPara mudar de recurso, toque no botão de acessibilidade e o pressione." "Para usar esse recurso, toque no botão de acessibilidade na sua tela." - "Para usar esse recurso, toque nas duas teclas de volume e as mantenha pressionadas." + "Para usar esse recurso, toque e mantenha as duas teclas de volume pressionadas." "Para iniciar ou interromper a ampliação, toque três vezes em qualquer lugar da tela." "Para iniciar ou interromper a ampliação, toque duas vezes em qualquer lugar da tela com dois dedos." - "Para usar esse recurso, deslize de baixo para cima na tela com dois dedos.\n\nPara alternar entre os recursos, deslize de baixo para cima com dois dedos, sem soltar." - "Para usar esse recurso, deslize de baixo para cima na tela com três dedos.\n\nPara alternar entre os recursos, deslize de baixo para cima com três dedos, sem soltar." + "Para usar esse recurso, deslize dois dedos na rela, de baixo para cima.\n\nPara mudar de recurso, deslize dois dedos de baixo para cima da tela e segure." + "Para usar esse recurso, deslize de baixo para cima na tela com três dedos.\n\nPara mudar de recurso, deslize de baixo para cima com três dedos, sem soltar." "Para usar um recurso de acessibilidade, deslize de baixo para cima na tela com dois dedos.\n\nPara alternar entre recursos, deslize de baixo para cima com dois dedos, sem soltar." "Para usar um recurso de acessibilidade, deslize de baixo para cima na tela com três dedos.\n\nPara alternar entre recursos, deslize de baixo para cima com três dedos, sem soltar." "Ok" @@ -2102,14 +2102,14 @@ "Deslizar para cima com três dedos" "Tocar no botão de acessibilidade" "Usar o gesto de acessibilidade" - "Toque no botão de acessibilidade %s na parte inferior da tela.\n\nPara alternar entre os recursos, toque no botão de acessibilidade e mantenha-o pressionado." + "Toque no botão de acessibilidade %s na parte inferior da tela.\n\nPara mudar de recurso, toque no botão de acessibilidade e mantenha-o pressionado." "Deslize de baixo para cima na tela com dois dedos.\n\nPara alternar entre recursos, deslize de baixo para cima na tela com dois dedos, sem soltar." "Deslize de baixo para cima na tela com três dedos.\n\nPara alternar entre recursos, deslize de baixo para cima na tela com três dedos, sem soltar." "Mais opções" "Saiba mais sobre %1$s" "Manter as teclas de volume pressionadas" "manter as teclas de volume pressionadas" - "Toque nas duas teclas de volume e as mantenha pressionadas" + "Toque e mantenha as duas teclas de volume pressionadas" "Tocar duas vezes na tela com dois dedos" "tocar duas vezes na tela com dois dedos" "Toque na tela {0,number,integer} vezes rapidamente com dois dedos" diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml index dd4ad70c707..d5245d2514f 100644 --- a/res/values-pt/strings.xml +++ b/res/values-pt/strings.xml @@ -2084,13 +2084,13 @@ "Tocar duas vezes na tela com dois dedos para abrir" "Usar gesto para abrir" "Usar o gesto de acessibilidade" - "Para usar esse recurso, toque no botão de acessibilidade %s na parte inferior da tela.\n\nPara alternar entre os recursos, toque no botão de acessibilidade e o pressione." + "Para usar esse recurso, toque no botão de acessibilidade %s na parte inferior da tela.\n\nPara mudar de recurso, toque no botão de acessibilidade e o pressione." "Para usar esse recurso, toque no botão de acessibilidade na sua tela." - "Para usar esse recurso, toque nas duas teclas de volume e as mantenha pressionadas." + "Para usar esse recurso, toque e mantenha as duas teclas de volume pressionadas." "Para iniciar ou interromper a ampliação, toque três vezes em qualquer lugar da tela." "Para iniciar ou interromper a ampliação, toque duas vezes em qualquer lugar da tela com dois dedos." - "Para usar esse recurso, deslize de baixo para cima na tela com dois dedos.\n\nPara alternar entre os recursos, deslize de baixo para cima com dois dedos, sem soltar." - "Para usar esse recurso, deslize de baixo para cima na tela com três dedos.\n\nPara alternar entre os recursos, deslize de baixo para cima com três dedos, sem soltar." + "Para usar esse recurso, deslize dois dedos na rela, de baixo para cima.\n\nPara mudar de recurso, deslize dois dedos de baixo para cima da tela e segure." + "Para usar esse recurso, deslize de baixo para cima na tela com três dedos.\n\nPara mudar de recurso, deslize de baixo para cima com três dedos, sem soltar." "Para usar um recurso de acessibilidade, deslize de baixo para cima na tela com dois dedos.\n\nPara alternar entre recursos, deslize de baixo para cima com dois dedos, sem soltar." "Para usar um recurso de acessibilidade, deslize de baixo para cima na tela com três dedos.\n\nPara alternar entre recursos, deslize de baixo para cima com três dedos, sem soltar." "Ok" @@ -2102,14 +2102,14 @@ "Deslizar para cima com três dedos" "Tocar no botão de acessibilidade" "Usar o gesto de acessibilidade" - "Toque no botão de acessibilidade %s na parte inferior da tela.\n\nPara alternar entre os recursos, toque no botão de acessibilidade e mantenha-o pressionado." + "Toque no botão de acessibilidade %s na parte inferior da tela.\n\nPara mudar de recurso, toque no botão de acessibilidade e mantenha-o pressionado." "Deslize de baixo para cima na tela com dois dedos.\n\nPara alternar entre recursos, deslize de baixo para cima na tela com dois dedos, sem soltar." "Deslize de baixo para cima na tela com três dedos.\n\nPara alternar entre recursos, deslize de baixo para cima na tela com três dedos, sem soltar." "Mais opções" "Saiba mais sobre %1$s" "Manter as teclas de volume pressionadas" "manter as teclas de volume pressionadas" - "Toque nas duas teclas de volume e as mantenha pressionadas" + "Toque e mantenha as duas teclas de volume pressionadas" "Tocar duas vezes na tela com dois dedos" "tocar duas vezes na tela com dois dedos" "Toque na tela {0,number,integer} vezes rapidamente com dois dedos" diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml index 82b501da56f..56395fed3ea 100644 --- a/res/values-sl/strings.xml +++ b/res/values-sl/strings.xml @@ -1892,7 +1892,7 @@ "Obratno pomikanje" "Pri drsenju navzdol se vsebina premika navzgor" "Dotik spodnjega desnega kota" - "Za več možnosti se dotaknite sledilne ploščice spodaj desno." + "Za več možnosti se dotaknite sledilne ploščice spodaj desno" "Hitrost kazalca" "Učenje potez na sledilni ploščici" "sledilna ploščica, miška, kazalec, drsenje, vlečenje, desni klik, klik" diff --git a/res/values-uz/strings.xml b/res/values-uz/strings.xml index 3374a8d4d9e..1acac595320 100644 --- a/res/values-uz/strings.xml +++ b/res/values-uz/strings.xml @@ -813,7 +813,7 @@ "Yaqin-atrofdagi Bluetooth qurilmalarga ulanish uchun Bluetooth aloqasini yoqing" "Yaqin-atrofdagi Bluetooth qurilmalarga ulanish uchun Bluetooth aloqasini yoqing. Tezkor ulashuv, Qurilmamni top va qurilma geolokatsiyasi kabi funksiyalar Bluetooth ishlatadi." "Yaqin-atrofdagi Bluetooth qurilmalarga ulanish uchun Bluetooth aloqasini yoqing.\n\nQurilmadan foydalanishni yaxshilash uchun istalgan vaqt ilova va xizmatlar hatto Bluetooth oʻchiq boʻlsa ham Wi-Fi tarmoqlarni qidirishi mumkin. Bundan joylashuv axborotiga asoslangan funksiya va xizmatlarni yaxshilashda foydalanish mumkin. Bu funksiyani Bluetooth qidiruv sozlamalari orqali oʻzgartirish mumkin." - "Yaqin-atrofdagi Bluetooth qurilmalarga ulanish uchun Bluetooth aloqasini yoqing. Tezkor ulashuv, Qurilmamni top kabi funksiyalar va qurilma joylashuvi Bluetook ishlatadi.\n\nIlova va xizmatlar istalgan vaqtda, hatto Bluetooth oʻchiq boʻlsa ham, atrofdagi qurilmalarni qidirishi mumkin. Bu, masalan, joylashuvga asoslangan funksiyalar va xizmatlarni yaxshilash uchun ishlatilishi mumkin. Buni Bluetooth qidirish sozlamalari orqali oʻzgartirishingiz mumkin." + "Yaqin-atrofdagi Bluetooth qurilmalarga ulanish uchun Bluetooth aloqasini yoqing. Tezkor ulashuv, Qurilmamni top kabi funksiyalar va qurilma joylashuvi Bluetooth ishlatadi.\n\nIlova va xizmatlar istalgan vaqtda, hatto Bluetooth oʻchiq boʻlsa ham, atrofdagi qurilmalarni qidirishi mumkin. Bu, masalan, joylashuvga asoslangan funksiyalar va xizmatlarni yaxshilash uchun ishlatilishi mumkin. Buni Bluetooth qidirish sozlamalari orqali oʻzgartirishingiz mumkin." "Oʻzgartirish" "Qurilma tafsilotlari" "Klaviatura sozlamalari" From 5ae84662b5851b05e37e56c23ca74d9a362f9ffb Mon Sep 17 00:00:00 2001 From: Chaohui Wang Date: Mon, 22 Apr 2024 12:49:40 +0800 Subject: [PATCH 6/8] Check isConvertedPsimSubscription in new UI Bug: 326896614 Test: manual test Change-Id: I0d3c87a863f58a9e962fb87df5b8001be9edb767 --- .../settings/network/SubscriptionUtil.java | 21 ++++++++++++------- .../settings/spa/network/SimsSection.kt | 17 ++++++++++++++- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/src/com/android/settings/network/SubscriptionUtil.java b/src/com/android/settings/network/SubscriptionUtil.java index f3eb5190319..682d1541f1f 100644 --- a/src/com/android/settings/network/SubscriptionUtil.java +++ b/src/com/android/settings/network/SubscriptionUtil.java @@ -919,15 +919,22 @@ public class SubscriptionUtil { SubscriptionManager.class); List allSubInofs = subscriptionManager.getAllSubscriptionInfoList(); for (SubscriptionInfo subInfo : allSubInofs) { - if (subInfo != null) { - if (com.android.internal.telephony.flags.Flags.supportPsimToEsimConversion() - && subInfo.getSubscriptionId() == subId - && !subInfo.isEmbedded() - && subInfo.getTransferStatus() == TRANSFER_STATUS_CONVERTED) { - return true; - } + if (subInfo != null && subInfo.getSubscriptionId() == subId + && isConvertedPsimSubscription(subInfo)) { + return true; } } return false; } + + /** + * Checks if the subscription is converted pSIM. + */ + public static boolean isConvertedPsimSubscription(@NonNull SubscriptionInfo subInfo) { + Log.d(TAG, "isConvertedPsimSubscription: isEmbedded " + subInfo.isEmbedded()); + Log.d(TAG, "isConvertedPsimSubscription: getTransferStatus " + subInfo.getTransferStatus()); + return com.android.internal.telephony.flags.Flags.supportPsimToEsimConversion() + && !subInfo.isEmbedded() + && subInfo.getTransferStatus() == TRANSFER_STATUS_CONVERTED; + } } diff --git a/src/com/android/settings/spa/network/SimsSection.kt b/src/com/android/settings/spa/network/SimsSection.kt index df92b37e0cb..5f6810d9f5d 100644 --- a/src/com/android/settings/spa/network/SimsSection.kt +++ b/src/com/android/settings/spa/network/SimsSection.kt @@ -28,6 +28,7 @@ import androidx.compose.material.icons.outlined.SimCard import androidx.compose.material.icons.outlined.SimCardDownload import androidx.compose.runtime.Composable import androidx.compose.runtime.State +import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource @@ -44,6 +45,7 @@ import com.android.settingslib.spa.widget.ui.SettingsIcon import com.android.settingslib.spaprivileged.model.enterprise.Restrictions import com.android.settingslib.spaprivileged.template.preference.RestrictedPreference import com.android.settingslib.spaprivileged.template.preference.RestrictedTwoTargetSwitchPreference +import kotlinx.coroutines.flow.flow @Composable fun SimsSection(subscriptionInfoList: List) { @@ -63,11 +65,23 @@ private fun SimPreference(subInfo: SubscriptionInfo) { context.isSubscriptionEnabledFlow(subInfo.subscriptionId) }.collectAsStateWithLifecycle(initialValue = false) val phoneNumber = phoneNumber(subInfo) + val isConvertedPsim by remember(subInfo) { + flow { + emit(SubscriptionUtil.isConvertedPsimSubscription(subInfo)) + } + }.collectAsStateWithLifecycle(initialValue = false) RestrictedTwoTargetSwitchPreference( model = object : SwitchPreferenceModel { override val title = subInfo.displayName.toString() - override val summary = { phoneNumber.value ?: "" } + override val summary = { + if (isConvertedPsim) { + context.getString(R.string.sim_category_converted_sim) + } else { + phoneNumber.value ?: "" + } + } override val icon = @Composable { SimIcon(subInfo.isEmbedded) } + override val changeable = { !isConvertedPsim } override val checked = { checked.value } override val onCheckedChange = { newChecked: Boolean -> SubscriptionUtil.startToggleSubscriptionDialogActivity( @@ -78,6 +92,7 @@ private fun SimPreference(subInfo: SubscriptionInfo) { } }, restrictions = Restrictions(keys = listOf(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)), + primaryEnabled = { !isConvertedPsim }, ) { MobileNetworkUtils.launchMobileNetworkSettings(context, subInfo) } From 365c16b217b74781a82c8260048ac220c70eb10d Mon Sep 17 00:00:00 2001 From: Elliot Sisteron Date: Mon, 22 Apr 2024 14:49:52 +0000 Subject: [PATCH 7/8] Reset SafetyCenterManagerWrapper instance between tests. This is because some other tests may set a mock on this static value, which will persist across test cases (whereas in this test we want to test the real thing). Bug: 335557039 Change-Id: I14fc81922761159241636c78dbd47fce7bfeb533 Test: atest SafetyCenterManagerWrapperTest --- .../settings/safetycenter/SafetyCenterManagerWrapperTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/unit/src/com/android/settings/safetycenter/SafetyCenterManagerWrapperTest.java b/tests/unit/src/com/android/settings/safetycenter/SafetyCenterManagerWrapperTest.java index 432a5d67e98..35057a6ba6e 100644 --- a/tests/unit/src/com/android/settings/safetycenter/SafetyCenterManagerWrapperTest.java +++ b/tests/unit/src/com/android/settings/safetycenter/SafetyCenterManagerWrapperTest.java @@ -40,6 +40,7 @@ public class SafetyCenterManagerWrapperTest { @Before public void setUp() { MockitoAnnotations.initMocks(this); + SafetyCenterManagerWrapper.sInstance = null; } @Test From af82199317cae9ba2748880686f2a7ec4b5f5671 Mon Sep 17 00:00:00 2001 From: Yuri Lin Date: Wed, 17 Apr 2024 18:32:04 -0400 Subject: [PATCH 8/8] Add info on whether the rule is active to ZenMode modifying the corresponding methods on ZenModesBackend to collect that information from NotificationManager. Bug: 327419222 Test: ZenModesBackendTest, ZenModeTest Change-Id: I01cb0ffa21a7fecaa5128cec51ced3eff384f370 --- .../settings/notification/modes/ZenMode.java | 21 ++- .../notification/modes/ZenModesBackend.java | 30 +++- .../notification/modes/ZenModeTest.java | 17 ++- .../modes/ZenModesBackendTest.java | 133 ++++++++++++++---- 4 files changed, 157 insertions(+), 44 deletions(-) diff --git a/src/com/android/settings/notification/modes/ZenMode.java b/src/com/android/settings/notification/modes/ZenMode.java index b0036788ecd..2e615008ff5 100644 --- a/src/com/android/settings/notification/modes/ZenMode.java +++ b/src/com/android/settings/notification/modes/ZenMode.java @@ -75,20 +75,22 @@ class ZenMode { private final String mId; private final AutomaticZenRule mRule; + private boolean mIsActive; private final boolean mIsManualDnd; - ZenMode(String id, AutomaticZenRule rule) { - this(id, rule, false); + ZenMode(String id, AutomaticZenRule rule, boolean isActive) { + this(id, rule, isActive, false); } - private ZenMode(String id, AutomaticZenRule rule, boolean isManualDnd) { + private ZenMode(String id, AutomaticZenRule rule, boolean isActive, boolean isManualDnd) { mId = id; mRule = rule; + mIsActive = isActive; mIsManualDnd = isManualDnd; } - static ZenMode manualDndMode(AutomaticZenRule dndPolicyAsRule) { - return new ZenMode(MANUAL_DND_MODE_ID, dndPolicyAsRule, true); + static ZenMode manualDndMode(AutomaticZenRule dndPolicyAsRule, boolean isActive) { + return new ZenMode(MANUAL_DND_MODE_ID, dndPolicyAsRule, isActive, true); } @NonNull @@ -190,11 +192,16 @@ class ZenMode { return mIsManualDnd; } + public boolean isActive() { + return mIsActive; + } + @Override public boolean equals(@Nullable Object obj) { return obj instanceof ZenMode other && mId.equals(other.mId) - && mRule.equals(other.mRule); + && mRule.equals(other.mRule) + && mIsActive == other.mIsActive; } @Override @@ -204,6 +211,6 @@ class ZenMode { @Override public String toString() { - return mId + " -> " + mRule; + return mId + "(" + (mIsActive ? "active" : "inactive") + ") -> " + mRule; } } diff --git a/src/com/android/settings/notification/modes/ZenModesBackend.java b/src/com/android/settings/notification/modes/ZenModesBackend.java index 388f13b15f8..306ce5072ac 100644 --- a/src/com/android/settings/notification/modes/ZenModesBackend.java +++ b/src/com/android/settings/notification/modes/ZenModesBackend.java @@ -67,11 +67,14 @@ class ZenModesBackend { List getModes() { ArrayList modes = new ArrayList<>(); - modes.add(getManualDndMode()); + ZenModeConfig currentConfig = mNotificationManager.getZenModeConfig(); + modes.add(getManualDndMode(currentConfig)); Map zenRules = mNotificationManager.getAutomaticZenRules(); for (Map.Entry zenRuleEntry : zenRules.entrySet()) { - modes.add(new ZenMode(zenRuleEntry.getKey(), zenRuleEntry.getValue())); + String ruleId = zenRuleEntry.getKey(); + modes.add(new ZenMode(ruleId, zenRuleEntry.getValue(), + isRuleActive(ruleId, currentConfig))); } // TODO: b/331429435 - Sort modes. @@ -80,15 +83,20 @@ class ZenModesBackend { @Nullable ZenMode getMode(String id) { + ZenModeConfig currentConfig = mNotificationManager.getZenModeConfig(); if (ZenMode.MANUAL_DND_MODE_ID.equals(id)) { - return getManualDndMode(); + // Regardless of its contents, non-null manualRule means that manual rule is active. + return getManualDndMode(currentConfig); } else { AutomaticZenRule rule = mNotificationManager.getAutomaticZenRule(id); - return rule != null ? new ZenMode(id, rule) : null; + if (rule == null) { + return null; + } + return new ZenMode(id, rule, isRuleActive(id, currentConfig)); } } - private ZenMode getManualDndMode() { + private ZenMode getManualDndMode(ZenModeConfig config) { // TODO: b/333530553 - Read ZenDeviceEffects of manual DND. // TODO: b/333682392 - Replace with final strings for name & trigger description AutomaticZenRule manualDndRule = new AutomaticZenRule.Builder( @@ -103,7 +111,17 @@ class ZenModesBackend { .setInterruptionFilter(NotificationManager.INTERRUPTION_FILTER_PRIORITY) .build(); - return ZenMode.manualDndMode(manualDndRule); + return ZenMode.manualDndMode(manualDndRule, + config != null && config.manualRule != null); // isActive + } + + private static boolean isRuleActive(String id, ZenModeConfig config) { + if (config == null) { + // shouldn't happen if the config is coming from NM, but be safe + return false; + } + ZenModeConfig.ZenRule configRule = config.automaticRules.get(id); + return configRule != null && configRule.isAutomaticActive(); } void updateMode(ZenMode mode) { diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModeTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModeTest.java index 52680ca639c..761f10758c8 100644 --- a/tests/robotests/src/com/android/settings/notification/modes/ZenModeTest.java +++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModeTest.java @@ -45,12 +45,19 @@ public class ZenModeTest { @Test public void testBasicMethods() { - ZenMode zenMode = new ZenMode("id", ZEN_RULE); + ZenMode zenMode = new ZenMode("id", ZEN_RULE, true); assertThat(zenMode.getId()).isEqualTo("id"); assertThat(zenMode.getRule()).isEqualTo(ZEN_RULE); assertThat(zenMode.isManualDnd()).isFalse(); assertThat(zenMode.canBeDeleted()).isTrue(); + assertThat(zenMode.isActive()).isTrue(); + + ZenMode manualMode = ZenMode.manualDndMode(ZEN_RULE, false); + assertThat(manualMode.getId()).isEqualTo(ZenMode.MANUAL_DND_MODE_ID); + assertThat(manualMode.isManualDnd()).isTrue(); + assertThat(manualMode.canBeDeleted()).isFalse(); + assertThat(manualMode.isActive()).isFalse(); } @Test @@ -58,7 +65,7 @@ public class ZenModeTest { ZenMode zenMode = new ZenMode("id", new AutomaticZenRule.Builder("Rule", Uri.EMPTY) .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY) .setZenPolicy(ZEN_POLICY) - .build()); + .build(), false); assertThat(zenMode.getPolicy()).isEqualTo(ZEN_POLICY); } @@ -68,7 +75,7 @@ public class ZenModeTest { ZenMode zenMode = new ZenMode("id", new AutomaticZenRule.Builder("Rule", Uri.EMPTY) .setInterruptionFilter(INTERRUPTION_FILTER_ALL) .setZenPolicy(ZEN_POLICY) // should be ignored - .build()); + .build(), false); assertThat(zenMode.getPolicy()).isEqualTo( new ZenPolicy.Builder().allowAllSounds().showAllVisualEffects().build()); @@ -79,7 +86,7 @@ public class ZenModeTest { ZenMode zenMode = new ZenMode("id", new AutomaticZenRule.Builder("Rule", Uri.EMPTY) .setInterruptionFilter(INTERRUPTION_FILTER_ALARMS) .setZenPolicy(ZEN_POLICY) // should be ignored - .build()); + .build(), false); assertThat(zenMode.getPolicy()).isEqualTo( new ZenPolicy.Builder() @@ -95,7 +102,7 @@ public class ZenModeTest { ZenMode zenMode = new ZenMode("id", new AutomaticZenRule.Builder("Rule", Uri.EMPTY) .setInterruptionFilter(INTERRUPTION_FILTER_NONE) .setZenPolicy(ZEN_POLICY) // should be ignored - .build()); + .build(), false); assertThat(zenMode.getPolicy()).isEqualTo( new ZenPolicy.Builder() diff --git a/tests/robotests/src/com/android/settings/notification/modes/ZenModesBackendTest.java b/tests/robotests/src/com/android/settings/notification/modes/ZenModesBackendTest.java index 06ce80b24d2..a0f6f022fa3 100644 --- a/tests/robotests/src/com/android/settings/notification/modes/ZenModesBackendTest.java +++ b/tests/robotests/src/com/android/settings/notification/modes/ZenModesBackendTest.java @@ -56,6 +56,7 @@ import java.util.List; @RunWith(RobolectricTestRunner.class) public class ZenModesBackendTest { + private static final String ZEN_RULE_ID = "rule"; private static final AutomaticZenRule ZEN_RULE = new AutomaticZenRule.Builder("Driving", Uri.parse("drive")) .setType(AutomaticZenRule.TYPE_DRIVING) @@ -63,13 +64,11 @@ public class ZenModesBackendTest { .setZenPolicy(new ZenPolicy.Builder().allowAllSounds().build()) .build(); - private static final ZenMode MANUAL_DND_MODE = ZenMode.manualDndMode( + private static final AutomaticZenRule MANUAL_DND_RULE = new AutomaticZenRule.Builder("Do Not Disturb", Uri.EMPTY) .setInterruptionFilter(INTERRUPTION_FILTER_PRIORITY) .setZenPolicy(new ZenPolicy.Builder().allowAllSounds().build()) - .build()); - - private static final ZenMode ZEN_RULE_MODE = new ZenMode("rule", ZEN_RULE); + .build(); @Mock private NotificationManager mNm; @@ -77,6 +76,35 @@ public class ZenModesBackendTest { private Context mContext; private ZenModesBackend mBackend; + // Helper methods to add active/inactive rule state to a config. Returns a copy. + private ZenModeConfig configWithManualRule(ZenModeConfig base, boolean active) { + ZenModeConfig out = base.copy(); + if (!active) { + out.manualRule = null; + } else { + out.manualRule = new ZenModeConfig.ZenRule(); + } + return out; + } + + private ZenModeConfig configWithRule(ZenModeConfig base, String ruleId, AutomaticZenRule rule, + boolean active) { + ZenModeConfig out = base.copy(); + + // Note that there are many other fields of zenRule, but here we only set the ones + // relevant to determining whether or not it is active. + ZenModeConfig.ZenRule zenRule = new ZenModeConfig.ZenRule(); + zenRule.pkg = "package"; + zenRule.enabled = active; + zenRule.snoozing = false; + zenRule.condition = new Condition(rule.getConditionId(), "", + active ? Condition.STATE_TRUE : Condition.STATE_FALSE, + Condition.SOURCE_USER_ACTION); + out.automaticRules.put(ruleId, zenRule); + + return out; + } + @Before public void setup() { MockitoAnnotations.initMocks(this); @@ -85,6 +113,10 @@ public class ZenModesBackendTest { mContext = RuntimeEnvironment.application; mBackend = new ZenModesBackend(mContext); + + // Default catch-all case with no data. This isn't realistic, but tests below that rely + // on the config to get data on rules active will create those individually. + when(mNm.getZenModeConfig()).thenReturn(new ZenModeConfig()); } @Test @@ -102,6 +134,7 @@ public class ZenModesBackendTest { List modes = mBackend.getModes(); + // all modes exist, but none of them are currently active assertThat(modes).containsExactly( ZenMode.manualDndMode( new AutomaticZenRule.Builder( @@ -112,9 +145,10 @@ public class ZenModesBackendTest { .setTriggerDescription( mContext.getString(R.string.zen_mode_settings_summary)) .setManualInvocationAllowed(true) - .build()), - new ZenMode("rule1", ZEN_RULE), - new ZenMode("rule2", rule2)) + .build(), + false), + new ZenMode("rule1", ZEN_RULE, false), + new ZenMode("rule2", rule2, false)) .inOrder(); } @@ -136,26 +170,70 @@ public class ZenModesBackendTest { .setTriggerDescription( mContext.getString(R.string.zen_mode_settings_summary)) .setManualInvocationAllowed(true) - .build())); + .build(), false)); } @Test public void getMode_zenRule_returnsMode() { - when(mNm.getAutomaticZenRule(eq("rule"))).thenReturn(ZEN_RULE); + when(mNm.getAutomaticZenRule(eq(ZEN_RULE_ID))).thenReturn(ZEN_RULE); - ZenMode mode = mBackend.getMode("rule"); + ZenMode mode = mBackend.getMode(ZEN_RULE_ID); - assertThat(mode).isEqualTo(new ZenMode("rule", ZEN_RULE)); + assertThat(mode).isEqualTo(new ZenMode(ZEN_RULE_ID, ZEN_RULE, false)); } @Test public void getMode_missingRule_returnsNull() { when(mNm.getAutomaticZenRule(any())).thenReturn(null); - ZenMode mode = mBackend.getMode("rule"); + ZenMode mode = mBackend.getMode(ZEN_RULE_ID); assertThat(mode).isNull(); - verify(mNm).getAutomaticZenRule(eq("rule")); + verify(mNm).getAutomaticZenRule(eq(ZEN_RULE_ID)); + } + + @Test + public void getMode_manualDnd_returnsCorrectActiveState() { + // Set up a base config with an active rule to make sure we're looking at the correct info + ZenModeConfig configWithActiveRule = configWithRule(new ZenModeConfig(), ZEN_RULE_ID, + ZEN_RULE, true); + when(mNm.getZenModeConfig()).thenReturn(configWithActiveRule); + + // Equivalent to disallowAllSounds() + Policy dndPolicy = new Policy(0, 0, 0); + when(mNm.getNotificationPolicy()).thenReturn(dndPolicy); + + ZenMode mode = mBackend.getMode(ZenMode.MANUAL_DND_MODE_ID); + + // By default, manual rule is inactive + assertThat(mode.isActive()).isFalse(); + + // Now the returned config will represent the manual rule being active + when(mNm.getZenModeConfig()).thenReturn(configWithManualRule(configWithActiveRule, true)); + ZenMode activeMode = mBackend.getMode(ZenMode.MANUAL_DND_MODE_ID); + assertThat(activeMode.isActive()).isTrue(); + } + + @Test + public void getMode_zenRule_returnsCorrectActiveState() { + // Set up a base config that has an active manual rule and "rule2", to make sure we're + // looking at the correct rule's info. + ZenModeConfig configWithActiveRules = configWithRule( + configWithManualRule(new ZenModeConfig(), true), // active manual rule + "rule2", ZEN_RULE, true); // active rule 2 + + when(mNm.getAutomaticZenRule(eq(ZEN_RULE_ID))).thenReturn(ZEN_RULE); + when(mNm.getZenModeConfig()).thenReturn( + configWithRule(configWithActiveRules, ZEN_RULE_ID, ZEN_RULE, false)); + + // Round 1: the current config should indicate that the rule is not active + ZenMode mode = mBackend.getMode(ZEN_RULE_ID); + assertThat(mode.isActive()).isFalse(); + + when(mNm.getZenModeConfig()).thenReturn( + configWithRule(configWithActiveRules, ZEN_RULE_ID, ZEN_RULE, true)); + ZenMode activeMode = mBackend.getMode(ZEN_RULE_ID); + assertThat(activeMode.isActive()).isTrue(); } @Test @@ -163,7 +241,7 @@ public class ZenModesBackendTest { ZenMode manualDnd = ZenMode.manualDndMode( new AutomaticZenRule.Builder("DND", Uri.EMPTY) .setZenPolicy(new ZenPolicy.Builder().allowAllSounds().build()) - .build()); + .build(), false); mBackend.updateMode(manualDnd); @@ -173,7 +251,7 @@ public class ZenModesBackendTest { @Test public void updateMode_zenRule_updatesRule() { - ZenMode ruleMode = new ZenMode("rule", ZEN_RULE); + ZenMode ruleMode = new ZenMode("rule", ZEN_RULE, false); mBackend.updateMode(ruleMode); @@ -182,7 +260,7 @@ public class ZenModesBackendTest { @Test public void activateMode_manualDnd_setsZenModeImportant() { - mBackend.activateMode(MANUAL_DND_MODE, null); + mBackend.activateMode(ZenMode.manualDndMode(MANUAL_DND_RULE, false), null); verify(mNm).setZenMode(eq(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS), eq(null), any(), eq(true)); @@ -190,7 +268,8 @@ public class ZenModesBackendTest { @Test public void activateMode_manualDndWithDuration_setsZenModeImportantWithCondition() { - mBackend.activateMode(MANUAL_DND_MODE, Duration.ofMinutes(30)); + mBackend.activateMode(ZenMode.manualDndMode(MANUAL_DND_RULE, false), + Duration.ofMinutes(30)); verify(mNm).setZenMode(eq(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS), eq(ZenModeConfig.toTimeCondition(mContext, 30, 0, true).id), @@ -200,9 +279,9 @@ public class ZenModesBackendTest { @Test public void activateMode_zenRule_setsRuleStateActive() { - mBackend.activateMode(ZEN_RULE_MODE, null); + mBackend.activateMode(new ZenMode(ZEN_RULE_ID, ZEN_RULE, false), null); - verify(mNm).setAutomaticZenRuleState(eq(ZEN_RULE_MODE.getId()), + verify(mNm).setAutomaticZenRuleState(eq(ZEN_RULE_ID), eq(new Condition(ZEN_RULE.getConditionId(), "", Condition.STATE_TRUE, Condition.SOURCE_USER_ACTION))); } @@ -210,34 +289,36 @@ public class ZenModesBackendTest { @Test public void activateMode_zenRuleWithDuration_fails() { assertThrows(IllegalArgumentException.class, - () -> mBackend.activateMode(ZEN_RULE_MODE, Duration.ofMinutes(30))); + () -> mBackend.activateMode(new ZenMode(ZEN_RULE_ID, ZEN_RULE, false), + Duration.ofMinutes(30))); } @Test public void deactivateMode_manualDnd_setsZenModeOff() { - mBackend.deactivateMode(MANUAL_DND_MODE); + mBackend.deactivateMode(ZenMode.manualDndMode(MANUAL_DND_RULE, true)); verify(mNm).setZenMode(eq(Settings.Global.ZEN_MODE_OFF), eq(null), any(), eq(true)); } @Test public void deactivateMode_zenRule_setsRuleStateInactive() { - mBackend.deactivateMode(ZEN_RULE_MODE); + mBackend.deactivateMode(new ZenMode(ZEN_RULE_ID, ZEN_RULE, false)); - verify(mNm).setAutomaticZenRuleState(eq(ZEN_RULE_MODE.getId()), + verify(mNm).setAutomaticZenRuleState(eq(ZEN_RULE_ID), eq(new Condition(ZEN_RULE.getConditionId(), "", Condition.STATE_FALSE, Condition.SOURCE_USER_ACTION))); } @Test public void removeMode_zenRule_deletesRule() { - mBackend.removeMode(ZEN_RULE_MODE); + mBackend.removeMode(new ZenMode(ZEN_RULE_ID, ZEN_RULE, false)); - verify(mNm).removeAutomaticZenRule(ZEN_RULE_MODE.getId(), true); + verify(mNm).removeAutomaticZenRule(ZEN_RULE_ID, true); } @Test public void removeMode_manualDnd_fails() { - assertThrows(IllegalArgumentException.class, () -> mBackend.removeMode(MANUAL_DND_MODE)); + assertThrows(IllegalArgumentException.class, + () -> mBackend.removeMode(ZenMode.manualDndMode(MANUAL_DND_RULE, false))); } }