From 37cfdc7536471cc3510720ed35037068ce6e3323 Mon Sep 17 00:00:00 2001 From: Cole Faust Date: Fri, 18 Nov 2022 22:18:46 -0800 Subject: [PATCH 01/16] Fix errorprone warnings that should be errors This commit is part of a large scale change to fix errorprone errors that have been downgraded to warnings in the android source tree, so that they can be promoted to errors again. The full list of changes include the following, but not all will be present in any one individual commit: BadAnnotationImplementation BadShiftAmount BanJNDI BoxedPrimitiveEquality ComparableType ComplexBooleanConstant CollectionToArraySafeParameter ConditionalExpressionNumericPromotion DangerousLiteralNull DoubleBraceInitialization DurationFrom DurationTemporalUnit EmptyTopLevelDeclaration EqualsNull EqualsReference FormatString FromTemporalAccessor GetClassOnAnnotation GetClassOnClass HashtableContains IdentityBinaryExpression IdentityHashMapBoxing InstantTemporalUnit InvalidTimeZoneID InvalidZoneId IsInstanceIncompatibleType JUnitParameterMethodNotFound LockOnBoxedPrimitive MathRoundIntLong MislabeledAndroidString MisusedDayOfYear MissingSuperCall MisusedWeekYear ModifyingCollectionWithItself NoCanIgnoreReturnValueOnClasses NonRuntimeAnnotation NullableOnContainingClass NullTernary OverridesJavaxInjectableMethod ParcelableCreator PeriodFrom PreconditionsInvalidPlaceholder ProtoBuilderReturnValueIgnored ProtoFieldNullComparison RandomModInteger RectIntersectReturnValueIgnored ReturnValueIgnored SelfAssignment SelfComparison SelfEquals SizeGreaterThanOrEqualsZero StringBuilderInitWithChar TreeToString TryFailThrowable UnnecessaryCheckNotNull UnusedCollectionModifiedInPlace XorPower See https://errorprone.info/bugpatterns for more information on the checks. Bug: 253827323 Test: m RUN_ERROR_PRONE=true javac-check Merged-In: I21aa58ebc02327849ed2161dbbafcdc806c007f2 Change-Id: I2fbc9701a4ad1caa264e0b22e02fd0dab310eabd --- .../settings/fuelgauge/BatteryChartPreferenceController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java b/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java index 02248c9af51..8b2bf6b484a 100644 --- a/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java +++ b/src/com/android/settings/fuelgauge/BatteryChartPreferenceController.java @@ -629,7 +629,7 @@ public class BatteryChartPreferenceController extends AbstractPreferenceControll if (batteryHistoryMap == null || batteryHistoryMap.isEmpty()) { return null; } - Log.d(TAG, String.format("getBatteryLast24HrData() size=%d time=&d/ms", + Log.d(TAG, String.format("getBatteryLast24HrData() size=%d time=%d/ms", batteryHistoryMap.size(), (System.currentTimeMillis() - start))); final Map> batteryIndexedMap = ConvertUtils.getIndexedUsageMap( From 728a59199b7a63829d1296ccdeb31e2ea64c1102 Mon Sep 17 00:00:00 2001 From: Weng Su Date: Sat, 19 Nov 2022 05:59:15 +0800 Subject: [PATCH 02/16] Keep "Resetting your internet" when screen rotates - The fragment of Internet Settings will be destroyed and recreated when screen rotates - Move connectivity recovery class into singleton class to avoid service being killed when fragment context is destroyed - Check if connectivity is recovering when fragment is recreated and show resettings message if necessary Bug: 202802736 Test: manual test atest -c InternetResetHelperTest make RunSettingsRoboTests ROBOTEST_FILTER=NetworkProviderSettingsTest Change-Id: Iae9585ff8366b8b71b4c39dc0ec7e87a0320fa5a --- .../settings/network/InternetResetHelper.java | 212 ++++++++++-------- .../network/NetworkProviderSettings.java | 23 +- .../network/InternetResetHelperTest.java | 134 +++++------ 3 files changed, 183 insertions(+), 186 deletions(-) diff --git a/src/com/android/settings/network/InternetResetHelper.java b/src/com/android/settings/network/InternetResetHelper.java index 086ef1b1c5d..7920cca8f61 100644 --- a/src/com/android/settings/network/InternetResetHelper.java +++ b/src/com/android/settings/network/InternetResetHelper.java @@ -21,14 +21,9 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.net.wifi.WifiManager; -import android.os.HandlerThread; -import android.os.Process; -import android.text.TextUtils; import android.util.Log; -import androidx.annotation.UiThread; import androidx.annotation.VisibleForTesting; -import androidx.annotation.WorkerThread; import androidx.lifecycle.Lifecycle; import androidx.lifecycle.LifecycleObserver; import androidx.lifecycle.OnLifecycleEvent; @@ -38,14 +33,14 @@ import androidx.preference.PreferenceCategory; import com.android.settingslib.connectivity.ConnectivitySubsystemsRecoveryManager; import com.android.settingslib.utils.HandlerInjector; +import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.List; /** * Helper class to restart connectivity for all requested subsystems. */ -public class InternetResetHelper implements LifecycleObserver, - ConnectivitySubsystemsRecoveryManager.RecoveryStatusCallback { +public class InternetResetHelper implements LifecycleObserver { protected static final String TAG = "InternetResetHelper"; public static final long RESTART_TIMEOUT_MS = 15_000; // 15 seconds @@ -61,41 +56,40 @@ public class InternetResetHelper implements LifecycleObserver, protected final IntentFilter mWifiStateFilter; protected final BroadcastReceiver mWifiStateReceiver = new BroadcastReceiver() { @Override - @WorkerThread public void onReceive(Context context, Intent intent) { - if (intent != null && TextUtils.equals(intent.getAction(), - WifiManager.NETWORK_STATE_CHANGED_ACTION)) { - updateWifiStateChange(); - } + updateWifiStateChange(); } }; - protected ConnectivitySubsystemsRecoveryManager mConnectivitySubsystemsRecoveryManager; - protected HandlerThread mWorkerThread; - protected boolean mIsRecoveryReady; - protected boolean mIsWifiReady; + protected RecoveryWorker mRecoveryWorker; + protected boolean mIsWifiReady = true; protected HandlerInjector mHandlerInjector; - protected final Runnable mResumeRunnable = () -> { - resumePreferences(); - }; protected final Runnable mTimeoutRunnable = () -> { - mIsRecoveryReady = true; + Log.w(TAG, "Resume preferences due to connectivity subsystems recovery timed out."); + mRecoveryWorker.clearRecovering(); mIsWifiReady = true; resumePreferences(); }; - public InternetResetHelper(Context context, Lifecycle lifecycle) { + public InternetResetHelper(Context context, Lifecycle lifecycle, + NetworkMobileProviderController mobileNetworkController, + Preference wifiTogglePreferences, + PreferenceCategory connectedWifiEntryPreferenceCategory, + PreferenceCategory firstWifiEntryPreferenceCategory, + PreferenceCategory wifiEntryPreferenceCategory, + Preference resettingPreference) { mContext = context; + mMobileNetworkController = mobileNetworkController; + mWifiTogglePreferences = wifiTogglePreferences; + mWifiNetworkPreferences.add(connectedWifiEntryPreferenceCategory); + mWifiNetworkPreferences.add(firstWifiEntryPreferenceCategory); + mWifiNetworkPreferences.add(wifiEntryPreferenceCategory); + mResettingPreference = resettingPreference; + mHandlerInjector = new HandlerInjector(context.getMainThreadHandler()); mWifiManager = mContext.getSystemService(WifiManager.class); mWifiStateFilter = new IntentFilter(WifiManager.NETWORK_STATE_CHANGED_ACTION); - - mWorkerThread = new HandlerThread(TAG - + "{" + Integer.toHexString(System.identityHashCode(this)) + "}", - Process.THREAD_PRIORITY_BACKGROUND); - mWorkerThread.start(); - mConnectivitySubsystemsRecoveryManager = new ConnectivitySubsystemsRecoveryManager( - mContext, mWorkerThread.getThreadHandler()); + mRecoveryWorker = RecoveryWorker.getInstance(mContext, this); if (lifecycle != null) { lifecycle.addObserver(this); @@ -118,72 +112,18 @@ public class InternetResetHelper implements LifecycleObserver, /** @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) */ @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY) public void onDestroy() { - mHandlerInjector.removeCallbacks(mResumeRunnable); mHandlerInjector.removeCallbacks(mTimeoutRunnable); - mWorkerThread.quit(); - } - - @Override - @WorkerThread - public void onSubsystemRestartOperationBegin() { - Log.d(TAG, "The connectivity subsystem is starting for recovery."); - } - - @Override - @WorkerThread - public void onSubsystemRestartOperationEnd() { - Log.d(TAG, "The connectivity subsystem is done for recovery."); - if (!mIsRecoveryReady) { - mIsRecoveryReady = true; - mHandlerInjector.postDelayed(mResumeRunnable, 0 /* delayMillis */); - } } @VisibleForTesting - @WorkerThread protected void updateWifiStateChange() { if (!mIsWifiReady && mWifiManager.isWifiEnabled()) { Log.d(TAG, "The Wi-Fi subsystem is done for recovery."); mIsWifiReady = true; - mHandlerInjector.postDelayed(mResumeRunnable, 0 /* delayMillis */); + resumePreferences(); } } - /** - * Sets the resetting preference. - */ - @UiThread - public void setResettingPreference(Preference preference) { - mResettingPreference = preference; - } - - /** - * Sets the mobile network controller. - */ - @UiThread - public void setMobileNetworkController(NetworkMobileProviderController controller) { - mMobileNetworkController = controller; - } - - /** - * Sets the Wi-Fi toggle preference. - */ - @UiThread - public void setWifiTogglePreference(Preference preference) { - mWifiTogglePreferences = preference; - } - - /** - * Adds the Wi-Fi network preference. - */ - @UiThread - public void addWifiNetworkPreference(PreferenceCategory preference) { - if (preference != null) { - mWifiNetworkPreferences.add(preference); - } - } - - @UiThread protected void suspendPreferences() { Log.d(TAG, "Suspend the subsystem preferences"); if (mMobileNetworkController != null) { @@ -201,9 +141,9 @@ public class InternetResetHelper implements LifecycleObserver, } } - @UiThread protected void resumePreferences() { - if (mIsRecoveryReady && mMobileNetworkController != null) { + boolean isRecoveryReady = !mRecoveryWorker.isRecovering(); + if (isRecoveryReady && mMobileNetworkController != null) { Log.d(TAG, "Resume the Mobile Network controller"); mMobileNetworkController.hidePreference(false /* hide */, true /* immediately */); } @@ -214,7 +154,7 @@ public class InternetResetHelper implements LifecycleObserver, pref.setVisible(true); } } - if (mIsRecoveryReady && mIsWifiReady) { + if (isRecoveryReady && mIsWifiReady) { mHandlerInjector.removeCallbacks(mTimeoutRunnable); if (mResettingPreference != null) { Log.d(TAG, "Resume the Resetting preference"); @@ -223,21 +163,99 @@ public class InternetResetHelper implements LifecycleObserver, } } - /** - * Restart connectivity for all requested subsystems. - */ - @UiThread + protected void showResettingAndSendTimeoutChecks() { + suspendPreferences(); + mHandlerInjector.postDelayed(mTimeoutRunnable, RESTART_TIMEOUT_MS); + } + + /** Restart connectivity for all requested subsystems. */ public void restart() { - if (!mConnectivitySubsystemsRecoveryManager.isRecoveryAvailable()) { + if (!mRecoveryWorker.isRecoveryAvailable()) { Log.e(TAG, "The connectivity subsystem is not available to restart."); return; } - - Log.d(TAG, "The connectivity subsystem is restarting for recovery."); - suspendPreferences(); - mIsRecoveryReady = false; + showResettingAndSendTimeoutChecks(); mIsWifiReady = !mWifiManager.isWifiEnabled(); - mHandlerInjector.postDelayed(mTimeoutRunnable, RESTART_TIMEOUT_MS); - mConnectivitySubsystemsRecoveryManager.triggerSubsystemRestart(null /* reason */, this); + mRecoveryWorker.triggerRestart(); + } + + /** Check if the connectivity subsystem is under recovering. */ + public void checkRecovering() { + if (!mRecoveryWorker.isRecovering()) return; + mIsWifiReady = false; + showResettingAndSendTimeoutChecks(); + } + + /** + * This is a singleton class for ConnectivitySubsystemsRecoveryManager worker. + */ + @VisibleForTesting + public static class RecoveryWorker implements + ConnectivitySubsystemsRecoveryManager.RecoveryStatusCallback { + private static final String TAG = "RecoveryWorker"; + private static RecoveryWorker sInstance; + private static WeakReference sCallback; + private static ConnectivitySubsystemsRecoveryManager sRecoveryManager; + private static boolean sIsRecovering; + + /** + * Create a singleton class for ConnectivitySubsystemsRecoveryManager. + * + * @param context The context to use for the content resolver. + * @param callback The callback of {@link InternetResetHelper} object. + * @return an instance of {@link RecoveryWorker} object. + */ + public static RecoveryWorker getInstance(Context context, InternetResetHelper callback) { + sCallback = new WeakReference<>(callback); + if (sInstance != null) return sInstance; + + sInstance = new RecoveryWorker(); + Context appContext = context.getApplicationContext(); + sRecoveryManager = new ConnectivitySubsystemsRecoveryManager(appContext, + appContext.getMainThreadHandler()); + return sInstance; + } + + /** Returns true, If the subsystem service is recovering. */ + public boolean isRecovering() { + return sIsRecovering; + } + + /** Clear the recovering flag. */ + public void clearRecovering() { + sIsRecovering = false; + } + + /** Returns true, If the subsystem service is recovery available. */ + public boolean isRecoveryAvailable() { + return sRecoveryManager.isRecoveryAvailable(); + } + + /** Trigger connectivity recovery for all requested technologies. */ + public boolean triggerRestart() { + if (!isRecoveryAvailable()) { + Log.e(TAG, "The connectivity subsystem is not available to restart."); + return false; + } + sIsRecovering = true; + sRecoveryManager.triggerSubsystemRestart(null /* reason */, sInstance); + Log.d(TAG, "The connectivity subsystem is restarting for recovery."); + return true; + } + + @Override + public void onSubsystemRestartOperationBegin() { + Log.d(TAG, "The connectivity subsystem is starting for recovery."); + sIsRecovering = true; + } + + @Override + public void onSubsystemRestartOperationEnd() { + Log.d(TAG, "The connectivity subsystem is done for recovery."); + sIsRecovering = false; + InternetResetHelper callback = sCallback.get(); + if (callback == null) return; + callback.resumePreferences(); + } } } diff --git a/src/com/android/settings/network/NetworkProviderSettings.java b/src/com/android/settings/network/NetworkProviderSettings.java index b622a3c308d..7b7cdca37d1 100644 --- a/src/com/android/settings/network/NetworkProviderSettings.java +++ b/src/com/android/settings/network/NetworkProviderSettings.java @@ -337,6 +337,8 @@ public class NetworkProviderSettings extends RestrictedSettingsFragment addConnectedEthernetNetworkController(); addWifiSwitchPreferenceController(); mWifiStatusMessagePreference = findPreference(PREF_KEY_WIFI_STATUS_MESSAGE); + + checkConnectivityRecovering(); } private void updateAirplaneModeMsgPreference(boolean visible) { @@ -382,6 +384,17 @@ public class NetworkProviderSettings extends RestrictedSettingsFragment mWifiSwitchPreferenceController.displayPreference(getPreferenceScreen()); } + private void checkConnectivityRecovering() { + mInternetResetHelper = new InternetResetHelper(getContext(), getLifecycle(), + mNetworkMobileProviderController, + findPreference(WifiSwitchPreferenceController.KEY), + mConnectedWifiEntryPreferenceCategory, + mFirstWifiEntryPreferenceCategory, + mWifiEntryPreferenceCategory, + mResetInternetPreference); + mInternetResetHelper.checkRecovering(); + } + @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); @@ -1455,16 +1468,6 @@ public class NetworkProviderSettings extends RestrictedSettingsFragment EventLog.writeEvent(0x534e4554, "252995826", UserHandle.myUserId(), "User is a guest"); return; } - if (mInternetResetHelper == null) { - mInternetResetHelper = new InternetResetHelper(getContext(), getLifecycle()); - mInternetResetHelper.setResettingPreference(mResetInternetPreference); - mInternetResetHelper.setMobileNetworkController(mNetworkMobileProviderController); - mInternetResetHelper.setWifiTogglePreference( - findPreference(WifiSwitchPreferenceController.KEY)); - mInternetResetHelper.addWifiNetworkPreference(mConnectedWifiEntryPreferenceCategory); - mInternetResetHelper.addWifiNetworkPreference(mFirstWifiEntryPreferenceCategory); - mInternetResetHelper.addWifiNetworkPreference(mWifiEntryPreferenceCategory); - } mInternetResetHelper.restart(); } diff --git a/tests/unit/src/com/android/settings/network/InternetResetHelperTest.java b/tests/unit/src/com/android/settings/network/InternetResetHelperTest.java index e6df8a06451..3fe688273d8 100644 --- a/tests/unit/src/com/android/settings/network/InternetResetHelperTest.java +++ b/tests/unit/src/com/android/settings/network/InternetResetHelperTest.java @@ -16,6 +16,8 @@ package com.android.settings.network; +import static com.android.settings.network.InternetResetHelper.RESTART_TIMEOUT_MS; + import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; @@ -29,8 +31,6 @@ import android.content.BroadcastReceiver; import android.content.Context; import android.content.IntentFilter; import android.net.wifi.WifiManager; -import android.os.Handler; -import android.os.HandlerThread; import android.os.Looper; import androidx.lifecycle.Lifecycle; @@ -39,7 +39,6 @@ import androidx.preference.PreferenceCategory; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; -import com.android.settingslib.connectivity.ConnectivitySubsystemsRecoveryManager; import com.android.settingslib.utils.HandlerInjector; import org.junit.Before; @@ -47,6 +46,7 @@ import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; +import org.mockito.Spy; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; @@ -55,66 +55,46 @@ public class InternetResetHelperTest { @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule(); + @Spy + private final Context mContext = ApplicationProvider.getApplicationContext(); @Mock private WifiManager mWifiManager; @Mock - public HandlerThread mWorkerThread; + InternetResetHelper.RecoveryWorker mRecoveryWorker; @Mock - public ConnectivitySubsystemsRecoveryManager mConnectivitySubsystemsRecoveryManager; + HandlerInjector mHandlerInjector; @Mock public NetworkMobileProviderController mMobileNetworkController; - private Context mContext; private InternetResetHelper mInternetResetHelper; private Preference mResettingPreference; private Preference mWifiTogglePreferences; private PreferenceCategory mConnectedWifiEntryPreferences; + private PreferenceCategory mFirstWifiEntryPreference; private PreferenceCategory mWifiEntryPreferences; - private FakeHandlerInjector mFakeHandlerInjector; - - private static class FakeHandlerInjector extends HandlerInjector { - - private Runnable mRunnable; - - FakeHandlerInjector(Handler handler) { - super(handler); - } - - @Override - public void postDelayed(Runnable runnable, long delayMillis) { - mRunnable = runnable; - } - - public Runnable getRunnable() { - return mRunnable; - } - } - @Before public void setUp() { - mContext = spy(ApplicationProvider.getApplicationContext()); when(mContext.getSystemService(WifiManager.class)).thenReturn(mWifiManager); + when(mRecoveryWorker.isRecovering()).thenReturn(false); if (Looper.myLooper() == null) { Looper.prepare(); } - mResettingPreference = new Preference(mContext); + mResettingPreference = spy(new Preference(mContext)); mWifiTogglePreferences = new Preference(mContext); mConnectedWifiEntryPreferences = spy(new PreferenceCategory(mContext)); + mFirstWifiEntryPreference = spy(new PreferenceCategory(mContext)); mWifiEntryPreferences = spy(new PreferenceCategory(mContext)); - final Lifecycle lifecycle = mock(Lifecycle.class); - mInternetResetHelper = new InternetResetHelper(mContext, lifecycle); - mInternetResetHelper.mWorkerThread = mWorkerThread; - mFakeHandlerInjector = new FakeHandlerInjector(mContext.getMainThreadHandler()); - mInternetResetHelper.mHandlerInjector = mFakeHandlerInjector; - mInternetResetHelper.mConnectivitySubsystemsRecoveryManager = - mConnectivitySubsystemsRecoveryManager; - mInternetResetHelper.setResettingPreference(mResettingPreference); - mInternetResetHelper.setMobileNetworkController(mMobileNetworkController); - mInternetResetHelper.setWifiTogglePreference(mWifiTogglePreferences); - mInternetResetHelper.addWifiNetworkPreference(mConnectedWifiEntryPreferences); - mInternetResetHelper.addWifiNetworkPreference(mWifiEntryPreferences); + mInternetResetHelper = new InternetResetHelper(mContext, mock(Lifecycle.class), + mMobileNetworkController, + mWifiTogglePreferences, + mConnectedWifiEntryPreferences, + mFirstWifiEntryPreference, + mWifiEntryPreferences, + mResettingPreference); + mInternetResetHelper.mHandlerInjector = mHandlerInjector; + mInternetResetHelper.mRecoveryWorker = mRecoveryWorker; } @Test @@ -135,30 +115,10 @@ public class InternetResetHelperTest { } @Test - public void onDestroy_quitWorkerThread() { + public void onDestroy_removeCallbacks() { mInternetResetHelper.onDestroy(); - verify(mWorkerThread).quit(); - } - - @Test - public void onSubsystemRestartOperationEnd_recoveryIsNotReady_postResumeRunnable() { - mInternetResetHelper.mIsRecoveryReady = false; - - mInternetResetHelper.onSubsystemRestartOperationEnd(); - - assertThat(mInternetResetHelper.mIsRecoveryReady).isTrue(); - assertThat(mFakeHandlerInjector.getRunnable()) - .isEqualTo(mInternetResetHelper.mResumeRunnable); - } - - @Test - public void onSubsystemRestartOperationEnd_recoveryIsReady_doNothing() { - mInternetResetHelper.mIsRecoveryReady = true; - - mInternetResetHelper.onSubsystemRestartOperationEnd(); - - assertThat(mFakeHandlerInjector.getRunnable()).isNull(); + verify(mHandlerInjector).removeCallbacks(any()); } @Test @@ -169,19 +129,16 @@ public class InternetResetHelperTest { mInternetResetHelper.updateWifiStateChange(); assertThat(mInternetResetHelper.mIsWifiReady).isFalse(); - assertThat(mFakeHandlerInjector.getRunnable()).isNull(); } @Test - public void updateWifiStateChange_wifiIsNotReadyAndWifiEnabled_postResumeRunnable() { + public void updateWifiStateChange_wifiIsNotReadyAndWifiEnabled_updateWifiIsReady() { mInternetResetHelper.mIsWifiReady = false; when(mWifiManager.isWifiEnabled()).thenReturn(true); mInternetResetHelper.updateWifiStateChange(); assertThat(mInternetResetHelper.mIsWifiReady).isTrue(); - assertThat(mFakeHandlerInjector.getRunnable()) - .isEqualTo(mInternetResetHelper.mResumeRunnable); } @Test @@ -191,7 +148,6 @@ public class InternetResetHelperTest { mInternetResetHelper.updateWifiStateChange(); assertThat(mInternetResetHelper.mIsWifiReady).isTrue(); - assertThat(mFakeHandlerInjector.getRunnable()).isNull(); } @Test @@ -203,16 +159,15 @@ public class InternetResetHelperTest { // Hide subsystem preferences verify(mMobileNetworkController).hidePreference(true /* hide */, true /* immediately*/); assertThat(mWifiTogglePreferences.isVisible()).isFalse(); - verify(mConnectedWifiEntryPreferences).removeAll(); assertThat(mConnectedWifiEntryPreferences.isVisible()).isFalse(); - verify(mWifiEntryPreferences).removeAll(); + assertThat(mFirstWifiEntryPreference.isVisible()).isFalse(); assertThat(mWifiEntryPreferences.isVisible()).isFalse(); } @Test public void resumePreferences_onlyRecoveryReady_shouldShowSubSysHideResetting() { mInternetResetHelper.suspendPreferences(); - mInternetResetHelper.mIsRecoveryReady = true; + when(mRecoveryWorker.isRecovering()).thenReturn(false); mInternetResetHelper.mIsWifiReady = false; mInternetResetHelper.resumePreferences(); @@ -224,13 +179,14 @@ public class InternetResetHelperTest { // Hide Wi-Fi preferences assertThat(mWifiTogglePreferences.isVisible()).isFalse(); assertThat(mConnectedWifiEntryPreferences.isVisible()).isFalse(); + assertThat(mFirstWifiEntryPreference.isVisible()).isFalse(); assertThat(mWifiEntryPreferences.isVisible()).isFalse(); } @Test public void resumePreferences_onlyWifiReady_shouldShowSubSysHideResetting() { mInternetResetHelper.suspendPreferences(); - mInternetResetHelper.mIsRecoveryReady = false; + when(mRecoveryWorker.isRecovering()).thenReturn(true); mInternetResetHelper.mIsWifiReady = true; mInternetResetHelper.resumePreferences(); @@ -240,6 +196,7 @@ public class InternetResetHelperTest { // Show Wi-Fi preferences assertThat(mWifiTogglePreferences.isVisible()).isTrue(); assertThat(mConnectedWifiEntryPreferences.isVisible()).isTrue(); + assertThat(mFirstWifiEntryPreference.isVisible()).isTrue(); assertThat(mWifiEntryPreferences.isVisible()).isTrue(); // Hide Mobile Network controller verify(mMobileNetworkController, never()) @@ -249,14 +206,16 @@ public class InternetResetHelperTest { @Test public void resumePreferences_allReady_shouldShowSubSysHideResetting() { mInternetResetHelper.suspendPreferences(); - mInternetResetHelper.mIsRecoveryReady = true; + when(mRecoveryWorker.isRecovering()).thenReturn(false); mInternetResetHelper.mIsWifiReady = true; + mInternetResetHelper.resumePreferences(); // Show subsystem preferences verify(mMobileNetworkController).hidePreference(false, true); assertThat(mWifiTogglePreferences.isVisible()).isTrue(); assertThat(mConnectedWifiEntryPreferences.isVisible()).isTrue(); + assertThat(mFirstWifiEntryPreference.isVisible()).isTrue(); assertThat(mWifiEntryPreferences.isVisible()).isTrue(); // Hide resetting preference assertThat(mResettingPreference.isVisible()).isFalse(); @@ -264,22 +223,39 @@ public class InternetResetHelperTest { @Test public void restart_recoveryNotAvailable_shouldDoTriggerSubsystemRestart() { - when(mConnectivitySubsystemsRecoveryManager.isRecoveryAvailable()).thenReturn(false); + when(mRecoveryWorker.isRecoveryAvailable()).thenReturn(false); mInternetResetHelper.restart(); - verify(mConnectivitySubsystemsRecoveryManager, never()) - .triggerSubsystemRestart(any(), any()); + verify(mRecoveryWorker, never()).triggerRestart(); } @Test public void restart_recoveryAvailable_triggerSubsystemRestart() { - when(mConnectivitySubsystemsRecoveryManager.isRecoveryAvailable()).thenReturn(true); + when(mRecoveryWorker.isRecoveryAvailable()).thenReturn(true); mInternetResetHelper.restart(); - assertThat(mFakeHandlerInjector.getRunnable()) - .isEqualTo(mInternetResetHelper.mTimeoutRunnable); - verify(mConnectivitySubsystemsRecoveryManager).triggerSubsystemRestart(any(), any()); + verify(mHandlerInjector) + .postDelayed(mInternetResetHelper.mTimeoutRunnable, RESTART_TIMEOUT_MS); + verify(mRecoveryWorker).triggerRestart(); + } + + @Test + public void checkRecovering_isRecovering_showResetting() { + when(mRecoveryWorker.isRecovering()).thenReturn(true); + + mInternetResetHelper.checkRecovering(); + + verify(mResettingPreference).setVisible(true); + } + + @Test + public void checkRecovering_isNotRecovering_doNotShowResetting() { + when(mRecoveryWorker.isRecovering()).thenReturn(false); + + mInternetResetHelper.checkRecovering(); + + verify(mResettingPreference, never()).setVisible(true); } } From b39fb9d21ca25d219953a06fc3791892f8168d26 Mon Sep 17 00:00:00 2001 From: Weng Su Date: Mon, 21 Nov 2022 22:23:21 +0800 Subject: [PATCH 03/16] Align same wording style with Settings main switch - Update the main swtich title from "Adaptive connectivity" to "Use adaptive connectivity" Bug: 216730079 Test: manual testing to confirm wording changes Change-Id: I20004d8ffc6c9484e8aa68b36cc2a9c11ce764b6 --- res/values/strings.xml | 2 ++ res/xml/adaptive_connectivity_settings.xml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/res/values/strings.xml b/res/values/strings.xml index 74b7dab169f..c0d075aca7a 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -5141,6 +5141,8 @@ Adaptive connectivity Extends battery life and improves device performance by automatically managing your network connections + + Use adaptive connectivity Credential storage diff --git a/res/xml/adaptive_connectivity_settings.xml b/res/xml/adaptive_connectivity_settings.xml index d5941ad0507..63060065f83 100644 --- a/res/xml/adaptive_connectivity_settings.xml +++ b/res/xml/adaptive_connectivity_settings.xml @@ -30,7 +30,7 @@ From 92333907f07c8ac8f0bad763fbc6bc81ac9648c4 Mon Sep 17 00:00:00 2001 From: Zoey Chen Date: Mon, 7 Nov 2022 14:06:27 +0000 Subject: [PATCH 04/16] [Settings] Apply the SettingsDataService to the SIM page, MobileDataPreferenceController Bug: 257950125 Test: atest MobileDataPreferenceControllerTest Change-Id: Ia64a8baf931e9aa7f54cad2b2f5bb264420be9b0 --- .../network/MobileNetworkRepository.java | 16 +- ...rkProviderDownloadedSimListController.java | 6 +- .../MobileDataPreferenceController.java | 156 ++++++++++++++---- .../telephony/MobileNetworkSettings.java | 19 ++- tests/componenttests/Android.bp | 1 + ...DataPreferenceControllerComponentTest.java | 20 ++- .../MobileDataPreferenceControllerTest.java | 100 ++++++++--- 7 files changed, 249 insertions(+), 69 deletions(-) diff --git a/src/com/android/settings/network/MobileNetworkRepository.java b/src/com/android/settings/network/MobileNetworkRepository.java index f6881380ea8..5de4c726f45 100644 --- a/src/com/android/settings/network/MobileNetworkRepository.java +++ b/src/com/android/settings/network/MobileNetworkRepository.java @@ -88,6 +88,7 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions private Uri mAirplaneModeSettingUri; private MetricsFeatureProvider mMetricsFeatureProvider; private IntentFilter mFilter = new IntentFilter(); + private MobileDataContentObserver mDataContentObserver; private int mPhysicalSlotIndex = SubscriptionManager.INVALID_SIM_SLOT_INDEX; private int mLogicalSlotIndex = SubscriptionManager.INVALID_SIM_SLOT_INDEX; @@ -125,6 +126,13 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions mMobileNetworkInfoDao = mMobileNetworkDatabase.mMobileNetworkInfoDao(); mAirplaneModeObserver = new AirplaneModeObserver(new Handler(Looper.getMainLooper())); mAirplaneModeSettingUri = Settings.Global.getUriFor(Settings.Global.AIRPLANE_MODE_ON); + mDataContentObserver = new MobileDataContentObserver( + new Handler(Looper.getMainLooper())); + mDataContentObserver.setOnMobileDataChangedListener(() -> { + mExecutor.execute(() -> { + insertMobileNetworkInfo(context); + }); + }); mFilter.addAction(TelephonyManager.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED); mFilter.addAction(SubscriptionManager.ACTION_DEFAULT_SUBSCRIPTION_CHANGED); mFilter.addAction(ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED); @@ -163,6 +171,9 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions public void addRegister(LifecycleOwner lifecycleOwner) { mSubscriptionManager.addOnSubscriptionsChangedListener(mContext.getMainExecutor(), this); mAirplaneModeObserver.register(mContext); + if (mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) { + mDataContentObserver.register(mContext, mSubId); + } mContext.registerReceiver(mDataSubscriptionChangedReceiver, mFilter); observeAllSubInfo(lifecycleOwner); observeAllUiccInfo(lifecycleOwner); @@ -170,6 +181,9 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions } public void removeRegister() { + if (mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) { + mDataContentObserver.unRegister(mContext); + } mAirplaneModeObserver.unRegister(mContext); if (mDataSubscriptionChangedReceiver != null) { mContext.unregisterReceiver(mDataSubscriptionChangedReceiver); @@ -404,7 +418,7 @@ public class MobileNetworkRepository extends SubscriptionManager.OnSubscriptions return new MobileNetworkInfoEntity(String.valueOf(mSubId), MobileNetworkUtils.isContactDiscoveryEnabled(context, mSubId), MobileNetworkUtils.isContactDiscoveryVisible(context, mSubId), - MobileNetworkUtils.isMobileDataEnabled(context), + mTelephonyManager.isDataEnabled(), MobileNetworkUtils.isCdmaOptions(context, mSubId), MobileNetworkUtils.isGsmOptions(context, mSubId), MobileNetworkUtils.isWorldMode(context, mSubId), diff --git a/src/com/android/settings/network/NetworkProviderDownloadedSimListController.java b/src/com/android/settings/network/NetworkProviderDownloadedSimListController.java index abde7c08074..421a8541d09 100644 --- a/src/com/android/settings/network/NetworkProviderDownloadedSimListController.java +++ b/src/com/android/settings/network/NetworkProviderDownloadedSimListController.java @@ -41,6 +41,7 @@ import com.android.settings.network.telephony.MobileNetworkUtils; import com.android.settingslib.core.AbstractPreferenceController; import com.android.settingslib.core.lifecycle.Lifecycle; import com.android.settingslib.core.lifecycle.LifecycleObserver; +import com.android.settingslib.mobile.dataservice.DataServiceUtils; import com.android.settingslib.mobile.dataservice.MobileNetworkInfoEntity; import com.android.settingslib.mobile.dataservice.SubscriptionInfoEntity; import com.android.settingslib.mobile.dataservice.UiccInfoEntity; @@ -181,10 +182,7 @@ public class NetworkProviderDownloadedSimListController extends @Override public void onAvailableSubInfoChanged(List subInfoEntityList) { - if ((mSubInfoEntityList != null && - (subInfoEntityList.isEmpty() || !subInfoEntityList.equals(mSubInfoEntityList))) - || (!subInfoEntityList.isEmpty() && mSubInfoEntityList == null)) { - Log.d(TAG, "subInfo list from framework is changed, update the subInfo entity list."); + if (DataServiceUtils.shouldUpdateEntityList(mSubInfoEntityList, subInfoEntityList)) { mSubInfoEntityList = subInfoEntityList; mPreferenceCategory.setVisible(isAvailable()); update(); diff --git a/src/com/android/settings/network/telephony/MobileDataPreferenceController.java b/src/com/android/settings/network/telephony/MobileDataPreferenceController.java index 69951bf43a0..8543770dc0d 100644 --- a/src/com/android/settings/network/telephony/MobileDataPreferenceController.java +++ b/src/com/android/settings/network/telephony/MobileDataPreferenceController.java @@ -16,14 +16,19 @@ package com.android.settings.network.telephony; +import static androidx.lifecycle.Lifecycle.Event.ON_START; +import static androidx.lifecycle.Lifecycle.Event.ON_STOP; + import android.content.Context; import android.os.Handler; import android.os.Looper; -import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.text.TextUtils; +import androidx.lifecycle.LifecycleObserver; +import androidx.lifecycle.LifecycleOwner; +import androidx.lifecycle.OnLifecycleEvent; import androidx.annotation.VisibleForTesting; import androidx.fragment.app.FragmentManager; import androidx.preference.Preference; @@ -32,16 +37,22 @@ import androidx.preference.SwitchPreference; import com.android.settings.R; import com.android.settings.network.MobileDataContentObserver; +import com.android.settings.network.MobileNetworkRepository; import com.android.settings.wifi.WifiPickerTrackerHelper; -import com.android.settingslib.core.lifecycle.LifecycleObserver; -import com.android.settingslib.core.lifecycle.events.OnStart; -import com.android.settingslib.core.lifecycle.events.OnStop; +import com.android.settingslib.core.lifecycle.Lifecycle; +import com.android.settingslib.mobile.dataservice.DataServiceUtils; +import com.android.settingslib.mobile.dataservice.MobileNetworkInfoEntity; +import com.android.settingslib.mobile.dataservice.SubscriptionInfoEntity; +import com.android.settingslib.mobile.dataservice.UiccInfoEntity; + +import java.util.ArrayList; +import java.util.List; /** * Preference controller for "Mobile data" */ public class MobileDataPreferenceController extends TelephonyTogglePreferenceController - implements LifecycleObserver, OnStart, OnStop { + implements LifecycleObserver, MobileNetworkRepository.MobileNetworkCallback { private static final String DIALOG_TAG = "MobileDataDialog"; @@ -56,12 +67,26 @@ public class MobileDataPreferenceController extends TelephonyTogglePreferenceCon boolean mNeedDialog; private WifiPickerTrackerHelper mWifiPickerTrackerHelper; + protected MobileNetworkRepository mMobileNetworkRepository; + protected LifecycleOwner mLifecycleOwner; + private List mSubscriptionInfoEntityList = new ArrayList<>(); + private List mMobileNetworkInfoEntityList = new ArrayList<>(); + private int mDefaultSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; + SubscriptionInfoEntity mSubscriptionInfoEntity; + MobileNetworkInfoEntity mMobileNetworkInfoEntity; - public MobileDataPreferenceController(Context context, String key) { + public MobileDataPreferenceController(Context context, String key, Lifecycle lifecycle, + LifecycleOwner lifecycleOwner, int subId) { super(context, key); + mSubId = subId; mSubscriptionManager = context.getSystemService(SubscriptionManager.class); mDataContentObserver = new MobileDataContentObserver(new Handler(Looper.getMainLooper())); mDataContentObserver.setOnMobileDataChangedListener(() -> updateState(mPreference)); + mMobileNetworkRepository = MobileNetworkRepository.createBySubId(context, this, mSubId); + mLifecycleOwner = lifecycleOwner; + if (lifecycle != null) { + lifecycle.addObserver(this); + } } @Override @@ -77,18 +102,14 @@ public class MobileDataPreferenceController extends TelephonyTogglePreferenceCon mPreference = screen.findPreference(getPreferenceKey()); } - @Override + @OnLifecycleEvent(ON_START) public void onStart() { - if (mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) { - mDataContentObserver.register(mContext, mSubId); - } + mMobileNetworkRepository.addRegister(mLifecycleOwner); } - @Override + @OnLifecycleEvent(ON_STOP) public void onStop() { - if (mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) { - mDataContentObserver.unRegister(mContext); - } + mMobileNetworkRepository.removeRegister(); } @Override @@ -122,39 +143,47 @@ public class MobileDataPreferenceController extends TelephonyTogglePreferenceCon @Override public boolean isChecked() { - mTelephonyManager = getTelephonyManager(); - return mTelephonyManager.isDataEnabled(); + return mMobileNetworkInfoEntity == null ? false + : mMobileNetworkInfoEntity.isMobileDataEnabled; } @Override public void updateState(Preference preference) { super.updateState(preference); - if (isOpportunistic()) { - preference.setEnabled(false); - preference.setSummary(R.string.mobile_data_settings_summary_auto_switch); - } else { - preference.setEnabled(true); - preference.setSummary(R.string.mobile_data_settings_summary); + mPreference = (SwitchPreference) preference; + update(); + } + + private void update() { + + if (mSubscriptionInfoEntity == null || mPreference == null) { + return; } - if (mSubId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { - preference.setSelectable(false); - preference.setSummary(R.string.mobile_data_settings_summary_unavailable); + mPreference.setChecked(isChecked()); + if (mSubscriptionInfoEntity.isOpportunistic) { + mPreference.setEnabled(false); + mPreference.setSummary(R.string.mobile_data_settings_summary_auto_switch); } else { - preference.setSelectable(true); + mPreference.setEnabled(true); + mPreference.setSummary(R.string.mobile_data_settings_summary); + } + if (!mSubscriptionInfoEntity.isValidSubscription) { + mPreference.setSelectable(false); + mPreference.setSummary(R.string.mobile_data_settings_summary_unavailable); + } else { + mPreference.setSelectable(true); } } - private boolean isOpportunistic() { - SubscriptionInfo info = mSubscriptionManager.getActiveSubscriptionInfo(mSubId); - return info != null && info.isOpportunistic(); - } - - public void init(FragmentManager fragmentManager, int subId) { + public void init(FragmentManager fragmentManager, int subId, + SubscriptionInfoEntity subInfoEntity, MobileNetworkInfoEntity networkInfoEntity) { mFragmentManager = fragmentManager; mSubId = subId; mTelephonyManager = null; mTelephonyManager = getTelephonyManager(); + mSubscriptionInfoEntity = subInfoEntity; + mMobileNetworkInfoEntity = networkInfoEntity; } private TelephonyManager getTelephonyManager() { @@ -179,9 +208,8 @@ public class MobileDataPreferenceController extends TelephonyTogglePreferenceCon final boolean enableData = !isChecked(); mTelephonyManager = getTelephonyManager(); final boolean isMultiSim = (mTelephonyManager.getActiveModemCount() > 1); - final int defaultSubId = mSubscriptionManager.getDefaultDataSubscriptionId(); - final boolean needToDisableOthers = mSubscriptionManager - .isActiveSubscriptionId(defaultSubId) && defaultSubId != mSubId; + final boolean needToDisableOthers = mDefaultSubId != mSubId; + if (enableData && isMultiSim && needToDisableOthers) { mDialogType = MobileDataDialogFragment.TYPE_MULTI_SIM_DIALOG; return true; @@ -194,4 +222,62 @@ public class MobileDataPreferenceController extends TelephonyTogglePreferenceCon mSubId); dialogFragment.show(mFragmentManager, DIALOG_TAG); } + + @VisibleForTesting + public void setSubscriptionInfoEntity(SubscriptionInfoEntity subscriptionInfoEntity) { + mSubscriptionInfoEntity = subscriptionInfoEntity; + } + + @VisibleForTesting + public void setMobileNetworkInfoEntity(MobileNetworkInfoEntity mobileNetworkInfoEntity) { + mMobileNetworkInfoEntity = mobileNetworkInfoEntity; + } + + @Override + public void onAirplaneModeChanged(boolean airplaneModeEnabled) { + } + + @Override + public void onAvailableSubInfoChanged(List subInfoEntityList) { + } + + @Override + public void onActiveSubInfoChanged(List subInfoEntityList) { + if (DataServiceUtils.shouldUpdateEntityList(mSubscriptionInfoEntityList, + subInfoEntityList)) { + mSubscriptionInfoEntityList = subInfoEntityList; + mSubscriptionInfoEntityList.forEach(entity -> { + if (Integer.parseInt(entity.subId) == mSubId) { + mSubscriptionInfoEntity = entity; + } + }); + if (mSubscriptionInfoEntity != null + && mSubscriptionInfoEntity.isDefaultDataSubscription) { + mDefaultSubId = Integer.parseInt(mSubscriptionInfoEntity.subId); + } + update(); + refreshSummary(mPreference); + } + } + + @Override + public void onAllUiccInfoChanged(List uiccInfoEntityList) { + } + + @Override + public void onAllMobileNetworkInfoChanged( + List mobileNetworkInfoEntityList) { + if (DataServiceUtils.shouldUpdateEntityList(mMobileNetworkInfoEntityList, + mobileNetworkInfoEntityList)) { + mMobileNetworkInfoEntityList = mobileNetworkInfoEntityList; + mMobileNetworkInfoEntityList.forEach(entity -> { + if (Integer.parseInt(entity.subId) == mSubId) { + mMobileNetworkInfoEntity = entity; + update(); + refreshSummary(mPreference); + return; + } + }); + } + } } diff --git a/src/com/android/settings/network/telephony/MobileNetworkSettings.java b/src/com/android/settings/network/telephony/MobileNetworkSettings.java index ae83c43c5bc..7d65744576e 100644 --- a/src/com/android/settings/network/telephony/MobileNetworkSettings.java +++ b/src/com/android/settings/network/telephony/MobileNetworkSettings.java @@ -79,6 +79,7 @@ public class MobileNetworkSettings extends AbstractMobileNetworkSettings impleme private static final String KEY_ROAMING_PREF = "button_roaming_key"; private static final String KEY_CALLS_PREF = "calls_preference"; private static final String KEY_SMS_PREF = "sms_preference"; + private static final String KEY_MOBILE_DATA_PREF = "mobile_data_enable"; //String keys for preference lookup private static final String BUTTON_CDMA_SYSTEM_SELECT_KEY = "cdma_system_select_key"; @@ -175,7 +176,9 @@ public class MobileNetworkSettings extends AbstractMobileNetworkSettings impleme new CallsDefaultSubscriptionController(context, KEY_CALLS_PREF, getSettingsLifecycle(), this), new SmsDefaultSubscriptionController(context, KEY_SMS_PREF, getSettingsLifecycle(), - this)); + this), + new MobileDataPreferenceController(context, KEY_MOBILE_DATA_PREF, + getSettingsLifecycle(), this, mSubId)); } @Override @@ -231,10 +234,16 @@ public class MobileNetworkSettings extends AbstractMobileNetworkSettings impleme REQUEST_CODE_DELETE_SUBSCRIPTION); use(DisableSimFooterPreferenceController.class).init(mSubId); use(NrDisabledInDsdsFooterPreferenceController.class).init(mSubId); - use(MobileDataPreferenceController.class).init(getFragmentManager(), mSubId); - use(MobileDataPreferenceController.class).setWifiPickerTrackerHelper( - new WifiPickerTrackerHelper(getSettingsLifecycle(), context, - null /* WifiPickerTrackerCallback */)); + + final MobileDataPreferenceController mobileDataPreferenceController = + use(MobileDataPreferenceController.class); + if (mobileDataPreferenceController != null) { + mobileDataPreferenceController.init(getFragmentManager(), mSubId, + mSubscriptionInfoEntity, mMobileNetworkInfoEntity); + mobileDataPreferenceController.setWifiPickerTrackerHelper( + new WifiPickerTrackerHelper(getSettingsLifecycle(), context, + null /* WifiPickerTrackerCallback */)); + } final RoamingPreferenceController roamingPreferenceController = use(RoamingPreferenceController.class); diff --git a/tests/componenttests/Android.bp b/tests/componenttests/Android.bp index 77ee1648d01..5c03aa97fb3 100644 --- a/tests/componenttests/Android.bp +++ b/tests/componenttests/Android.bp @@ -26,6 +26,7 @@ android_test { "androidx.test.runner", "androidx.test.rules", "androidx.test.ext.junit", + "mockito-target", ], test_suites: ["device-tests"], diff --git a/tests/componenttests/src/com/android/settings/network/telephony/MobileDataPreferenceControllerComponentTest.java b/tests/componenttests/src/com/android/settings/network/telephony/MobileDataPreferenceControllerComponentTest.java index 78a2c92f329..df3dd2effd2 100644 --- a/tests/componenttests/src/com/android/settings/network/telephony/MobileDataPreferenceControllerComponentTest.java +++ b/tests/componenttests/src/com/android/settings/network/telephony/MobileDataPreferenceControllerComponentTest.java @@ -20,6 +20,8 @@ import static com.android.settings.testutils.CommonUtils.set_wifi_enabled; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Mockito.mock; + import android.app.Instrumentation; import android.content.Context; import android.content.Intent; @@ -31,6 +33,7 @@ import android.util.Log; import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentManager; +import androidx.lifecycle.LifecycleOwner; import androidx.test.core.app.ActivityScenario; import androidx.test.ext.junit.rules.ActivityScenarioRule; import androidx.test.ext.junit.runners.AndroidJUnit4; @@ -40,6 +43,9 @@ import androidx.test.platform.app.InstrumentationRegistry; import com.android.settings.Settings; import com.android.settings.testutils.CommonUtils; import com.android.settings.testutils.UiUtils; +import com.android.settingslib.core.lifecycle.Lifecycle; +import com.android.settingslib.mobile.dataservice.MobileNetworkInfoEntity; +import com.android.settingslib.mobile.dataservice.SubscriptionInfoEntity; import org.junit.After; import org.junit.Assume; @@ -47,6 +53,8 @@ import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; import java.io.IOException; import java.net.URL; @@ -54,6 +62,12 @@ import java.net.URL; @RunWith(AndroidJUnit4.class) @SmallTest public class MobileDataPreferenceControllerComponentTest { + + @Mock + private Lifecycle mLifecycle; + @Mock + private LifecycleOwner mLifecycleOwner; + public static final int TIMEOUT = 2000; private static int sSubscriptionId = 2; public final String TAG = this.getClass().getName(); @@ -116,9 +130,11 @@ public class MobileDataPreferenceControllerComponentTest { try { URL url = new URL("https://www.google.net"); MobileDataPreferenceController controller = new MobileDataPreferenceController( - mInstrumentation.getTargetContext(), "mobile_data"); + mInstrumentation.getTargetContext(), "mobile_data", mLifecycle, + mLifecycleOwner, sSubscriptionId); FragmentManager manager = ((FragmentActivity) activity).getSupportFragmentManager(); - controller.init(manager, sSubscriptionId); + controller.init(manager, sSubscriptionId, mock(SubscriptionInfoEntity.class), mock( + MobileNetworkInfoEntity.class)); // Make sure mobile network can connect at first. assertThat(UiUtils.waitUntilCondition(1000, diff --git a/tests/unit/src/com/android/settings/network/telephony/MobileDataPreferenceControllerTest.java b/tests/unit/src/com/android/settings/network/telephony/MobileDataPreferenceControllerTest.java index 45f3693a298..16e3963b738 100644 --- a/tests/unit/src/com/android/settings/network/telephony/MobileDataPreferenceControllerTest.java +++ b/tests/unit/src/com/android/settings/network/telephony/MobileDataPreferenceControllerTest.java @@ -28,18 +28,24 @@ import static org.mockito.Mockito.when; import android.app.Instrumentation; import android.content.Context; +import android.os.Looper; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentTransaction; +import androidx.lifecycle.LifecycleOwner; +import androidx.lifecycle.LifecycleRegistry; import androidx.preference.SwitchPreference; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; import androidx.test.platform.app.InstrumentationRegistry; import com.android.settings.testutils.ResourcesUtils; +import com.android.settingslib.core.lifecycle.Lifecycle; +import com.android.settingslib.mobile.dataservice.MobileNetworkInfoEntity; +import com.android.settingslib.mobile.dataservice.SubscriptionInfoEntity; import org.junit.Before; import org.junit.Test; @@ -49,6 +55,10 @@ import org.mockito.MockitoAnnotations; @RunWith(AndroidJUnit4.class) public class MobileDataPreferenceControllerTest { + private static final String SUB_ID_1 = "1"; + private static final String SUB_ID_2 = "2"; + private static final String DISPLAY_NAME_1 = "Sub 1"; + private static final String DISPLAY_NAME_2 = "Sub 2"; private static final int SUB_ID = 2; private static final int SUB_ID_OTHER = 3; @@ -64,7 +74,15 @@ public class MobileDataPreferenceControllerTest { private SubscriptionInfo mSubscriptionInfo; @Mock private FragmentTransaction mFragmentTransaction; - + @Mock + private Lifecycle mLifecycle; + @Mock + private LifecycleOwner mLifecycleOwner; + private SubscriptionInfoEntity mSubInfo1; + private SubscriptionInfoEntity mSubInfo2; + private MobileNetworkInfoEntity mNetworkInfo1; + private MobileNetworkInfoEntity mNetworkInfo2; + private LifecycleRegistry mLifecycleRegistry; private MobileDataPreferenceController mController; private SwitchPreference mPreference; private Context mContext; @@ -73,6 +91,10 @@ public class MobileDataPreferenceControllerTest { public void setUp() { MockitoAnnotations.initMocks(this); + if (Looper.myLooper() == null) { + Looper.prepare(); + } + mContext = spy(ApplicationProvider.getApplicationContext()); doReturn(mTelephonyManager).when(mContext).getSystemService(Context.TELEPHONY_SERVICE); @@ -83,22 +105,45 @@ public class MobileDataPreferenceControllerTest { doReturn(mFragmentTransaction).when(mFragmentManager).beginTransaction(); mPreference = new SwitchPreference(mContext); - mController = new MobileDataPreferenceController(mContext, "mobile_data"); - mController.init(mFragmentManager, SUB_ID); + mController = new MobileDataPreferenceController(mContext, "mobile_data", mLifecycle, + mLifecycleOwner, SUB_ID); + mController.init(mFragmentManager, SUB_ID, mSubInfo1, mNetworkInfo1); mPreference.setKey(mController.getPreferenceKey()); + mLifecycleRegistry = new LifecycleRegistry(mLifecycleOwner); + when(mLifecycleOwner.getLifecycle()).thenReturn(mLifecycleRegistry); + } + + private SubscriptionInfoEntity setupSubscriptionInfoEntity(String subId, String displayName, + boolean isOpportunistic, boolean isValid, boolean isActive, boolean isAvailable, + boolean isDefaultData) { + int id = Integer.parseInt(subId); + return new SubscriptionInfoEntity(subId, id, id, + displayName, displayName, 0, "mcc", "mnc", "countryIso", false, id, + TelephonyManager.DEFAULT_PORT_INDEX, isOpportunistic, null, + SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM, displayName, false, + "1234567890", true, "default", false, isValid, true, isActive, isAvailable, false, + false, isDefaultData, false, false); + } + + private MobileNetworkInfoEntity setupMobileNetworkInfoEntity(String subId, + boolean isDatEnabled) { + return new MobileNetworkInfoEntity(subId, false, false, isDatEnabled, false, false, false, + false, false, false, false, false); } @Test public void getAvailabilityStatus_invalidSubscription_returnAvailableUnsearchable() { - mController.init(mFragmentManager, SubscriptionManager.INVALID_SUBSCRIPTION_ID); + mController.init(mFragmentManager, SubscriptionManager.INVALID_SUBSCRIPTION_ID, mSubInfo1, + mNetworkInfo1); assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE_UNSEARCHABLE); } @Test public void isDialogNeeded_disableSingleSim_returnFalse() { - doReturn(true).when(mTelephonyManager).isDataEnabled(); - doReturn(mSubscriptionInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(SUB_ID); + mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, DISPLAY_NAME_1, false, true, true, true, + true); + mNetworkInfo1 = setupMobileNetworkInfoEntity(String.valueOf(SUB_ID), true); doReturn(1).when(mTelephonyManager).getActiveModemCount(); assertThat(mController.isDialogNeeded()).isFalse(); @@ -106,12 +151,15 @@ public class MobileDataPreferenceControllerTest { @Test public void isDialogNeeded_enableNonDefaultSimInMultiSimMode_returnTrue() { - doReturn(false).when(mTelephonyManager).isDataEnabled(); - doReturn(mSubscriptionInfo).when(mSubscriptionManager) - .getActiveSubscriptionInfo(SUB_ID); + mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, DISPLAY_NAME_1, false, true, true, true, + false); + mNetworkInfo1 = setupMobileNetworkInfoEntity(String.valueOf(SUB_ID), false); + doReturn(1).when(mTelephonyManager).getActiveModemCount(); // Ideally, it would be better if we could set the default data subscription to // SUB_ID_OTHER, and set that as an active subscription id. - when(mSubscriptionManager.isActiveSubscriptionId(anyInt())).thenReturn(true); + mSubInfo2 = setupSubscriptionInfoEntity(SUB_ID_2, DISPLAY_NAME_2, false, true, true, true, + true); + mNetworkInfo1 = setupMobileNetworkInfoEntity(String.valueOf(SUB_ID), true); doReturn(2).when(mTelephonyManager).getActiveModemCount(); assertThat(mController.isDialogNeeded()).isTrue(); @@ -132,8 +180,11 @@ public class MobileDataPreferenceControllerTest { @Test public void onPreferenceChange_singleSim_On_shouldEnableData() { - doReturn(true).when(mTelephonyManager).isDataEnabled(); - doReturn(mSubscriptionInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(SUB_ID); + mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, DISPLAY_NAME_1, true, true, true, true, + true); + mNetworkInfo1 = setupMobileNetworkInfoEntity(String.valueOf(SUB_ID), true); + mController.setSubscriptionInfoEntity(mSubInfo1); + mController.setMobileNetworkInfoEntity(mNetworkInfo1); doReturn(1).when(mTelephonyManager).getActiveModemCount(); mController.onPreferenceChange(mPreference, true); @@ -143,8 +194,11 @@ public class MobileDataPreferenceControllerTest { @Test public void onPreferenceChange_multiSim_On_shouldEnableData() { - doReturn(true).when(mTelephonyManager).isDataEnabled(); - doReturn(mSubscriptionInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(SUB_ID); + mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, DISPLAY_NAME_1, true, true, true, true, + true); + mNetworkInfo1 = setupMobileNetworkInfoEntity(String.valueOf(SUB_ID), true); + mController.setSubscriptionInfoEntity(mSubInfo1); + mController.setMobileNetworkInfoEntity(mNetworkInfo1); doReturn(2).when(mTelephonyManager).getActiveModemCount(); mController.onPreferenceChange(mPreference, true); @@ -154,18 +208,20 @@ public class MobileDataPreferenceControllerTest { @Test public void isChecked_returnUserDataEnabled() { - mController.init(mFragmentManager, SUB_ID); + mNetworkInfo1 = setupMobileNetworkInfoEntity(String.valueOf(SUB_ID), false); + mController.init(mFragmentManager, SUB_ID, mSubInfo1, mNetworkInfo1); assertThat(mController.isChecked()).isFalse(); - doReturn(true).when(mTelephonyManager).isDataEnabled(); + mNetworkInfo1 = setupMobileNetworkInfoEntity(String.valueOf(SUB_ID), true); + mController.setMobileNetworkInfoEntity(mNetworkInfo1); assertThat(mController.isChecked()).isTrue(); } @Test public void updateState_opportunistic_disabled() { - doReturn(mSubscriptionInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(SUB_ID); - mController.init(mFragmentManager, SUB_ID); - doReturn(true).when(mSubscriptionInfo).isOpportunistic(); + mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, DISPLAY_NAME_1, true, true, true, true, + true); + mController.init(mFragmentManager, SUB_ID, mSubInfo1, mNetworkInfo1); mController.updateState(mPreference); assertThat(mPreference.isEnabled()).isFalse(); @@ -176,9 +232,9 @@ public class MobileDataPreferenceControllerTest { @Test public void updateState_notOpportunistic_enabled() { - doReturn(mSubscriptionInfo).when(mSubscriptionManager).getActiveSubscriptionInfo(SUB_ID); - mController.init(mFragmentManager, SUB_ID); - doReturn(false).when(mSubscriptionInfo).isOpportunistic(); + mSubInfo1 = setupSubscriptionInfoEntity(SUB_ID_1, DISPLAY_NAME_1, false, true, true, true, + true); + mController.init(mFragmentManager, SUB_ID, mSubInfo1, mNetworkInfo1); mController.updateState(mPreference); assertThat(mPreference.isEnabled()).isTrue(); From 517431039288b21440da77b59fd703fd8fd5dba6 Mon Sep 17 00:00:00 2001 From: Milton Wu Date: Tue, 22 Nov 2022 16:37:11 +0800 Subject: [PATCH 05/16] Fix FingerprintEnrollmentActivity rotaiton crash 1. When FragmentActivity rotated, FragmentManager will call default fragment constructor w/o parameters. Remove parameters of FingerprintEnrollIntroFragment constructor. And also remove BiometricsFragmentFactory because of useless now. 2. Remove some LiveData inside AutoCredentialViewModel because it causes jitter on activity transition. 3. Save and restore data inside AutoCredentialViewModel for handling activity recreation during rotation. 4. clear FingerprintEnrollIntroViewModel.mActionLiveData to prevent that activity gets previous action after recreate 5. Fix launching wrong activity during setupwizard Bug: 259626932 Test: atest AutoCredentialViewModelTest CredentialModelTest FingerprintEnrollIntroViewModelTest Change-Id: Ia26c86dc99ad91dbddef90538d9f5e5583585063 --- .../factory/BiometricsFragmentFactory.java | 57 ---- .../biometrics2/ui/model/CredentialModel.java | 28 +- .../view/FingerprintEnrollIntroFragment.java | 24 +- .../view/FingerprintEnrollmentActivity.java | 67 ++-- .../ui/viewmodel/AutoCredentialViewModel.java | 95 +++--- .../FingerprintEnrollIntroViewModel.java | 7 + .../ui/model/CredentialModelTest.java | 164 +++++++++ .../AutoCredentialViewModelTest.java | 311 ++++++++++++------ .../FingerprintEnrollIntroViewModelTest.java | 13 + 9 files changed, 520 insertions(+), 246 deletions(-) delete mode 100644 src/com/android/settings/biometrics2/factory/BiometricsFragmentFactory.java create mode 100644 tests/unit/src/com/android/settings/biometrics2/ui/model/CredentialModelTest.java diff --git a/src/com/android/settings/biometrics2/factory/BiometricsFragmentFactory.java b/src/com/android/settings/biometrics2/factory/BiometricsFragmentFactory.java deleted file mode 100644 index 9a0cab21d5a..00000000000 --- a/src/com/android/settings/biometrics2/factory/BiometricsFragmentFactory.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.settings.biometrics2.factory; - -import android.app.Application; -import android.app.admin.DevicePolicyManager; - -import androidx.annotation.NonNull; -import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentFactory; -import androidx.lifecycle.ViewModelProvider; - -import com.android.settings.biometrics2.ui.view.FingerprintEnrollIntroFragment; - -/** - * Fragment factory for biometrics - */ -public class BiometricsFragmentFactory extends FragmentFactory { - - private final Application mApplication; - private final ViewModelProvider mViewModelProvider; - - public BiometricsFragmentFactory(Application application, - ViewModelProvider viewModelProvider) { - mApplication = application; - mViewModelProvider = viewModelProvider; - } - - @NonNull - @Override - public Fragment instantiate(@NonNull ClassLoader classLoader, @NonNull String className) { - final Class clazz = loadFragmentClass(classLoader, className); - if (FingerprintEnrollIntroFragment.class.equals(clazz)) { - final DevicePolicyManager devicePolicyManager = - mApplication.getSystemService(DevicePolicyManager.class); - if (devicePolicyManager != null) { - return new FingerprintEnrollIntroFragment(mViewModelProvider, - devicePolicyManager.getResources()); - } - } - return super.instantiate(classLoader, className); - } -} diff --git a/src/com/android/settings/biometrics2/ui/model/CredentialModel.java b/src/com/android/settings/biometrics2/ui/model/CredentialModel.java index 06caf5e6945..b943608be20 100644 --- a/src/com/android/settings/biometrics2/ui/model/CredentialModel.java +++ b/src/com/android/settings/biometrics2/ui/model/CredentialModel.java @@ -22,6 +22,7 @@ import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_C import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE; import android.content.Intent; +import android.os.Bundle; import android.os.UserHandle; import androidx.annotation.NonNull; @@ -80,17 +81,30 @@ public final class CredentialModel { @Nullable private Long mClearGkPwHandleMillis = null; - public CredentialModel(@NonNull Intent intent, @NonNull Clock clock) { - mUserId = intent.getIntExtra(Intent.EXTRA_USER_ID, UserHandle.myUserId()); - mSensorId = intent.getIntExtra(EXTRA_KEY_SENSOR_ID, INVALID_SENSOR_ID); - mChallenge = intent.getLongExtra(EXTRA_KEY_CHALLENGE, INVALID_CHALLENGE); - mToken = intent.getByteArrayExtra(EXTRA_KEY_CHALLENGE_TOKEN); - mGkPwHandle = intent.getLongExtra(EXTRA_KEY_GK_PW_HANDLE, - INVALID_GK_PW_HANDLE); + public CredentialModel(@NonNull Bundle bundle, @NonNull Clock clock) { + mUserId = bundle.getInt(Intent.EXTRA_USER_ID, UserHandle.myUserId()); + mSensorId = bundle.getInt(EXTRA_KEY_SENSOR_ID, INVALID_SENSOR_ID); + mChallenge = bundle.getLong(EXTRA_KEY_CHALLENGE, INVALID_CHALLENGE); + mToken = bundle.getByteArray(EXTRA_KEY_CHALLENGE_TOKEN); + mGkPwHandle = bundle.getLong(EXTRA_KEY_GK_PW_HANDLE, INVALID_GK_PW_HANDLE); mClock = clock; mInitMillis = mClock.millis(); } + /** + * Get a bundle which can be used to recreate CredentialModel + */ + @NonNull + public Bundle getBundle() { + final Bundle bundle = new Bundle(); + bundle.putInt(Intent.EXTRA_USER_ID, mUserId); + bundle.putInt(EXTRA_KEY_SENSOR_ID, mSensorId); + bundle.putLong(EXTRA_KEY_CHALLENGE, mChallenge); + bundle.putByteArray(EXTRA_KEY_CHALLENGE_TOKEN, mToken); + bundle.putLong(EXTRA_KEY_GK_PW_HANDLE, mGkPwHandle); + return bundle; + } + /** * Get userId for this credential */ diff --git a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollIntroFragment.java b/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollIntroFragment.java index 2308f2ef9d1..14d859dbffc 100644 --- a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollIntroFragment.java +++ b/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollIntroFragment.java @@ -25,7 +25,7 @@ import static com.android.settings.biometrics2.ui.model.FingerprintEnrollIntroSt import static com.google.android.setupdesign.util.DynamicColorPalette.ColorType.ACCENT; import android.app.Activity; -import android.app.admin.DevicePolicyResourcesManager; +import android.app.admin.DevicePolicyManager; import android.content.Context; import android.graphics.PorterDuff; import android.graphics.PorterDuffColorFilter; @@ -63,9 +63,6 @@ public class FingerprintEnrollIntroFragment extends Fragment { private static final String TAG = "FingerprintEnrollIntroFragment"; - @NonNull private final ViewModelProvider mViewModelProvider; - @Nullable private final DevicePolicyResourcesManager mDevicePolicyMgrRes; - private FingerprintEnrollIntroViewModel mViewModel = null; private View mView = null; @@ -75,12 +72,8 @@ public class FingerprintEnrollIntroFragment extends Fragment { private TextView mFooterMessage6 = null; @Nullable private PorterDuffColorFilter mIconColorFilter; - public FingerprintEnrollIntroFragment( - @NonNull ViewModelProvider viewModelProvider, - @Nullable DevicePolicyResourcesManager devicePolicyMgrRes) { + public FingerprintEnrollIntroFragment() { super(); - mViewModelProvider = viewModelProvider; - mDevicePolicyMgrRes = devicePolicyMgrRes; } @Nullable @@ -197,7 +190,8 @@ public class FingerprintEnrollIntroFragment extends Fragment { @Override public void onAttach(@NonNull Context context) { - mViewModel = mViewModelProvider.get(FingerprintEnrollIntroViewModel.class); + mViewModel = new ViewModelProvider(getActivity()) + .get(FingerprintEnrollIntroViewModel.class); getLifecycle().addObserver(mViewModel); super.onAttach(context); } @@ -232,12 +226,16 @@ public class FingerprintEnrollIntroFragment extends Fragment { private String getDescriptionDisabledByAdmin(@NonNull Context context) { final int defaultStrId = R.string.security_settings_fingerprint_enroll_introduction_message_unlock_disabled; - if (mDevicePolicyMgrRes == null) { + + final DevicePolicyManager devicePolicyManager = getActivity() + .getSystemService(DevicePolicyManager.class); + if (devicePolicyManager != null) { + return devicePolicyManager.getResources().getString(FINGERPRINT_UNLOCK_DISABLED, + () -> context.getString(defaultStrId)); + } else { Log.w(TAG, "getDescriptionDisabledByAdmin, null device policy manager res"); return ""; } - return mDevicePolicyMgrRes.getString(FINGERPRINT_UNLOCK_DISABLED, - () -> context.getString(defaultStrId)); } private void setHeaderText(@NonNull Activity activity, int resId) { diff --git a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollmentActivity.java b/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollmentActivity.java index e9cf6fd49b1..991aeba74d2 100644 --- a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollmentActivity.java +++ b/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollmentActivity.java @@ -19,20 +19,19 @@ package com.android.settings.biometrics2.ui.view; import static androidx.lifecycle.ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY; import static com.android.settings.biometrics2.factory.BiometricsViewModelFactory.CHALLENGE_GENERATOR; -import static com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.CREDENTIAL_FAIL_DURING_GENERATE_CHALLENGE; import static com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.CREDENTIAL_FAIL_NEED_TO_CHOOSE_LOCK; import static com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.CREDENTIAL_FAIL_NEED_TO_CONFIRM_LOCK; +import static com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.CREDENTIAL_IS_GENERATING_CHALLENGE; +import static com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.CREDENTIAL_VALID; import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollIntroViewModel.FINGERPRINT_ENROLL_INTRO_ACTION_CONTINUE_ENROLL; import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollIntroViewModel.FINGERPRINT_ENROLL_INTRO_ACTION_DONE_AND_FINISH; import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollIntroViewModel.FINGERPRINT_ENROLL_INTRO_ACTION_SKIP_OR_CANCEL; -import android.app.Activity; import android.app.Application; import android.content.Intent; import android.content.res.ColorStateList; import android.graphics.Color; import android.os.Bundle; -import android.os.SystemClock; import android.util.Log; import androidx.activity.result.ActivityResult; @@ -42,7 +41,6 @@ import androidx.annotation.ColorInt; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.FragmentActivity; -import androidx.fragment.app.FragmentManager; import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.viewmodel.CreationExtras; import androidx.lifecycle.viewmodel.MutableCreationExtras; @@ -51,11 +49,9 @@ import com.android.settings.R; import com.android.settings.Utils; import com.android.settings.biometrics.BiometricEnrollBase; import com.android.settings.biometrics.fingerprint.FingerprintEnrollFindSensor; -import com.android.settings.biometrics.fingerprint.SetupFingerprintEnrollEnrolling; +import com.android.settings.biometrics.fingerprint.SetupFingerprintEnrollFindSensor; import com.android.settings.biometrics2.data.repository.FingerprintRepository; -import com.android.settings.biometrics2.factory.BiometricsFragmentFactory; import com.android.settings.biometrics2.factory.BiometricsViewModelFactory; -import com.android.settings.biometrics2.ui.model.CredentialModel; import com.android.settings.biometrics2.ui.model.EnrollmentRequest; import com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel; import com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.FingerprintChallengeGenerator; @@ -102,12 +98,12 @@ public class FingerprintEnrollmentActivity extends FragmentActivity { getLifecycle().addObserver(mViewModel); mAutoCredentialViewModel = viewModelProvider.get(AutoCredentialViewModel.class); - mAutoCredentialViewModel.setCredentialModel(new CredentialModel(getIntent(), - SystemClock.elapsedRealtimeClock())); - getLifecycle().addObserver(mAutoCredentialViewModel); + mAutoCredentialViewModel.setCredentialModel(savedInstanceState, getIntent()); + mAutoCredentialViewModel.getGenerateChallengeFailLiveData().observe(this, + this::onGenerateChallengeFail); mViewModel.getSetResultLiveData().observe(this, this::onSetActivityResult); - mAutoCredentialViewModel.getActionLiveData().observe(this, this::onCredentialAction); + checkCredential(); // Theme setTheme(mViewModel.getRequest().getTheme()); @@ -116,21 +112,29 @@ public class FingerprintEnrollmentActivity extends FragmentActivity { // fragment setContentView(R.layout.biometric_enrollment_container); - final FragmentManager fragmentManager = getSupportFragmentManager(); - fragmentManager.setFragmentFactory( - new BiometricsFragmentFactory(getApplication(), viewModelProvider)); final FingerprintEnrollIntroViewModel fingerprintEnrollIntroViewModel = viewModelProvider.get(FingerprintEnrollIntroViewModel.class); fingerprintEnrollIntroViewModel.setEnrollmentRequest(mViewModel.getRequest()); fingerprintEnrollIntroViewModel.setUserId(mAutoCredentialViewModel.getUserId()); + + // Clear ActionLiveData in FragmentViewModel to prevent getting previous action when + // recreate + fingerprintEnrollIntroViewModel.clearActionLiveData(); fingerprintEnrollIntroViewModel.getActionLiveData().observe( this, this::observeIntroAction); - final String tag = "FingerprintEnrollIntroFragment"; - fragmentManager.beginTransaction() - .setReorderingAllowed(true) - .add(R.id.fragment_container_view, FingerprintEnrollIntroFragment.class, null, tag) - .commit(); + if (savedInstanceState == null) { + final String tag = "FingerprintEnrollIntroFragment"; + getSupportFragmentManager().beginTransaction() + .setReorderingAllowed(true) + .add(R.id.fragment_container_view, FingerprintEnrollIntroFragment.class, null, + tag) + .commit(); + } + } + + private void onGenerateChallengeFail(@NonNull Boolean isFail) { + onSetActivityResult(new ActivityResult(RESULT_CANCELED, null)); } private void onSetActivityResult(@NonNull ActivityResult result) { @@ -141,8 +145,8 @@ public class FingerprintEnrollmentActivity extends FragmentActivity { finish(); } - private void onCredentialAction(@NonNull Integer action) { - switch (action) { + private void checkCredential() { + switch (mAutoCredentialViewModel.checkCredential()) { case CREDENTIAL_FAIL_NEED_TO_CHOOSE_LOCK: { final Intent intent = mAutoCredentialViewModel.getChooseLockIntent(this, mViewModel.getRequest().isSuw(), mViewModel.getRequest().getSuwExtras()); @@ -168,12 +172,9 @@ public class FingerprintEnrollmentActivity extends FragmentActivity { } return; } - case CREDENTIAL_FAIL_DURING_GENERATE_CHALLENGE: { - Log.w(TAG, "observeCredentialLiveData, finish with action:" + action); - if (mViewModel.getRequest().isAfterSuwOrSuwSuggestedAction()) { - setResult(Activity.RESULT_CANCELED); - } - finish(); + case CREDENTIAL_VALID: + case CREDENTIAL_IS_GENERATING_CHALLENGE: { + // Do nothing } } } @@ -186,10 +187,15 @@ public class FingerprintEnrollmentActivity extends FragmentActivity { if (mAutoCredentialViewModel.checkNewCredentialFromActivityResult( isChooseLock, activityResult)) { overridePendingTransition(R.anim.sud_slide_next_in, R.anim.sud_slide_next_out); + } else { + onSetActivityResult(activityResult); } } - private void observeIntroAction(@NonNull Integer action) { + private void observeIntroAction(@Nullable Integer action) { + if (action == null) { + return; + } switch (action) { case FINGERPRINT_ENROLL_INTRO_ACTION_DONE_AND_FINISH: { onSetActivityResult( @@ -207,9 +213,9 @@ public class FingerprintEnrollmentActivity extends FragmentActivity { Log.w(TAG, "startNext, isSuw:" + isSuw + ", fail to set isWaiting flag"); } final Intent intent = new Intent(this, isSuw - ? SetupFingerprintEnrollEnrolling.class + ? SetupFingerprintEnrollFindSensor.class : FingerprintEnrollFindSensor.class); - intent.putExtras(mAutoCredentialViewModel.getCredentialBundle()); + intent.putExtras(mAutoCredentialViewModel.getCredentialIntentExtra()); intent.putExtras(mViewModel.getNextActivityBaseIntentExtras()); mNextActivityLauncher.launch(intent); } @@ -272,5 +278,6 @@ public class FingerprintEnrollmentActivity extends FragmentActivity { protected void onSaveInstanceState(@NonNull Bundle outState) { super.onSaveInstanceState(outState); mViewModel.onSaveInstanceState(outState); + mAutoCredentialViewModel.onSaveInstanceState(outState); } } diff --git a/src/com/android/settings/biometrics2/ui/viewmodel/AutoCredentialViewModel.java b/src/com/android/settings/biometrics2/ui/viewmodel/AutoCredentialViewModel.java index b1a7f90e33f..a443e69a855 100644 --- a/src/com/android/settings/biometrics2/ui/viewmodel/AutoCredentialViewModel.java +++ b/src/com/android/settings/biometrics2/ui/viewmodel/AutoCredentialViewModel.java @@ -30,20 +30,21 @@ import android.app.Application; import android.content.Context; import android.content.Intent; import android.os.Bundle; +import android.os.SystemClock; import android.util.Log; import androidx.activity.result.ActivityResult; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.annotation.VisibleForTesting; import androidx.lifecycle.AndroidViewModel; -import androidx.lifecycle.DefaultLifecycleObserver; -import androidx.lifecycle.LifecycleOwner; import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.VerifyCredentialResponse; import com.android.settings.biometrics.BiometricUtils; +import com.android.settings.biometrics.BiometricUtils.GatekeeperCredentialNotMatchException; import com.android.settings.biometrics2.data.repository.FingerprintRepository; import com.android.settings.biometrics2.ui.model.CredentialModel; import com.android.settings.password.ChooseLockGeneric; @@ -57,31 +58,40 @@ import java.lang.annotation.RetentionPolicy; * AutoCredentialViewModel which uses CredentialModel to determine next actions for activity, like * start ChooseLockActivity, start ConfirmLockActivity, GenerateCredential, or do nothing. */ -public class AutoCredentialViewModel extends AndroidViewModel implements DefaultLifecycleObserver { +public class AutoCredentialViewModel extends AndroidViewModel { private static final String TAG = "AutoCredentialViewModel"; - private static final boolean DEBUG = true; + + @VisibleForTesting + static final String KEY_CREDENTIAL_MODEL = "credential_model"; + + private static final boolean DEBUG = false; + + /** + * Valid credential, activity doesn't need to do anything. + */ + public static final int CREDENTIAL_VALID = 0; + + /** + * This credential looks good, but still need to run generateChallenge(). + */ + public static final int CREDENTIAL_IS_GENERATING_CHALLENGE = 1; /** * Need activity to run choose lock */ - public static final int CREDENTIAL_FAIL_NEED_TO_CHOOSE_LOCK = 1; + public static final int CREDENTIAL_FAIL_NEED_TO_CHOOSE_LOCK = 2; /** * Need activity to run confirm lock */ - public static final int CREDENTIAL_FAIL_NEED_TO_CONFIRM_LOCK = 2; - - /** - * Fail to use challenge from hardware generateChallenge(), shall finish activity with proper - * error code - */ - public static final int CREDENTIAL_FAIL_DURING_GENERATE_CHALLENGE = 3; + public static final int CREDENTIAL_FAIL_NEED_TO_CONFIRM_LOCK = 3; @IntDef(prefix = { "CREDENTIAL_" }, value = { + CREDENTIAL_VALID, + CREDENTIAL_IS_GENERATING_CHALLENGE, CREDENTIAL_FAIL_NEED_TO_CHOOSE_LOCK, - CREDENTIAL_FAIL_NEED_TO_CONFIRM_LOCK, - CREDENTIAL_FAIL_DURING_GENERATE_CHALLENGE + CREDENTIAL_FAIL_NEED_TO_CONFIRM_LOCK }) @Retention(RetentionPolicy.SOURCE) public @interface CredentialAction {} @@ -157,11 +167,10 @@ public class AutoCredentialViewModel extends AndroidViewModel implements Default } } - @NonNull private final LockPatternUtils mLockPatternUtils; @NonNull private final ChallengeGenerator mChallengeGenerator; private CredentialModel mCredentialModel = null; - @NonNull private final MutableLiveData mActionLiveData = + @NonNull private final MutableLiveData mGenerateChallengeFailLiveData = new MutableLiveData<>(); public AutoCredentialViewModel( @@ -173,51 +182,63 @@ public class AutoCredentialViewModel extends AndroidViewModel implements Default mChallengeGenerator = challengeGenerator; } - public void setCredentialModel(@NonNull CredentialModel credentialModel) { - mCredentialModel = credentialModel; + /** + * Set CredentialModel, the source is coming from savedInstanceState or activity intent + */ + public void setCredentialModel(@Nullable Bundle savedInstanceState, @NonNull Intent intent) { + mCredentialModel = new CredentialModel( + savedInstanceState != null + ? savedInstanceState.getBundle(KEY_CREDENTIAL_MODEL) + : intent.getExtras(), + SystemClock.elapsedRealtimeClock()); + + if (DEBUG) { + Log.d(TAG, "setCredentialModel " + mCredentialModel + ", savedInstanceState exist:" + + (savedInstanceState != null)); + } } /** - * Observe ActionLiveData for actions about choosing lock, confirming lock, or finishing - * activity + * Handle onSaveInstanceState from activity */ - @NonNull - public LiveData getActionLiveData() { - return mActionLiveData; + public void onSaveInstanceState(@NonNull Bundle outState) { + outState.putBundle(KEY_CREDENTIAL_MODEL, mCredentialModel.getBundle()); } - @Override - public void onCreate(@NonNull LifecycleOwner owner) { - checkCredential(); + @NonNull + public LiveData getGenerateChallengeFailLiveData() { + return mGenerateChallengeFailLiveData; } /** * Check credential status for biometric enrollment. */ - private void checkCredential() { + @CredentialAction + public int checkCredential() { if (isValidCredential()) { - return; + return CREDENTIAL_VALID; } final long gkPwHandle = mCredentialModel.getGkPwHandle(); if (isUnspecifiedPassword()) { - mActionLiveData.postValue(CREDENTIAL_FAIL_NEED_TO_CHOOSE_LOCK); + return CREDENTIAL_FAIL_NEED_TO_CHOOSE_LOCK; } else if (CredentialModel.isValidGkPwHandle(gkPwHandle)) { generateChallenge(gkPwHandle); + return CREDENTIAL_IS_GENERATING_CHALLENGE; } else { - mActionLiveData.postValue(CREDENTIAL_FAIL_NEED_TO_CONFIRM_LOCK); + return CREDENTIAL_FAIL_NEED_TO_CONFIRM_LOCK; } } private void generateChallenge(long gkPwHandle) { mChallengeGenerator.setCallback((sensorId, userId, challenge) -> { - mCredentialModel.setSensorId(sensorId); - mCredentialModel.setChallenge(challenge); try { final byte[] newToken = requestGatekeeperHat(gkPwHandle, challenge, userId); + mCredentialModel.setSensorId(sensorId); + mCredentialModel.setChallenge(challenge); mCredentialModel.setToken(newToken); } catch (IllegalStateException e) { Log.e(TAG, "generateChallenge, IllegalStateException", e); - mActionLiveData.postValue(CREDENTIAL_FAIL_DURING_GENERATE_CHALLENGE); + mGenerateChallengeFailLiveData.postValue(true); return; } @@ -231,7 +252,7 @@ public class AutoCredentialViewModel extends AndroidViewModel implements Default // Check credential again if (!isValidCredential()) { Log.w(TAG, "generateChallenge, invalid Credential"); - mActionLiveData.postValue(CREDENTIAL_FAIL_DURING_GENERATE_CHALLENGE); + mGenerateChallengeFailLiveData.postValue(true); } }); mChallengeGenerator.generateChallenge(getUserId()); @@ -282,16 +303,16 @@ public class AutoCredentialViewModel extends AndroidViewModel implements Default final VerifyCredentialResponse response = mLockPatternUtils .verifyGatekeeperPasswordHandle(gkPwHandle, challenge, userId); if (!response.isMatched()) { - throw new IllegalStateException("Unable to request Gatekeeper HAT"); + throw new GatekeeperCredentialNotMatchException("Unable to request Gatekeeper HAT"); } return response.getGatekeeperHAT(); } /** - * Get Credential bundle which will be used to launch next activity. + * Get Credential intent extra which will be used to launch next activity. */ @NonNull - public Bundle getCredentialBundle() { + public Bundle getCredentialIntentExtra() { final Bundle retBundle = new Bundle(); final long gkPwHandle = mCredentialModel.getGkPwHandle(); if (CredentialModel.isValidGkPwHandle(gkPwHandle)) { diff --git a/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollIntroViewModel.java b/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollIntroViewModel.java index 252a508e630..3274eb29565 100644 --- a/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollIntroViewModel.java +++ b/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollIntroViewModel.java @@ -144,6 +144,13 @@ public class FingerprintEnrollIntroViewModel extends AndroidViewModel return mPageStatusLiveData; } + /** + * Clear user's action live data (like clicking Agree, Skip, or Done) + */ + public void clearActionLiveData() { + mActionLiveData.setValue(null); + } + /** * Get user's action live data (like clicking Agree, Skip, or Done) */ diff --git a/tests/unit/src/com/android/settings/biometrics2/ui/model/CredentialModelTest.java b/tests/unit/src/com/android/settings/biometrics2/ui/model/CredentialModelTest.java new file mode 100644 index 00000000000..1fac8b5b084 --- /dev/null +++ b/tests/unit/src/com/android/settings/biometrics2/ui/model/CredentialModelTest.java @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.biometrics2.ui.model; + +import static com.android.settings.biometrics.BiometricEnrollBase.EXTRA_KEY_CHALLENGE; +import static com.android.settings.biometrics.BiometricEnrollBase.EXTRA_KEY_SENSOR_ID; +import static com.android.settings.biometrics2.ui.model.CredentialModel.INVALID_CHALLENGE; +import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE; + +import static com.google.common.truth.Truth.assertThat; +import static com.google.common.truth.Truth.assertWithMessage; + +import android.annotation.NonNull; +import android.content.Intent; +import android.os.Bundle; +import android.os.SystemClock; + +import androidx.annotation.Nullable; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import com.android.settings.password.ChooseLockSettingsHelper; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.time.Clock; +import java.util.Arrays; +import java.util.Set; + +@RunWith(AndroidJUnit4.class) +public class CredentialModelTest { + + private final Clock mClock = SystemClock.elapsedRealtimeClock(); + + public static Bundle newCredentialModelIntentExtras(int userId, long challenge, int sensorId, + @Nullable byte[] token, long gkPwHandle) { + final Bundle bundle = new Bundle(); + bundle.putInt(Intent.EXTRA_USER_ID, userId); + bundle.putInt(EXTRA_KEY_SENSOR_ID, sensorId); + bundle.putLong(EXTRA_KEY_CHALLENGE, challenge); + bundle.putByteArray(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token); + bundle.putLong(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, gkPwHandle); + return bundle; + } + + public static Bundle newValidTokenCredentialIntentExtras(int userId) { + return newCredentialModelIntentExtras(userId, 1L, 1, new byte[] { 0 }, 0L); + } + + public static Bundle newInvalidChallengeCredentialIntentExtras(int userId) { + return newCredentialModelIntentExtras(userId, INVALID_CHALLENGE, 1, null, 0L); + } + + public static Bundle newGkPwHandleCredentialIntentExtras(int userId, long gkPwHandle) { + return newCredentialModelIntentExtras(userId, INVALID_CHALLENGE, 1, null, gkPwHandle); + } + + private static void checkBundleLongValue(@NonNull Bundle bundle1, @NonNull Bundle bundle2, + @NonNull String key) { + if (!bundle1.containsKey(key)) { + return; + } + final int value1 = bundle1.getInt(key); + final int value2 = bundle2.getInt(key); + assertWithMessage("bundle not match, key:" + key + ", value1:" + value1 + ", value2:" + + value2).that(value1).isEqualTo(value2); + } + + private static void checkBundleIntValue(@NonNull Bundle bundle1, @NonNull Bundle bundle2, + @NonNull String key) { + if (!bundle1.containsKey(key)) { + return; + } + final long value1 = bundle1.getLong(key); + final long value2 = bundle2.getLong(key); + assertWithMessage("bundle not match, key:" + key + ", value1:" + value1 + ", value2:" + + value2).that(value1).isEqualTo(value2); + } + + private static void checkBundleByteArrayValue(@NonNull Bundle bundle1, @NonNull Bundle bundle2, + @NonNull String key) { + if (!bundle1.containsKey(key)) { + return; + } + final byte[] value1 = bundle1.getByteArray(key); + final byte[] value2 = bundle2.getByteArray(key); + final String errMsg = "bundle not match, key:" + key + ", value1:" + Arrays.toString(value1) + + ", value2:" + Arrays.toString(value2); + if (value1 == null) { + assertWithMessage(errMsg).that(value2).isNull(); + } else { + assertWithMessage(errMsg).that(value1.length).isEqualTo(value2.length); + for (int i = 0; i < value1.length; ++i) { + assertWithMessage(errMsg).that(value1[i]).isEqualTo(value2[i]); + } + } + } + + public static void verifySameCredentialModels(@NonNull CredentialModel model1, + @NonNull CredentialModel model2) { + + assertThat(model1.getUserId()).isEqualTo(model2.getUserId()); + assertThat(model1.getSensorId()).isEqualTo(model2.getSensorId()); + assertThat(model1.getChallenge()).isEqualTo(model2.getChallenge()); + assertThat(model1.getGkPwHandle()).isEqualTo(model2.getGkPwHandle()); + + final byte[] token1 = model1.getToken(); + final byte[] token2 = model2.getToken(); + if (token1 == null) { + assertThat(token2).isNull(); + } else { + assertThat(token2).isNotNull(); + assertThat(token1.length).isEqualTo(token2.length); + for (int i = 0; i < token1.length; ++i) { + assertThat(token1[i]).isEqualTo(token2[i]); + } + } + + final Bundle bundle1 = model1.getBundle(); + final Bundle bundle2 = model2.getBundle(); + final Set keySet1 = bundle1.keySet(); + assertThat(keySet1.equals(bundle2.keySet())).isTrue(); + checkBundleIntValue(bundle1, bundle2, Intent.EXTRA_USER_ID); + checkBundleIntValue(bundle1, bundle2, EXTRA_KEY_SENSOR_ID); + checkBundleLongValue(bundle1, bundle2, EXTRA_KEY_CHALLENGE); + checkBundleByteArrayValue(bundle1, bundle2, EXTRA_KEY_CHALLENGE); + checkBundleLongValue(bundle1, bundle2, EXTRA_KEY_GK_PW_HANDLE); + } + + @Test + public void sameValueFromBundle() { + final Bundle bundle = newCredentialModelIntentExtras(1234, 6677L, 1, + new byte[] { 33, 44, 55 }, 987654321); + + final CredentialModel model1 = new CredentialModel(bundle, mClock); + final CredentialModel model2 = new CredentialModel(model1.getBundle(), mClock); + + verifySameCredentialModels(model1, model2); + } + + @Test + public void sameValueFromBundle_nullToken() { + final Bundle bundle = newCredentialModelIntentExtras(22, 33L, 1, null, 21L); + + final CredentialModel model1 = new CredentialModel(bundle, mClock); + final CredentialModel model2 = new CredentialModel(model1.getBundle(), mClock); + + verifySameCredentialModels(model1, model2); + } +} diff --git a/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/AutoCredentialViewModelTest.java b/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/AutoCredentialViewModelTest.java index 7a13875a8fa..a11650ebe84 100644 --- a/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/AutoCredentialViewModelTest.java +++ b/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/AutoCredentialViewModelTest.java @@ -24,12 +24,22 @@ import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED import static com.android.settings.biometrics.BiometricEnrollBase.EXTRA_KEY_CHALLENGE; import static com.android.settings.biometrics.BiometricEnrollBase.EXTRA_KEY_SENSOR_ID; import static com.android.settings.biometrics2.ui.model.CredentialModel.INVALID_CHALLENGE; +import static com.android.settings.biometrics2.ui.model.CredentialModel.INVALID_GK_PW_HANDLE; import static com.android.settings.biometrics2.ui.model.CredentialModel.INVALID_SENSOR_ID; +import static com.android.settings.biometrics2.ui.model.CredentialModelTest.newCredentialModelIntentExtras; +import static com.android.settings.biometrics2.ui.model.CredentialModelTest.newGkPwHandleCredentialIntentExtras; +import static com.android.settings.biometrics2.ui.model.CredentialModelTest.newInvalidChallengeCredentialIntentExtras; +import static com.android.settings.biometrics2.ui.model.CredentialModelTest.newValidTokenCredentialIntentExtras; import static com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.CREDENTIAL_FAIL_NEED_TO_CHOOSE_LOCK; import static com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.CREDENTIAL_FAIL_NEED_TO_CONFIRM_LOCK; +import static com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.CREDENTIAL_IS_GENERATING_CHALLENGE; +import static com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.CREDENTIAL_VALID; import static com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.ChallengeGenerator; import static com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.CredentialAction; import static com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.GenerateChallengeCallback; +import static com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.KEY_CREDENTIAL_MODEL; +import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN; +import static com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE; import static com.google.common.truth.Truth.assertThat; @@ -38,12 +48,11 @@ import static org.mockito.Mockito.when; import android.annotation.NonNull; import android.app.Activity; import android.content.Intent; -import android.os.SystemClock; +import android.os.Bundle; import android.os.UserHandle; import androidx.activity.result.ActivityResult; import androidx.annotation.Nullable; -import androidx.lifecycle.LifecycleOwner; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; @@ -68,7 +77,6 @@ public class AutoCredentialViewModelTest { @Rule public final MockitoRule mockito = MockitoJUnit.rule(); @Rule public final InstantTaskExecutorRule mTaskExecutorRule = new InstantTaskExecutorRule(); - @Mock private LifecycleOwner mLifecycleOwner; @Mock private LockPatternUtils mLockPatternUtils; private TestChallengeGenerator mChallengeGenerator = null; private AutoCredentialViewModel mAutoCredentialViewModel; @@ -82,142 +90,222 @@ public class AutoCredentialViewModelTest { mChallengeGenerator); } - private CredentialModel newCredentialModel(int userId, long challenge, - @Nullable byte[] token, long gkPwHandle) { - final Intent intent = new Intent(); - intent.putExtra(Intent.EXTRA_USER_ID, userId); - intent.putExtra(EXTRA_KEY_SENSOR_ID, 1); - intent.putExtra(EXTRA_KEY_CHALLENGE, challenge); - intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token); - intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, gkPwHandle); - return new CredentialModel(intent, SystemClock.elapsedRealtimeClock()); - } - - private CredentialModel newValidTokenCredentialModel(int userId) { - return newCredentialModel(userId, 1L, new byte[] { 0 }, 0L); - } - - private CredentialModel newInvalidChallengeCredentialModel(int userId) { - return newCredentialModel(userId, INVALID_CHALLENGE, null, 0L); - } - - private CredentialModel newGkPwHandleCredentialModel(int userId, long gkPwHandle) { - return newCredentialModel(userId, INVALID_CHALLENGE, null, gkPwHandle); - } - - private void verifyNothingHappen() { - assertThat(mAutoCredentialViewModel.getActionLiveData().getValue()).isNull(); - } - - private void verifyOnlyActionLiveData(@CredentialAction int action) { - final Integer value = mAutoCredentialViewModel.getActionLiveData().getValue(); - assertThat(value).isEqualTo(action); - } - - private void setupGenerateTokenFlow(long gkPwHandle, int userId, int newSensorId, - long newChallenge) { + private void setupGenerateChallenge(int userId, int newSensorId, long newChallenge) { when(mLockPatternUtils.getActivePasswordQuality(userId)).thenReturn( PASSWORD_QUALITY_SOMETHING); mChallengeGenerator.mUserId = userId; mChallengeGenerator.mSensorId = newSensorId; mChallengeGenerator.mChallenge = newChallenge; - when(mLockPatternUtils.verifyGatekeeperPasswordHandle(gkPwHandle, newChallenge, userId)) - .thenReturn(newGoodCredential(gkPwHandle, new byte[] { 1 })); } @Test - public void checkCredential_validCredentialCase() { + public void testGetCredentialIntentExtra_sameResultFromSavedInstanceOrIntent() { + final Bundle extras = newCredentialModelIntentExtras(12, 33, 1, new byte[] { 2, 3 }, 3L); + + AutoCredentialViewModel autoCredentialViewModel2 = new AutoCredentialViewModel( + ApplicationProvider.getApplicationContext(), + mLockPatternUtils, + mChallengeGenerator); + + mAutoCredentialViewModel.setCredentialModel(null, + new Intent().putExtras(extras)); + final Bundle savedInstance = new Bundle(); + savedInstance.putBundle(KEY_CREDENTIAL_MODEL, extras); + autoCredentialViewModel2.setCredentialModel(savedInstance, new Intent()); + + final Bundle bundle1 = mAutoCredentialViewModel.getCredentialIntentExtra(); + final Bundle bundle2 = autoCredentialViewModel2.getCredentialIntentExtra(); + assertThat(bundle1.getLong(EXTRA_KEY_GK_PW_HANDLE)) + .isEqualTo(bundle2.getLong(EXTRA_KEY_GK_PW_HANDLE)); + assertThat(bundle1.getLong(Intent.EXTRA_USER_ID)) + .isEqualTo(bundle2.getLong(Intent.EXTRA_USER_ID)); + assertThat(bundle1.getLong(EXTRA_KEY_CHALLENGE)) + .isEqualTo(bundle2.getLong(EXTRA_KEY_CHALLENGE)); + assertThat(bundle1.getInt(EXTRA_KEY_SENSOR_ID)) + .isEqualTo(bundle2.getInt(EXTRA_KEY_SENSOR_ID)); + final byte[] token1 = bundle1.getByteArray(EXTRA_KEY_CHALLENGE_TOKEN); + final byte[] token2 = bundle2.getByteArray(EXTRA_KEY_CHALLENGE_TOKEN); + assertThat(token1).isNotNull(); + assertThat(token2).isNotNull(); + assertThat(token1.length).isEqualTo(token2.length); + for (int i = 0; i < token2.length; ++i) { + assertThat(token1[i]).isEqualTo(token2[i]); + } + } + + @Test + public void testGetCredentialIntentExtra_sameResultFromSavedInstanceOrIntent_invalidValues() { + final Bundle extras = newCredentialModelIntentExtras(UserHandle.USER_NULL, + INVALID_CHALLENGE, INVALID_SENSOR_ID, null, INVALID_GK_PW_HANDLE); + + AutoCredentialViewModel autoCredentialViewModel2 = new AutoCredentialViewModel( + ApplicationProvider.getApplicationContext(), + mLockPatternUtils, + mChallengeGenerator); + + mAutoCredentialViewModel.setCredentialModel(null, + new Intent().putExtras(extras)); + final Bundle savedInstance = new Bundle(); + savedInstance.putBundle(KEY_CREDENTIAL_MODEL, extras); + autoCredentialViewModel2.setCredentialModel(savedInstance, new Intent()); + + final Bundle bundle1 = mAutoCredentialViewModel.getCredentialIntentExtra(); + final Bundle bundle2 = autoCredentialViewModel2.getCredentialIntentExtra(); + assertThat(bundle1.containsKey(EXTRA_KEY_GK_PW_HANDLE)).isFalse(); + assertThat(bundle2.containsKey(EXTRA_KEY_GK_PW_HANDLE)).isFalse(); + assertThat(bundle1.containsKey(EXTRA_KEY_CHALLENGE_TOKEN)).isFalse(); + assertThat(bundle2.containsKey(EXTRA_KEY_CHALLENGE_TOKEN)).isFalse(); + assertThat(bundle1.containsKey(EXTRA_KEY_SENSOR_ID)).isTrue(); + assertThat(bundle2.containsKey(EXTRA_KEY_SENSOR_ID)).isTrue(); + assertThat(bundle1.containsKey(Intent.EXTRA_USER_ID)).isFalse(); + assertThat(bundle2.containsKey(Intent.EXTRA_USER_ID)).isFalse(); + } + + @Test + public void testCheckCredential_validCredentialCase() { final int userId = 99; - mAutoCredentialViewModel.setCredentialModel(newValidTokenCredentialModel(userId)); + mAutoCredentialViewModel.setCredentialModel(null, + new Intent().putExtras(newValidTokenCredentialIntentExtras(userId))); when(mLockPatternUtils.getActivePasswordQuality(userId)).thenReturn( PASSWORD_QUALITY_SOMETHING); // Run credential check - mAutoCredentialViewModel.onCreate(mLifecycleOwner); + @CredentialAction final int action = mAutoCredentialViewModel.checkCredential(); - verifyNothingHappen(); + assertThat(action).isEqualTo(CREDENTIAL_VALID); + assertThat(mAutoCredentialViewModel.getGenerateChallengeFailLiveData().getValue()).isNull(); } @Test - public void checkCredential_needToChooseLock() { + public void testCheckCredential_needToChooseLock() { final int userId = 100; - mAutoCredentialViewModel.setCredentialModel(newInvalidChallengeCredentialModel(userId)); + mAutoCredentialViewModel.setCredentialModel(null, + new Intent().putExtras(newInvalidChallengeCredentialIntentExtras(userId))); when(mLockPatternUtils.getActivePasswordQuality(userId)).thenReturn( PASSWORD_QUALITY_UNSPECIFIED); // Run credential check - mAutoCredentialViewModel.onCreate(mLifecycleOwner); + @CredentialAction final int action = mAutoCredentialViewModel.checkCredential(); - verifyOnlyActionLiveData(CREDENTIAL_FAIL_NEED_TO_CHOOSE_LOCK); + assertThat(action).isEqualTo(CREDENTIAL_FAIL_NEED_TO_CHOOSE_LOCK); + assertThat(mAutoCredentialViewModel.getGenerateChallengeFailLiveData().getValue()).isNull(); } @Test - public void checkCredential_needToConfirmLockFoSomething() { + public void testCheckCredential_needToConfirmLockFoSomething() { final int userId = 101; - mAutoCredentialViewModel.setCredentialModel(newInvalidChallengeCredentialModel(userId)); + mAutoCredentialViewModel.setCredentialModel(null, + new Intent().putExtras(newInvalidChallengeCredentialIntentExtras(userId))); when(mLockPatternUtils.getActivePasswordQuality(userId)).thenReturn( PASSWORD_QUALITY_SOMETHING); // Run credential check - mAutoCredentialViewModel.onCreate(mLifecycleOwner); + @CredentialAction final int action = mAutoCredentialViewModel.checkCredential(); - verifyOnlyActionLiveData(CREDENTIAL_FAIL_NEED_TO_CONFIRM_LOCK); + assertThat(action).isEqualTo(CREDENTIAL_FAIL_NEED_TO_CONFIRM_LOCK); + assertThat(mAutoCredentialViewModel.getGenerateChallengeFailLiveData().getValue()).isNull(); } @Test - public void checkCredential_needToConfirmLockForNumeric() { + public void testCheckCredential_needToConfirmLockForNumeric() { final int userId = 102; - mAutoCredentialViewModel.setCredentialModel(newInvalidChallengeCredentialModel(userId)); + mAutoCredentialViewModel.setCredentialModel(null, + new Intent().putExtras(newInvalidChallengeCredentialIntentExtras(userId))); when(mLockPatternUtils.getActivePasswordQuality(userId)).thenReturn( PASSWORD_QUALITY_NUMERIC); // Run credential check - mAutoCredentialViewModel.onCreate(mLifecycleOwner); + @CredentialAction final int action = mAutoCredentialViewModel.checkCredential(); - verifyOnlyActionLiveData(CREDENTIAL_FAIL_NEED_TO_CONFIRM_LOCK); + assertThat(action).isEqualTo(CREDENTIAL_FAIL_NEED_TO_CONFIRM_LOCK); + assertThat(mAutoCredentialViewModel.getGenerateChallengeFailLiveData().getValue()).isNull(); } @Test - public void checkCredential_needToConfirmLockForAlphabetic() { + public void testCheckCredential_needToConfirmLockForAlphabetic() { final int userId = 103; - mAutoCredentialViewModel.setCredentialModel(newInvalidChallengeCredentialModel(userId)); + mAutoCredentialViewModel.setCredentialModel(null, + new Intent().putExtras(newInvalidChallengeCredentialIntentExtras(userId))); when(mLockPatternUtils.getActivePasswordQuality(userId)).thenReturn( PASSWORD_QUALITY_ALPHABETIC); // Run credential check - mAutoCredentialViewModel.onCreate(mLifecycleOwner); + @CredentialAction final int action = mAutoCredentialViewModel.checkCredential(); - verifyOnlyActionLiveData(CREDENTIAL_FAIL_NEED_TO_CONFIRM_LOCK); + assertThat(action).isEqualTo(CREDENTIAL_FAIL_NEED_TO_CONFIRM_LOCK); + assertThat(mAutoCredentialViewModel.getGenerateChallengeFailLiveData().getValue()).isNull(); } @Test - public void checkCredential_generateChallenge() { + public void testCheckCredential_generateChallenge() { final int userId = 104; final long gkPwHandle = 1111L; - final CredentialModel credentialModel = newGkPwHandleCredentialModel(userId, gkPwHandle); - mAutoCredentialViewModel.setCredentialModel(credentialModel); + mAutoCredentialViewModel.setCredentialModel(null, + new Intent().putExtras(newGkPwHandleCredentialIntentExtras(userId, gkPwHandle))); when(mLockPatternUtils.getActivePasswordQuality(userId)).thenReturn( PASSWORD_QUALITY_SOMETHING); final int newSensorId = 10; final long newChallenge = 20L; - setupGenerateTokenFlow(gkPwHandle, userId, newSensorId, newChallenge); + setupGenerateChallenge(userId, newSensorId, newChallenge); + when(mLockPatternUtils.verifyGatekeeperPasswordHandle(gkPwHandle, newChallenge, userId)) + .thenReturn(newGoodCredential(gkPwHandle, new byte[] { 1 })); // Run credential check - mAutoCredentialViewModel.onCreate(mLifecycleOwner); + @CredentialAction final int action = mAutoCredentialViewModel.checkCredential(); - assertThat(mAutoCredentialViewModel.getActionLiveData().getValue()).isNull(); - assertThat(credentialModel.getSensorId()).isEqualTo(newSensorId); - assertThat(credentialModel.getChallenge()).isEqualTo(newChallenge); - assertThat(CredentialModel.isValidToken(credentialModel.getToken())).isTrue(); - assertThat(CredentialModel.isValidGkPwHandle(credentialModel.getGkPwHandle())).isFalse(); + assertThat(action).isEqualTo(CREDENTIAL_IS_GENERATING_CHALLENGE); + assertThat(mAutoCredentialViewModel.getGenerateChallengeFailLiveData().getValue()).isNull(); + final Bundle extras = mAutoCredentialViewModel.getCredentialIntentExtra(); + assertThat(extras.getInt(EXTRA_KEY_SENSOR_ID)).isEqualTo(newSensorId); + assertThat(extras.getLong(EXTRA_KEY_CHALLENGE)).isEqualTo(newChallenge); + assertThat(CredentialModel.isValidToken(extras.getByteArray(EXTRA_KEY_CHALLENGE_TOKEN))) + .isTrue(); + assertThat(CredentialModel.isValidGkPwHandle(extras.getLong(EXTRA_KEY_GK_PW_HANDLE))) + .isFalse(); assertThat(mChallengeGenerator.mCallbackRunCount).isEqualTo(1); } @Test - public void testGetUserId() { + public void testCheckCredential_generateChallengeFail() { + final int userId = 104; + final long gkPwHandle = 1111L; + mAutoCredentialViewModel.setCredentialModel(null, + new Intent().putExtras(newGkPwHandleCredentialIntentExtras(userId, gkPwHandle))); + when(mLockPatternUtils.getActivePasswordQuality(userId)).thenReturn( + PASSWORD_QUALITY_SOMETHING); + + final int newSensorId = 10; + final long newChallenge = 20L; + setupGenerateChallenge(userId, newSensorId, newChallenge); + when(mLockPatternUtils.verifyGatekeeperPasswordHandle(gkPwHandle, newChallenge, userId)) + .thenReturn(newBadCredential(0)); + + // Run credential check + @CredentialAction final int action = mAutoCredentialViewModel.checkCredential(); + + assertThat(action).isEqualTo(CREDENTIAL_IS_GENERATING_CHALLENGE); + assertThat(mAutoCredentialViewModel.getGenerateChallengeFailLiveData().getValue()).isTrue(); + assertThat(mChallengeGenerator.mCallbackRunCount).isEqualTo(1); + } + + @Test + public void testGetUserId_fromIntent() { final int userId = 106; - mAutoCredentialViewModel.setCredentialModel(newInvalidChallengeCredentialModel(userId)); + mAutoCredentialViewModel.setCredentialModel(null, + new Intent().putExtras(newInvalidChallengeCredentialIntentExtras(userId))); + + // Get userId + assertThat(mAutoCredentialViewModel.getUserId()).isEqualTo(userId); + } + + @Test + public void testGetUserId_fromSavedInstance() { + final int userId = 106; + final Bundle savedInstance = new Bundle(); + savedInstance.putBundle(KEY_CREDENTIAL_MODEL, + newInvalidChallengeCredentialIntentExtras(userId)); + mAutoCredentialViewModel.setCredentialModel(savedInstance, new Intent()); // Get userId assertThat(mAutoCredentialViewModel.getUserId()).isEqualTo(userId); @@ -227,8 +315,8 @@ public class AutoCredentialViewModelTest { public void testCheckNewCredentialFromActivityResult_invalidChooseLock() { final int userId = 107; final long gkPwHandle = 3333L; - mAutoCredentialViewModel.setCredentialModel( - newGkPwHandleCredentialModel(userId, gkPwHandle)); + mAutoCredentialViewModel.setCredentialModel(null, + new Intent().putExtras(newGkPwHandleCredentialIntentExtras(userId, gkPwHandle))); final Intent intent = new Intent(); intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, gkPwHandle); @@ -237,15 +325,15 @@ public class AutoCredentialViewModelTest { new ActivityResult(ChooseLockPattern.RESULT_FINISHED + 1, intent)); assertThat(ret).isFalse(); - verifyNothingHappen(); + assertThat(mAutoCredentialViewModel.getGenerateChallengeFailLiveData().getValue()).isNull(); } @Test public void testCheckNewCredentialFromActivityResult_invalidConfirmLock() { final int userId = 107; final long gkPwHandle = 3333L; - mAutoCredentialViewModel.setCredentialModel( - newGkPwHandleCredentialModel(userId, gkPwHandle)); + mAutoCredentialViewModel.setCredentialModel(null, + new Intent().putExtras(newGkPwHandleCredentialIntentExtras(userId, gkPwHandle))); final Intent intent = new Intent(); intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, gkPwHandle); @@ -254,62 +342,68 @@ public class AutoCredentialViewModelTest { new ActivityResult(Activity.RESULT_OK + 1, intent)); assertThat(ret).isFalse(); - verifyNothingHappen(); + assertThat(mAutoCredentialViewModel.getGenerateChallengeFailLiveData().getValue()).isNull(); } @Test public void testCheckNewCredentialFromActivityResult_nullDataChooseLock() { final int userId = 108; final long gkPwHandle = 4444L; - mAutoCredentialViewModel.setCredentialModel( - newGkPwHandleCredentialModel(userId, gkPwHandle)); + mAutoCredentialViewModel.setCredentialModel(null, + new Intent().putExtras(newGkPwHandleCredentialIntentExtras(userId, gkPwHandle))); // run checkNewCredentialFromActivityResult() final boolean ret = mAutoCredentialViewModel.checkNewCredentialFromActivityResult(true, new ActivityResult(ChooseLockPattern.RESULT_FINISHED, null)); assertThat(ret).isFalse(); - verifyNothingHappen(); + assertThat(mAutoCredentialViewModel.getGenerateChallengeFailLiveData().getValue()).isNull(); } @Test public void testCheckNewCredentialFromActivityResult_nullDataConfirmLock() { final int userId = 109; - mAutoCredentialViewModel.setCredentialModel(newInvalidChallengeCredentialModel(userId)); + mAutoCredentialViewModel.setCredentialModel(null, + new Intent().putExtras(newInvalidChallengeCredentialIntentExtras(userId))); // run checkNewCredentialFromActivityResult() final boolean ret = mAutoCredentialViewModel.checkNewCredentialFromActivityResult(false, new ActivityResult(Activity.RESULT_OK, null)); assertThat(ret).isFalse(); - verifyNothingHappen(); + assertThat(mAutoCredentialViewModel.getGenerateChallengeFailLiveData().getValue()).isNull(); } @Test public void testCheckNewCredentialFromActivityResult_validChooseLock() { final int userId = 108; - final CredentialModel credentialModel = newInvalidChallengeCredentialModel(userId); - mAutoCredentialViewModel.setCredentialModel(credentialModel); + mAutoCredentialViewModel.setCredentialModel(null, + new Intent().putExtras(newInvalidChallengeCredentialIntentExtras(userId))); when(mLockPatternUtils.getActivePasswordQuality(userId)).thenReturn( PASSWORD_QUALITY_SOMETHING); final long gkPwHandle = 6666L; final int newSensorId = 50; final long newChallenge = 60L; - setupGenerateTokenFlow(gkPwHandle, userId, newSensorId, newChallenge); - final Intent intent = new Intent(); - intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, gkPwHandle); + setupGenerateChallenge(userId, newSensorId, newChallenge); + when(mLockPatternUtils.verifyGatekeeperPasswordHandle(gkPwHandle, newChallenge, userId)) + .thenReturn(newGoodCredential(gkPwHandle, new byte[] { 1 })); // Run checkNewCredentialFromActivityResult() + final Intent intent = new Intent().putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, + gkPwHandle); final boolean ret = mAutoCredentialViewModel.checkNewCredentialFromActivityResult(true, new ActivityResult(ChooseLockPattern.RESULT_FINISHED, intent)); assertThat(ret).isTrue(); - assertThat(mAutoCredentialViewModel.getActionLiveData().getValue()).isNull(); - assertThat(credentialModel.getSensorId()).isEqualTo(newSensorId); - assertThat(credentialModel.getChallenge()).isEqualTo(newChallenge); - assertThat(CredentialModel.isValidToken(credentialModel.getToken())).isTrue(); - assertThat(CredentialModel.isValidGkPwHandle(credentialModel.getGkPwHandle())).isFalse(); + assertThat(mAutoCredentialViewModel.getGenerateChallengeFailLiveData().getValue()).isNull(); + final Bundle extras = mAutoCredentialViewModel.getCredentialIntentExtra(); + assertThat(extras.getInt(EXTRA_KEY_SENSOR_ID)).isEqualTo(newSensorId); + assertThat(extras.getLong(EXTRA_KEY_CHALLENGE)).isEqualTo(newChallenge); + assertThat(CredentialModel.isValidToken(extras.getByteArray(EXTRA_KEY_CHALLENGE_TOKEN))) + .isTrue(); + assertThat(CredentialModel.isValidGkPwHandle(extras.getLong(EXTRA_KEY_GK_PW_HANDLE))) + .isFalse(); assertThat(mChallengeGenerator.mCallbackRunCount).isEqualTo(1); } @@ -317,28 +411,33 @@ public class AutoCredentialViewModelTest { @Test public void testCheckNewCredentialFromActivityResult_validConfirmLock() { final int userId = 109; - final CredentialModel credentialModel = newInvalidChallengeCredentialModel(userId); - mAutoCredentialViewModel.setCredentialModel(credentialModel); + mAutoCredentialViewModel.setCredentialModel(null, + new Intent().putExtras(newInvalidChallengeCredentialIntentExtras(userId))); when(mLockPatternUtils.getActivePasswordQuality(userId)).thenReturn( PASSWORD_QUALITY_SOMETHING); final long gkPwHandle = 5555L; final int newSensorId = 80; final long newChallenge = 90L; - setupGenerateTokenFlow(gkPwHandle, userId, newSensorId, newChallenge); - final Intent intent = new Intent(); - intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, gkPwHandle); + setupGenerateChallenge(userId, newSensorId, newChallenge); + when(mLockPatternUtils.verifyGatekeeperPasswordHandle(gkPwHandle, newChallenge, userId)) + .thenReturn(newGoodCredential(gkPwHandle, new byte[] { 1 })); // Run checkNewCredentialFromActivityResult() + final Intent intent = new Intent().putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, + gkPwHandle); final boolean ret = mAutoCredentialViewModel.checkNewCredentialFromActivityResult(false, new ActivityResult(Activity.RESULT_OK, intent)); assertThat(ret).isTrue(); - assertThat(mAutoCredentialViewModel.getActionLiveData().getValue()).isNull(); - assertThat(credentialModel.getSensorId()).isEqualTo(newSensorId); - assertThat(credentialModel.getChallenge()).isEqualTo(newChallenge); - assertThat(CredentialModel.isValidToken(credentialModel.getToken())).isTrue(); - assertThat(CredentialModel.isValidGkPwHandle(credentialModel.getGkPwHandle())).isFalse(); + assertThat(mAutoCredentialViewModel.getGenerateChallengeFailLiveData().getValue()).isNull(); + final Bundle extras = mAutoCredentialViewModel.getCredentialIntentExtra(); + assertThat(extras.getInt(EXTRA_KEY_SENSOR_ID)).isEqualTo(newSensorId); + assertThat(extras.getLong(EXTRA_KEY_CHALLENGE)).isEqualTo(newChallenge); + assertThat(CredentialModel.isValidToken(extras.getByteArray(EXTRA_KEY_CHALLENGE_TOKEN))) + .isTrue(); + assertThat(CredentialModel.isValidGkPwHandle(extras.getLong(EXTRA_KEY_GK_PW_HANDLE))) + .isFalse(); assertThat(mChallengeGenerator.mCallbackRunCount).isEqualTo(1); } @@ -377,4 +476,12 @@ public class AutoCredentialViewModelTest { .setGatekeeperHAT(hat) .build(); } + + private VerifyCredentialResponse newBadCredential(int timeout) { + if (timeout > 0) { + return VerifyCredentialResponse.fromTimeout(timeout); + } else { + return VerifyCredentialResponse.fromError(); + } + } } diff --git a/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollIntroViewModelTest.java b/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollIntroViewModelTest.java index 5069ea1962a..921f1822809 100644 --- a/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollIntroViewModelTest.java +++ b/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollIntroViewModelTest.java @@ -46,6 +46,7 @@ import android.hardware.fingerprint.FingerprintManager; import androidx.annotation.NonNull; import androidx.lifecycle.LifecycleOwner; +import androidx.lifecycle.MutableLiveData; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; @@ -92,6 +93,18 @@ public class FingerprintEnrollIntroViewModelTest { assertThat(status.getEnrollableStatus()).isEqualTo(FINGERPRINT_ENROLLABLE_UNKNOWN); } + @Test + public void testClearActionLiveData() { + final MutableLiveData actionLiveData = + (MutableLiveData) mViewModel.getActionLiveData(); + actionLiveData.postValue(1); + assertThat(actionLiveData.getValue()).isEqualTo(1); + + mViewModel.clearActionLiveData(); + + assertThat(actionLiveData.getValue()).isNull(); + } + @Test public void testGetEnrollmentRequest() { final EnrollmentRequest request = newAllFalseRequest(mApplication); From 68c294df2459794bfeb433673416faa1ad350c56 Mon Sep 17 00:00:00 2001 From: Bonian Chen Date: Tue, 22 Nov 2022 10:39:18 +0000 Subject: [PATCH 06/16] [Settings] Additional route for dismiss activity dialog Previous design dismiss an activity dialog through Intent would lead to a pair of creating and finishing activity. The task switch during the creating and finishing may introduce some side effect to the other apps. This change tried to add additional route to avoid from dismiss through Intent but sending an async close request to that specific dialog (if available). Bug: 236956105 Test: local, auto testing Merged-In: I7a912a3393694155d29614d325796e08598985bf Merged-In: I0a7e0e9826a301f2aa0ca34f40b5570f0e384b4f Change-Id: I88a6c0632c1be906b310a10c154149c319d34759 --- .../settings/sim/SimDialogActivity.java | 13 +++ .../sim/SimDialogProhibitService.java | 89 +++++++++++++++++++ .../settings/sim/SimSelectNotification.java | 5 +- .../sim/SimSelectNotificationTest.java | 25 +++--- 4 files changed, 114 insertions(+), 18 deletions(-) create mode 100644 src/com/android/settings/sim/SimDialogProhibitService.java diff --git a/src/com/android/settings/sim/SimDialogActivity.java b/src/com/android/settings/sim/SimDialogActivity.java index 732277b3d8a..9c4f8f18915 100644 --- a/src/com/android/settings/sim/SimDialogActivity.java +++ b/src/com/android/settings/sim/SimDialogActivity.java @@ -65,6 +65,8 @@ public class SimDialogActivity extends FragmentActivity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + SimDialogProhibitService.supportDismiss(this); + getWindow().addSystemFlags( WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS); showOrUpdateDialog(); @@ -225,4 +227,15 @@ public class SimDialogActivity extends FragmentActivity { } return null; } + + /* + * Force dismiss this Activity. + */ + protected void forceClose() { + if (isFinishing() || isDestroyed()) { + return; + } + Log.d(TAG, "Dismissed by Service"); + finishAndRemoveTask(); + } } diff --git a/src/com/android/settings/sim/SimDialogProhibitService.java b/src/com/android/settings/sim/SimDialogProhibitService.java new file mode 100644 index 00000000000..1558fb3ec0f --- /dev/null +++ b/src/com/android/settings/sim/SimDialogProhibitService.java @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.sim; + +import android.content.Context; +import android.content.Intent; +import android.util.Log; + +import java.lang.ref.WeakReference; +import java.util.concurrent.RejectedExecutionException; + +/** + * A class for routing dismiss dialog request to SimDialogActivity. + */ +public class SimDialogProhibitService { + + private static final String TAG = "SimDialogProhibitService"; + + private static WeakReference sSimDialogActivity; + + /** + * Support the dismiss of {@link SimDialogActivity} (singletone.) + * + * @param activity {@link SimDialogActivity} + */ + public static void supportDismiss(SimDialogActivity activity) { + sSimDialogActivity = new WeakReference(activity); + } + + /** + * Dismiss SimDialogActivity dialog. + * + * @param context is a {@link Context} + */ + public static void dismissDialog(Context context) { + // Dismiss existing dialog. + if (!dismissDialogThroughRunnable()) { + dismissDialogThroughIntent(context); + } + } + + /** + * Dismiss dialog (if there's any). + * + * @return {@code true} when success, {@code false} when failure. + */ + protected static boolean dismissDialogThroughRunnable() { + final SimDialogActivity activity = (sSimDialogActivity == null) ? + null : sSimDialogActivity.get(); + if (activity == null) { + Log.i(TAG, "No SimDialogActivity for dismiss."); + return true; + } + + try { + activity.getMainExecutor().execute(() -> activity.forceClose()); + return true; + } catch (RejectedExecutionException exception) { + Log.w(TAG, "Fail to close SimDialogActivity through executor", exception); + } + return false; + } + + /** + * Dismiss dialog through {@link Intent}. + * + * @param uiContext is {@link Context} for start SimDialogActivity. + */ + protected static void dismissDialogThroughIntent(Context uiContext) { + Intent newIntent = new Intent(uiContext, SimDialogActivity.class); + newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + newIntent.putExtra(SimDialogActivity.DIALOG_TYPE_KEY, SimDialogActivity.PICK_DISMISS); + uiContext.startActivity(newIntent); + } +} diff --git a/src/com/android/settings/sim/SimSelectNotification.java b/src/com/android/settings/sim/SimSelectNotification.java index 5902b926020..9d3f860a014 100644 --- a/src/com/android/settings/sim/SimSelectNotification.java +++ b/src/com/android/settings/sim/SimSelectNotification.java @@ -164,10 +164,7 @@ public class SimSelectNotification extends BroadcastReceiver { // If the dialog type is to dismiss. if (dialogType == EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_DISMISS) { - Intent newIntent = new Intent(context, SimDialogActivity.class); - newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - newIntent.putExtra(SimDialogActivity.DIALOG_TYPE_KEY, PICK_DISMISS); - context.startActivity(newIntent); + SimDialogProhibitService.dismissDialog(context); return; } diff --git a/tests/robotests/src/com/android/settings/sim/SimSelectNotificationTest.java b/tests/robotests/src/com/android/settings/sim/SimSelectNotificationTest.java index 10e291cf2c0..b33e94ba52e 100644 --- a/tests/robotests/src/com/android/settings/sim/SimSelectNotificationTest.java +++ b/tests/robotests/src/com/android/settings/sim/SimSelectNotificationTest.java @@ -42,6 +42,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.clearInvocations; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -74,6 +75,7 @@ import org.robolectric.RobolectricTestRunner; import org.robolectric.annotation.Config; import java.util.Arrays; +import java.util.concurrent.Executor; @RunWith(RobolectricTestRunner.class) @Config(shadows = ShadowAlertDialogCompat.class) @@ -81,6 +83,8 @@ public class SimSelectNotificationTest { @Mock private Context mContext; @Mock + private Executor mExecutor; + @Mock private NotificationManager mNotificationManager; @Mock private TelephonyManager mTelephonyManager; @@ -94,6 +98,8 @@ public class SimSelectNotificationTest { private SubscriptionInfo mSubInfo; @Mock private DisplayMetrics mDisplayMetrics; + @Mock + private SimDialogActivity mActivity; private final String mFakeDisplayName = "fake_display_name"; private final CharSequence mFakeNotificationChannelTitle = "fake_notification_channel_title"; @@ -236,27 +242,18 @@ public class SimSelectNotificationTest { @Test public void onReceivePrimarySubListChange_WithDismissExtra_shouldDismiss() { + doReturn(mExecutor).when(mActivity).getMainExecutor(); + SimDialogProhibitService.supportDismiss(mActivity); + Intent intent = new Intent(TelephonyManager.ACTION_PRIMARY_SUBSCRIPTION_LIST_CHANGED); intent.putExtra(EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE, - EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_DATA); + EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_DISMISS); mSimSelectNotification.onReceive(mContext, intent); clearInvocations(mContext); // Dismiss. - intent.putExtra(EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE, - EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_DISMISS); - mSimSelectNotification.onReceive(mContext, intent); - ArgumentCaptor intentCaptor = ArgumentCaptor.forClass(Intent.class); - verify(mContext).startActivity(intentCaptor.capture()); - Intent capturedIntent = intentCaptor.getValue(); - assertThat(capturedIntent).isNotNull(); - assertThat(capturedIntent.getComponent().getClassName()).isEqualTo( - SimDialogActivity.class.getName()); - assertThat(capturedIntent.getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK) - .isNotEqualTo(0); - assertThat(capturedIntent.getIntExtra(SimDialogActivity.DIALOG_TYPE_KEY, INVALID_PICK)) - .isEqualTo(PICK_DISMISS); + verify(mExecutor).execute(any()); } @Test public void onReceivePrimarySubListChange_DualCdmaWarning_notificationShouldSend() { From fa589ca6f1e489fbf0da1a18b07f9be2b18d7b64 Mon Sep 17 00:00:00 2001 From: SongFerngWang Date: Tue, 22 Nov 2022 18:58:52 +0800 Subject: [PATCH 07/16] Remove "Backup Calling" button from Settings UI Remove "Backup Calling" button from Settings UI, keep it always enabled. Bug: 253698238 Test: build pass Change-Id: Iff2665829e559ab7dce20e58a50ca75b8dcd6f83 --- res/values/strings.xml | 3 +++ res/xml/mobile_network_settings.xml | 8 -------- res/xml/network_provider_calls_sms.xml | 8 -------- .../network/NetworkProviderCallsSmsFragment.java | 10 ---------- .../telephony/BackupCallingPreferenceController.java | 1 + .../network/telephony/MobileNetworkSettings.java | 5 ----- .../telephony/NetworkProviderBackupCallingGroup.java | 1 + ...tworkProviderBackupCallingPreferenceController.java | 1 + .../BackupCallingPreferenceControllerTest.java | 5 +++++ .../NetworkProviderBackupCallingGroupTest.java | 8 ++++++++ 10 files changed, 19 insertions(+), 31 deletions(-) diff --git a/res/values/strings.xml b/res/values/strings.xml index 2dc4e655b92..91587a90633 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -10510,12 +10510,15 @@ Use Wi\u2011Fi for calls to improve quality + Backup calling + If %1$s is unavailable or roaming, use your mobile data SIM for %1$s calls. + backup calling diff --git a/res/xml/mobile_network_settings.xml b/res/xml/mobile_network_settings.xml index 96eacbc7349..22434b1ddc2 100644 --- a/res/xml/mobile_network_settings.xml +++ b/res/xml/mobile_network_settings.xml @@ -183,14 +183,6 @@ android:persistent="true" settings:controller="com.android.settings.network.telephony.VideoCallingPreferenceController"/> - - - - diff --git a/src/com/android/settings/network/NetworkProviderCallsSmsFragment.java b/src/com/android/settings/network/NetworkProviderCallsSmsFragment.java index ab247f1a87c..772db452fcf 100644 --- a/src/com/android/settings/network/NetworkProviderCallsSmsFragment.java +++ b/src/com/android/settings/network/NetworkProviderCallsSmsFragment.java @@ -26,7 +26,6 @@ import com.android.settings.R; import com.android.settings.Utils; import com.android.settings.dashboard.DashboardFragment; import com.android.settings.network.telephony.CallsDefaultSubscriptionController; -import com.android.settings.network.telephony.NetworkProviderBackupCallingPreferenceController; import com.android.settings.network.telephony.NetworkProviderWifiCallingPreferenceController; import com.android.settings.network.telephony.SmsDefaultSubscriptionController; import com.android.settings.search.BaseSearchIndexProvider; @@ -42,9 +41,6 @@ public class NetworkProviderCallsSmsFragment extends DashboardFragment { static final String LOG_TAG = "NetworkProviderCallsSmsFragment"; @VisibleForTesting static final String KEY_PREFERENCE_CATEGORY_CALLING = "provider_model_calling_category"; - @VisibleForTesting - static final String KEY_PREFERENCE_CATEGORY_BACKUP_CALLING = - "provider_model_backup_calling_category"; @VisibleForTesting static final String KEY_PREFERENCE_CALLS= "provider_model_calls_preference"; @@ -67,12 +63,6 @@ public class NetworkProviderCallsSmsFragment extends DashboardFragment { mNetworkProviderWifiCallingPreferenceController.init(getSettingsLifecycle()); controllers.add(mNetworkProviderWifiCallingPreferenceController); - NetworkProviderBackupCallingPreferenceController backupCallingPrefCtrl = - new NetworkProviderBackupCallingPreferenceController(context, - KEY_PREFERENCE_CATEGORY_BACKUP_CALLING); - backupCallingPrefCtrl.init(getSettingsLifecycle()); - controllers.add(backupCallingPrefCtrl); - return controllers; } diff --git a/src/com/android/settings/network/telephony/BackupCallingPreferenceController.java b/src/com/android/settings/network/telephony/BackupCallingPreferenceController.java index 4f64399f524..3db6dfe87e8 100644 --- a/src/com/android/settings/network/telephony/BackupCallingPreferenceController.java +++ b/src/com/android/settings/network/telephony/BackupCallingPreferenceController.java @@ -38,6 +38,7 @@ import java.util.Objects; /** * Preference controller for "Backup Calling" + * Deprecated ToDo: b/260059444 remove it next version **/ public class BackupCallingPreferenceController extends TelephonyTogglePreferenceController { diff --git a/src/com/android/settings/network/telephony/MobileNetworkSettings.java b/src/com/android/settings/network/telephony/MobileNetworkSettings.java index ae83c43c5bc..df7fd839e68 100644 --- a/src/com/android/settings/network/telephony/MobileNetworkSettings.java +++ b/src/com/android/settings/network/telephony/MobileNetworkSettings.java @@ -269,11 +269,6 @@ public class MobileNetworkSettings extends AbstractMobileNetworkSettings impleme final VideoCallingPreferenceController videoCallingPreferenceController = use(VideoCallingPreferenceController.class).init(mSubId); - final BackupCallingPreferenceController crossSimCallingPreferenceController = - use(BackupCallingPreferenceController.class).init(mSubId); - use(CallingPreferenceCategoryController.class).setChildren( - Arrays.asList(wifiCallingPreferenceController, videoCallingPreferenceController, - crossSimCallingPreferenceController)); use(Enhanced4gLtePreferenceController.class).init(mSubId) .addListener(videoCallingPreferenceController); use(Enhanced4gCallingPreferenceController.class).init(mSubId) diff --git a/src/com/android/settings/network/telephony/NetworkProviderBackupCallingGroup.java b/src/com/android/settings/network/telephony/NetworkProviderBackupCallingGroup.java index 58dd18f2c62..3659f651336 100644 --- a/src/com/android/settings/network/telephony/NetworkProviderBackupCallingGroup.java +++ b/src/com/android/settings/network/telephony/NetworkProviderBackupCallingGroup.java @@ -49,6 +49,7 @@ import java.util.Map; /** * Preference controller for "Backup Calling" + * Deprecated ToDo: b/260059444 remove it next version **/ public class NetworkProviderBackupCallingGroup extends TelephonyTogglePreferenceController implements LifecycleObserver, diff --git a/src/com/android/settings/network/telephony/NetworkProviderBackupCallingPreferenceController.java b/src/com/android/settings/network/telephony/NetworkProviderBackupCallingPreferenceController.java index 5c336efc507..c10bfb83d7c 100644 --- a/src/com/android/settings/network/telephony/NetworkProviderBackupCallingPreferenceController.java +++ b/src/com/android/settings/network/telephony/NetworkProviderBackupCallingPreferenceController.java @@ -32,6 +32,7 @@ import java.util.List; /** * Preference controller for "Backup Calling" summary list + * Deprecated ToDo: b/260059444 remove it next version */ public class NetworkProviderBackupCallingPreferenceController extends BasePreferenceController implements LifecycleObserver { diff --git a/tests/unit/src/com/android/settings/network/telephony/BackupCallingPreferenceControllerTest.java b/tests/unit/src/com/android/settings/network/telephony/BackupCallingPreferenceControllerTest.java index 4e110f0d018..34d7c925b40 100644 --- a/tests/unit/src/com/android/settings/network/telephony/BackupCallingPreferenceControllerTest.java +++ b/tests/unit/src/com/android/settings/network/telephony/BackupCallingPreferenceControllerTest.java @@ -28,9 +28,13 @@ import androidx.test.ext.junit.runners.AndroidJUnit4; import com.android.settings.core.BasePreferenceController; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; +/** + * Deprecated ToDo: b/260059444 remove it next version + */ @RunWith(AndroidJUnit4.class) public class BackupCallingPreferenceControllerTest { private static final int SUB_ID = 2; @@ -47,6 +51,7 @@ public class BackupCallingPreferenceControllerTest { } @Test + @Ignore public void controller_isUnavailable() { assertThat(mController.getAvailabilityStatus()) .isEqualTo(BasePreferenceController.CONDITIONALLY_UNAVAILABLE); diff --git a/tests/unit/src/com/android/settings/network/telephony/NetworkProviderBackupCallingGroupTest.java b/tests/unit/src/com/android/settings/network/telephony/NetworkProviderBackupCallingGroupTest.java index a5717ef519a..09f020085f3 100644 --- a/tests/unit/src/com/android/settings/network/telephony/NetworkProviderBackupCallingGroupTest.java +++ b/tests/unit/src/com/android/settings/network/telephony/NetworkProviderBackupCallingGroupTest.java @@ -40,6 +40,7 @@ import com.android.settings.network.CarrierConfigCache; import com.android.settingslib.core.lifecycle.Lifecycle; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; @@ -47,6 +48,9 @@ import org.mockito.MockitoAnnotations; import java.util.List; +/** + * Deprecated ToDo: b/260059444 remove it next version + */ @RunWith(AndroidJUnit4.class) public class NetworkProviderBackupCallingGroupTest { @@ -133,12 +137,14 @@ public class NetworkProviderBackupCallingGroupTest { } @Test + @Ignore public void shouldShowBackupCallingForSub_invalidSubId_returnFalse() { assertThat(mNetworkProviderBackupCallingGroup.hasBackupCallingFeature( SubscriptionManager.INVALID_SUBSCRIPTION_ID)).isEqualTo(false); } @Test + @Ignore public void shouldShowBackupCallingForSub_carrierConfigIsUnavailable_returnFalse() { mCarrierConfig.putBoolean(CarrierConfigManager.KEY_CARRIER_CROSS_SIM_IMS_AVAILABLE_BOOL, false); @@ -148,6 +154,7 @@ public class NetworkProviderBackupCallingGroupTest { } @Test + @Ignore public void shouldShowBackupCallingForSub_crossSimDisabled_returnFalse() { doReturn(false).when(mNetworkProviderBackupCallingGroup).isCrossSimEnabledByPlatform( @@ -158,6 +165,7 @@ public class NetworkProviderBackupCallingGroupTest { } @Test + @Ignore public void shouldBackupCallingForSub_crossSimEnabled_returnTrue() { doReturn(true).when(mNetworkProviderBackupCallingGroup).isCrossSimEnabledByPlatform( mContext, SUB_ID_1); From ebc354ab687ff3217910e206b3d2d4765e940e56 Mon Sep 17 00:00:00 2001 From: Bill Yi Date: Tue, 22 Nov 2022 15:53:52 -0800 Subject: [PATCH 08/16] Import translations. DO NOT MERGE ANYWHERE Auto-generated-cl: translation import Change-Id: Ib53e903156f20220886651eca3ee1b7958cce2cc --- res/values-af/arrays.xml | 8 +++++--- res/values-ar/arrays.xml | 10 ++++++---- res/values-as/arrays.xml | 8 +++++--- res/values-az/arrays.xml | 8 +++++--- res/values-b+sr+Latn/arrays.xml | 8 +++++--- res/values-be/arrays.xml | 8 +++++--- res/values-bg/arrays.xml | 8 +++++--- res/values-bn/arrays.xml | 8 +++++--- res/values-bs/arrays.xml | 8 +++++--- res/values-ca/arrays.xml | 8 +++++--- res/values-cs/arrays.xml | 8 +++++--- res/values-da/arrays.xml | 8 +++++--- res/values-el/arrays.xml | 8 +++++--- res/values-en-rAU/arrays.xml | 8 +++++--- res/values-en-rGB/arrays.xml | 8 +++++--- res/values-en-rIN/arrays.xml | 8 +++++--- res/values-es-rUS/arrays.xml | 8 +++++--- res/values-es/arrays.xml | 8 +++++--- res/values-et/arrays.xml | 8 +++++--- res/values-eu/arrays.xml | 8 +++++--- res/values-fa/arrays.xml | 8 +++++--- res/values-fi/arrays.xml | 8 +++++--- res/values-fr-rCA/arrays.xml | 8 +++++--- res/values-fr/arrays.xml | 8 +++++--- res/values-gl/arrays.xml | 8 +++++--- res/values-gu/arrays.xml | 8 +++++--- res/values-hi/arrays.xml | 8 +++++--- res/values-hr/arrays.xml | 8 +++++--- res/values-hu/arrays.xml | 8 +++++--- res/values-hy/arrays.xml | 8 +++++--- res/values-in/arrays.xml | 8 +++++--- res/values-is/arrays.xml | 8 +++++--- res/values-it/arrays.xml | 8 +++++--- res/values-iw/arrays.xml | 8 +++++--- res/values-ja/arrays.xml | 8 +++++--- res/values-ka/arrays.xml | 8 +++++--- res/values-kk/arrays.xml | 8 +++++--- res/values-km/arrays.xml | 8 +++++--- res/values-kn/arrays.xml | 8 +++++--- res/values-ko/arrays.xml | 8 +++++--- res/values-ky/arrays.xml | 8 +++++--- res/values-lo/arrays.xml | 8 +++++--- res/values-lt/arrays.xml | 8 +++++--- res/values-mk/arrays.xml | 8 +++++--- res/values-ml/arrays.xml | 8 +++++--- res/values-mn/arrays.xml | 8 +++++--- res/values-mr/arrays.xml | 8 +++++--- res/values-ms/arrays.xml | 8 +++++--- res/values-my/arrays.xml | 8 +++++--- res/values-nb/arrays.xml | 8 +++++--- res/values-ne/arrays.xml | 8 +++++--- res/values-nl/arrays.xml | 8 +++++--- res/values-or/arrays.xml | 8 +++++--- res/values-pa/arrays.xml | 8 +++++--- res/values-pl/arrays.xml | 8 +++++--- res/values-pt-rBR/arrays.xml | 8 +++++--- res/values-pt-rPT/arrays.xml | 8 +++++--- res/values-pt/arrays.xml | 8 +++++--- res/values-ro/arrays.xml | 8 +++++--- res/values-ru/arrays.xml | 8 +++++--- res/values-si/arrays.xml | 8 +++++--- res/values-sk/arrays.xml | 8 +++++--- res/values-sl/arrays.xml | 8 +++++--- res/values-sq/arrays.xml | 8 +++++--- res/values-sr/arrays.xml | 8 +++++--- res/values-sv/arrays.xml | 8 +++++--- res/values-sw/arrays.xml | 8 +++++--- res/values-ta/arrays.xml | 8 +++++--- res/values-te/arrays.xml | 8 +++++--- res/values-th/arrays.xml | 8 +++++--- res/values-tl/arrays.xml | 8 +++++--- res/values-tr/arrays.xml | 8 +++++--- res/values-uk/arrays.xml | 8 +++++--- res/values-ur/arrays.xml | 8 +++++--- res/values-uz/arrays.xml | 8 +++++--- res/values-vi/arrays.xml | 8 +++++--- res/values-zh-rCN/arrays.xml | 8 +++++--- res/values-zh-rHK/arrays.xml | 8 +++++--- res/values-zh-rTW/arrays.xml | 8 +++++--- res/values-zu/arrays.xml | 8 +++++--- 80 files changed, 401 insertions(+), 241 deletions(-) diff --git a/res/values-af/arrays.xml b/res/values-af/arrays.xml index 989fc52caa0..ec180835bd7 100644 --- a/res/values-af/arrays.xml +++ b/res/values-af/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "Nooit" + "Ná 1 minuut" + "Ná 5 minute" + diff --git a/res/values-ar/arrays.xml b/res/values-ar/arrays.xml index 6b1e7c2f684..89732d5186c 100644 --- a/res/values-ar/arrays.xml +++ b/res/values-ar/arrays.xml @@ -444,7 +444,7 @@ "غير متصل" - "جار التهيئة..." + "جارٍ التهيئة..." "جارٍ الاتصال..." "متصلة" "المهلة" @@ -586,7 +586,9 @@ "0" "1" - - - + + "أبدًا" + "بعد دقيقة واحدة" + "بعد 5 دقائق" + diff --git a/res/values-as/arrays.xml b/res/values-as/arrays.xml index de72b394597..39bd9b5e323 100644 --- a/res/values-as/arrays.xml +++ b/res/values-as/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "কেতিয়াও নহয়" + "১ মিনিটৰ পাছত" + "৫ মিনিটৰ পাছত" + diff --git a/res/values-az/arrays.xml b/res/values-az/arrays.xml index d7438fb3db1..7d5de04ad35 100644 --- a/res/values-az/arrays.xml +++ b/res/values-az/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "Heç vaxt" + "1 dəqiqə sonra" + "5 dəqiqə sonra" + diff --git a/res/values-b+sr+Latn/arrays.xml b/res/values-b+sr+Latn/arrays.xml index 5920c215c43..f3d5e888afb 100644 --- a/res/values-b+sr+Latn/arrays.xml +++ b/res/values-b+sr+Latn/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "Nikad" + "Posle 1 minuta" + "Posle 5 minuta" + diff --git a/res/values-be/arrays.xml b/res/values-be/arrays.xml index 266e1a39158..71a7ab988a7 100644 --- a/res/values-be/arrays.xml +++ b/res/values-be/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "Ніколі" + "Праз 1 хвіліну" + "Праз 5 хвілін" + diff --git a/res/values-bg/arrays.xml b/res/values-bg/arrays.xml index 76a7c9b1141..6e7ad8fd283 100644 --- a/res/values-bg/arrays.xml +++ b/res/values-bg/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "Никога" + "След 1 минута" + "След 5 минути" + diff --git a/res/values-bn/arrays.xml b/res/values-bn/arrays.xml index 10ce151406e..d33f6a48992 100644 --- a/res/values-bn/arrays.xml +++ b/res/values-bn/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "কখনওই নয়" + "১ মিনিট পর" + "৫ মিনিট পর" + diff --git a/res/values-bs/arrays.xml b/res/values-bs/arrays.xml index 2d510add11a..c9004be24c7 100644 --- a/res/values-bs/arrays.xml +++ b/res/values-bs/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "Nikada" + "Nakon 1 min" + "Nakon 5 min" + diff --git a/res/values-ca/arrays.xml b/res/values-ca/arrays.xml index 6c81342a3bb..40afb0d5dcd 100644 --- a/res/values-ca/arrays.xml +++ b/res/values-ca/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "Mai" + "Després d\'1 minut" + "Després de 5 minuts" + diff --git a/res/values-cs/arrays.xml b/res/values-cs/arrays.xml index 148be929828..9ab3e8d5ce7 100644 --- a/res/values-cs/arrays.xml +++ b/res/values-cs/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "Nikdy" + "Po 1 minutě" + "Po 5 minutách" + diff --git a/res/values-da/arrays.xml b/res/values-da/arrays.xml index 0fc8c8fb430..057c0a32532 100644 --- a/res/values-da/arrays.xml +++ b/res/values-da/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "Aldrig" + "Efter 1 minut" + "Efter 5 minutter" + diff --git a/res/values-el/arrays.xml b/res/values-el/arrays.xml index 68ef0417b25..eddc84005b3 100644 --- a/res/values-el/arrays.xml +++ b/res/values-el/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "Ποτέ" + "Μετά από 1 λεπτό" + "Μετά από 5 λεπτά" + diff --git a/res/values-en-rAU/arrays.xml b/res/values-en-rAU/arrays.xml index 278609d20f1..f3fc33e7987 100644 --- a/res/values-en-rAU/arrays.xml +++ b/res/values-en-rAU/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "Never" + "After one minute" + "After five minutes" + diff --git a/res/values-en-rGB/arrays.xml b/res/values-en-rGB/arrays.xml index 278609d20f1..f3fc33e7987 100644 --- a/res/values-en-rGB/arrays.xml +++ b/res/values-en-rGB/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "Never" + "After one minute" + "After five minutes" + diff --git a/res/values-en-rIN/arrays.xml b/res/values-en-rIN/arrays.xml index 278609d20f1..f3fc33e7987 100644 --- a/res/values-en-rIN/arrays.xml +++ b/res/values-en-rIN/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "Never" + "After one minute" + "After five minutes" + diff --git a/res/values-es-rUS/arrays.xml b/res/values-es-rUS/arrays.xml index b06eb9a2014..594244ff722 100644 --- a/res/values-es-rUS/arrays.xml +++ b/res/values-es-rUS/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "Nunca" + "Después de 1 minuto" + "Después de 5 minutos" + diff --git a/res/values-es/arrays.xml b/res/values-es/arrays.xml index 70a6f859a1a..25f95b419b7 100644 --- a/res/values-es/arrays.xml +++ b/res/values-es/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "Nunca" + "Tras 1 minuto" + "Tras 5 minutos" + diff --git a/res/values-et/arrays.xml b/res/values-et/arrays.xml index fa0703ee6ab..facb2237f75 100644 --- a/res/values-et/arrays.xml +++ b/res/values-et/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "Mitte kunagi" + "1 minuti pärast" + "5 minuti pärast" + diff --git a/res/values-eu/arrays.xml b/res/values-eu/arrays.xml index ea682bc82d6..3528495d59a 100644 --- a/res/values-eu/arrays.xml +++ b/res/values-eu/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "Inoiz ez" + "Minutu bat igarotakoan" + "Bost minutu igarotakoan" + diff --git a/res/values-fa/arrays.xml b/res/values-fa/arrays.xml index 8a140b46212..691e19f35ef 100644 --- a/res/values-fa/arrays.xml +++ b/res/values-fa/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "هرگز" + "پس‌از ۱ دقیقه" + "پس‌از ۵ دقیقه" + diff --git a/res/values-fi/arrays.xml b/res/values-fi/arrays.xml index 7b252473f73..934d586c5b7 100644 --- a/res/values-fi/arrays.xml +++ b/res/values-fi/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "Ei koskaan" + "1 minuutin kuluttua" + "5 minuutin kuluttua" + diff --git a/res/values-fr-rCA/arrays.xml b/res/values-fr-rCA/arrays.xml index 379ba573608..3bddb712fde 100644 --- a/res/values-fr-rCA/arrays.xml +++ b/res/values-fr-rCA/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "Jamais" + "Après 1 minute" + "Après 5 minutes" + diff --git a/res/values-fr/arrays.xml b/res/values-fr/arrays.xml index 725c353b304..04d59e93a7b 100644 --- a/res/values-fr/arrays.xml +++ b/res/values-fr/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "Jamais" + "Après 1 minute" + "Après 5 minutes" + diff --git a/res/values-gl/arrays.xml b/res/values-gl/arrays.xml index 95bcb3b38b6..28114ad5a73 100644 --- a/res/values-gl/arrays.xml +++ b/res/values-gl/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "Nunca" + "Tras 1 minuto" + "Tras 5 minutos" + diff --git a/res/values-gu/arrays.xml b/res/values-gu/arrays.xml index 295610e7996..259b2bbbf10 100644 --- a/res/values-gu/arrays.xml +++ b/res/values-gu/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "ક્યારેય નહીં" + "1 મિનિટ પછી" + "5 મિનિટ પછી" + diff --git a/res/values-hi/arrays.xml b/res/values-hi/arrays.xml index 247ab1e55a9..9636a39c243 100644 --- a/res/values-hi/arrays.xml +++ b/res/values-hi/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "कभी नहीं" + "एक मिनट बाद" + "पांच मिनट बाद" + diff --git a/res/values-hr/arrays.xml b/res/values-hr/arrays.xml index 1fa3c0d9182..f062cc621b0 100644 --- a/res/values-hr/arrays.xml +++ b/res/values-hr/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "Nikad" + "Nakon 1 minute" + "Nakon 5 minuta" + diff --git a/res/values-hu/arrays.xml b/res/values-hu/arrays.xml index 22984c01cf4..8edb713adc5 100644 --- a/res/values-hu/arrays.xml +++ b/res/values-hu/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "Soha" + "1 perc után" + "5 perc után" + diff --git a/res/values-hy/arrays.xml b/res/values-hy/arrays.xml index 9bd9dfdac81..d5a8506df45 100644 --- a/res/values-hy/arrays.xml +++ b/res/values-hy/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "Երբեք" + "1 րոպեից" + "5 րոպեից" + diff --git a/res/values-in/arrays.xml b/res/values-in/arrays.xml index 2a529139f65..5b446f3c06d 100644 --- a/res/values-in/arrays.xml +++ b/res/values-in/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "Tidak pernah" + "Setelah 1 menit" + "Setelah 5 menit" + diff --git a/res/values-is/arrays.xml b/res/values-is/arrays.xml index 0ca13877cc6..b2fe2806d96 100644 --- a/res/values-is/arrays.xml +++ b/res/values-is/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "Aldrei" + "Eftir 1 mínútu" + "Eftir 5 mínútur" + diff --git a/res/values-it/arrays.xml b/res/values-it/arrays.xml index b2fbdbf2bb7..15e4cebc87c 100644 --- a/res/values-it/arrays.xml +++ b/res/values-it/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "Mai" + "Dopo 1 minuto" + "Dopo 5 minuti" + diff --git a/res/values-iw/arrays.xml b/res/values-iw/arrays.xml index 45ca1800470..3003499e59d 100644 --- a/res/values-iw/arrays.xml +++ b/res/values-iw/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "אף פעם" + "לאחר דקה אחת" + "לאחר 5 דקות" + diff --git a/res/values-ja/arrays.xml b/res/values-ja/arrays.xml index 57368f3fede..9be2520ac50 100644 --- a/res/values-ja/arrays.xml +++ b/res/values-ja/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "なし" + "1 分後" + "5 分後" + diff --git a/res/values-ka/arrays.xml b/res/values-ka/arrays.xml index 011a3b3a7da..373493ef4e3 100644 --- a/res/values-ka/arrays.xml +++ b/res/values-ka/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "არასოდეს" + "1 წუთის შემდეგ" + "5 წუთის შემდეგ" + diff --git a/res/values-kk/arrays.xml b/res/values-kk/arrays.xml index 203efd872a4..e49dd37057e 100644 --- a/res/values-kk/arrays.xml +++ b/res/values-kk/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "Ешқашан" + "1 минуттан кейін" + "5 минуттан кейін" + diff --git a/res/values-km/arrays.xml b/res/values-km/arrays.xml index f10739677a8..f5381dc6b5b 100644 --- a/res/values-km/arrays.xml +++ b/res/values-km/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "កុំឱ្យសោះ" + "បន្ទាប់ពី 1 នាទី" + "បន្ទាប់ពី 5 នាទី" + diff --git a/res/values-kn/arrays.xml b/res/values-kn/arrays.xml index ecbfbf8053a..4e1070d446d 100644 --- a/res/values-kn/arrays.xml +++ b/res/values-kn/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "ಎಂದಿಗೂ ಬೇಡ" + "1 ನಿಮಿಷದ ನಂತರ" + "5 ನಿಮಿಷಗಳ ನಂತರ" + diff --git a/res/values-ko/arrays.xml b/res/values-ko/arrays.xml index d2e9a0cd4df..13371c3a5f3 100644 --- a/res/values-ko/arrays.xml +++ b/res/values-ko/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "사용 안함" + "1분 후" + "5분 후" + diff --git a/res/values-ky/arrays.xml b/res/values-ky/arrays.xml index 999fb89d59a..7feb770a523 100644 --- a/res/values-ky/arrays.xml +++ b/res/values-ky/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "Эч качан" + "1 мүнөттөн кийин" + "5 мүнөттөн кийин" + diff --git a/res/values-lo/arrays.xml b/res/values-lo/arrays.xml index 4745c9dbcda..84c8ca1b813 100644 --- a/res/values-lo/arrays.xml +++ b/res/values-lo/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "ບໍ່ເດັດຂາດ" + "ຫຼັງຈາກ 1 ນາທີ" + "ຫຼັງຈາກ 5 ນາທີ" + diff --git a/res/values-lt/arrays.xml b/res/values-lt/arrays.xml index efaa519925a..8d1a0f9066f 100644 --- a/res/values-lt/arrays.xml +++ b/res/values-lt/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "Niekada" + "Po vienos minutės" + "Po penkių minučių" + diff --git a/res/values-mk/arrays.xml b/res/values-mk/arrays.xml index af5aaf4c96c..8a68560cd5d 100644 --- a/res/values-mk/arrays.xml +++ b/res/values-mk/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "Никогаш" + "По 1 минута" + "По 5 минути" + diff --git a/res/values-ml/arrays.xml b/res/values-ml/arrays.xml index 771c191113d..b8f639e6880 100644 --- a/res/values-ml/arrays.xml +++ b/res/values-ml/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "ഒരിക്കലും വേണ്ട" + "ഒരു മിനിറ്റിന് ശേഷം" + "5 മിനിറ്റിന് ശേഷം" + diff --git a/res/values-mn/arrays.xml b/res/values-mn/arrays.xml index aed4998d076..c1b2b5d0c8e 100644 --- a/res/values-mn/arrays.xml +++ b/res/values-mn/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "Огт үгүй" + "1 минутын дараа" + "5 минутын дараа" + diff --git a/res/values-mr/arrays.xml b/res/values-mr/arrays.xml index 0890f2e2e0d..4418001e072 100644 --- a/res/values-mr/arrays.xml +++ b/res/values-mr/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "कधीही नाही" + "एका मिनिटानंतर" + "पाच मिनिटांनंतर" + diff --git a/res/values-ms/arrays.xml b/res/values-ms/arrays.xml index c1be80692c7..243c5aa2d45 100644 --- a/res/values-ms/arrays.xml +++ b/res/values-ms/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "Tidak sekali-kali" + "Selepas 1 minit" + "Selepas 5 minit" + diff --git a/res/values-my/arrays.xml b/res/values-my/arrays.xml index ea117d514ec..3cf3a613184 100644 --- a/res/values-my/arrays.xml +++ b/res/values-my/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "မည်သည့်အခါမှ" + "၁ မိနစ်နောက်ပိုင်း" + "၅ မိနစ်နောက်ပိုင်း" + diff --git a/res/values-nb/arrays.xml b/res/values-nb/arrays.xml index 62513c98d36..8dcc6d8fe56 100644 --- a/res/values-nb/arrays.xml +++ b/res/values-nb/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "Aldri" + "Etter 1 minutt" + "Etter 5 minutter" + diff --git a/res/values-ne/arrays.xml b/res/values-ne/arrays.xml index aa844a32973..65b8415478d 100644 --- a/res/values-ne/arrays.xml +++ b/res/values-ne/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "कहिल्यै पनि होइन" + "१ मिनेटपछि" + "५ मिनेटपछि" + diff --git a/res/values-nl/arrays.xml b/res/values-nl/arrays.xml index e79a3e273c4..e39bbcca700 100644 --- a/res/values-nl/arrays.xml +++ b/res/values-nl/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "Nooit" + "Na 1 minuut" + "Na 5 minuten" + diff --git a/res/values-or/arrays.xml b/res/values-or/arrays.xml index a36a11a32a9..78e992cd255 100644 --- a/res/values-or/arrays.xml +++ b/res/values-or/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "କେବେ ବି ନୁହେଁ" + "1 ମିନିଟ ପରେ" + "5 ମିନିଟ ପରେ" + diff --git a/res/values-pa/arrays.xml b/res/values-pa/arrays.xml index 8d01382e7ba..4124df5429c 100644 --- a/res/values-pa/arrays.xml +++ b/res/values-pa/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "ਕਦੇ ਵੀ ਨਹੀਂ" + "1 ਮਿੰਟ ਬਾਅਦ" + "5 ਮਿੰਟਾਂ ਬਾਅਦ" + diff --git a/res/values-pl/arrays.xml b/res/values-pl/arrays.xml index c591eb3bc33..f7681b611e8 100644 --- a/res/values-pl/arrays.xml +++ b/res/values-pl/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "Nigdy" + "Po minucie" + "Po 5 minutach" + diff --git a/res/values-pt-rBR/arrays.xml b/res/values-pt-rBR/arrays.xml index 6d6a91bf1e1..e0bc5980270 100644 --- a/res/values-pt-rBR/arrays.xml +++ b/res/values-pt-rBR/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "Nunca" + "Depois de um minuto" + "Depois de cinco minutos" + diff --git a/res/values-pt-rPT/arrays.xml b/res/values-pt-rPT/arrays.xml index 0f8dccd1c99..c4b33218a6f 100644 --- a/res/values-pt-rPT/arrays.xml +++ b/res/values-pt-rPT/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "Nunca" + "Após 1 minuto" + "Após 5 minutos" + diff --git a/res/values-pt/arrays.xml b/res/values-pt/arrays.xml index 6d6a91bf1e1..e0bc5980270 100644 --- a/res/values-pt/arrays.xml +++ b/res/values-pt/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "Nunca" + "Depois de um minuto" + "Depois de cinco minutos" + diff --git a/res/values-ro/arrays.xml b/res/values-ro/arrays.xml index 9bfbc8240d6..3e08df23ca8 100644 --- a/res/values-ro/arrays.xml +++ b/res/values-ro/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "Niciodată" + "După un minut" + "După cinci minute" + diff --git a/res/values-ru/arrays.xml b/res/values-ru/arrays.xml index 4fd838a656b..43e84a63b42 100644 --- a/res/values-ru/arrays.xml +++ b/res/values-ru/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "Никогда" + "Через 1 минуту" + "Через 5 минут" + diff --git a/res/values-si/arrays.xml b/res/values-si/arrays.xml index ecb3b12ffdb..3fc127b461b 100644 --- a/res/values-si/arrays.xml +++ b/res/values-si/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "කවදාවත් නෑ" + "මිනිත්තු 1කට පසුව" + "මිනිත්තු 5කට පසුව" + diff --git a/res/values-sk/arrays.xml b/res/values-sk/arrays.xml index e671d471179..6df77d6dbb5 100644 --- a/res/values-sk/arrays.xml +++ b/res/values-sk/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "Nikdy" + "Po 1 minúte" + "Po 5 minútach" + diff --git a/res/values-sl/arrays.xml b/res/values-sl/arrays.xml index f101e38e1c7..92c70793558 100644 --- a/res/values-sl/arrays.xml +++ b/res/values-sl/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "Nikoli" + "Po 1 minuti" + "Po 5 minutah" + diff --git a/res/values-sq/arrays.xml b/res/values-sq/arrays.xml index 95ae5c22c18..f622ec70d34 100644 --- a/res/values-sq/arrays.xml +++ b/res/values-sq/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "Asnjëherë" + "Pas 1 minute" + "Pas 5 minutash" + diff --git a/res/values-sr/arrays.xml b/res/values-sr/arrays.xml index 498a4473b05..f8db0f6659e 100644 --- a/res/values-sr/arrays.xml +++ b/res/values-sr/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "Никад" + "После 1 минута" + "После 5 минута" + diff --git a/res/values-sv/arrays.xml b/res/values-sv/arrays.xml index a93791a3e47..13b9adcb918 100644 --- a/res/values-sv/arrays.xml +++ b/res/values-sv/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "Aldrig" + "Efter 1 minut" + "Efter 5 minuter" + diff --git a/res/values-sw/arrays.xml b/res/values-sw/arrays.xml index dfaa698307f..b651a656795 100644 --- a/res/values-sw/arrays.xml +++ b/res/values-sw/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "Usiishe kamwe" + "Baada ya dakika 1" + "Baada ya dakika 5" + diff --git a/res/values-ta/arrays.xml b/res/values-ta/arrays.xml index 368e69c86fb..16c5eb96ee2 100644 --- a/res/values-ta/arrays.xml +++ b/res/values-ta/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "ஒருபோதுமில்லை" + "1 நிமிடத்திற்குப் பிறகு" + "5 நிமிடங்களுக்குப் பிறகு" + diff --git a/res/values-te/arrays.xml b/res/values-te/arrays.xml index aa5fb998d7c..e8ae5faacb9 100644 --- a/res/values-te/arrays.xml +++ b/res/values-te/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "ఎప్పుడూ వద్దు" + "1 నిమిషం తర్వాత" + "5 నిమిషాల తర్వాత" + diff --git a/res/values-th/arrays.xml b/res/values-th/arrays.xml index 67567b0714c..31399899bd7 100644 --- a/res/values-th/arrays.xml +++ b/res/values-th/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "ไม่เลย" + "หลังจาก 1 นาที" + "หลังจาก 5 นาที" + diff --git a/res/values-tl/arrays.xml b/res/values-tl/arrays.xml index 9dd7a7402d5..354ddbb1fe5 100644 --- a/res/values-tl/arrays.xml +++ b/res/values-tl/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "Hindi kailanman" + "Pagkalipas ng 1 minuto" + "Pagkalipas ng 5 minuto" + diff --git a/res/values-tr/arrays.xml b/res/values-tr/arrays.xml index 543c9481165..afd0178c7e5 100644 --- a/res/values-tr/arrays.xml +++ b/res/values-tr/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "Hiçbir zaman" + "1 dakika sonra" + "5 dakika sonra" + diff --git a/res/values-uk/arrays.xml b/res/values-uk/arrays.xml index fbe9a1d820c..21b147603da 100644 --- a/res/values-uk/arrays.xml +++ b/res/values-uk/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "Ніколи" + "Через 1 хвилину" + "Через 5 хвилин" + diff --git a/res/values-ur/arrays.xml b/res/values-ur/arrays.xml index 2131e8f5657..0e85df5bde1 100644 --- a/res/values-ur/arrays.xml +++ b/res/values-ur/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "کبھی نہیں" + "1 منٹ کے بعد" + "5 منٹ کے بعد" + diff --git a/res/values-uz/arrays.xml b/res/values-uz/arrays.xml index 3c265f9436a..588ad0c927d 100644 --- a/res/values-uz/arrays.xml +++ b/res/values-uz/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "Hech qachon" + "1 daqiqadan keyin" + "5 daqiqadan keyin" + diff --git a/res/values-vi/arrays.xml b/res/values-vi/arrays.xml index 8eb8275b791..46f22617a21 100644 --- a/res/values-vi/arrays.xml +++ b/res/values-vi/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "Không bao giờ" + "Sau 1 phút" + "Sau 5 phút" + diff --git a/res/values-zh-rCN/arrays.xml b/res/values-zh-rCN/arrays.xml index 7c01a565202..7b68493b957 100644 --- a/res/values-zh-rCN/arrays.xml +++ b/res/values-zh-rCN/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "永不" + "1 分钟后" + "5 分钟后" + diff --git a/res/values-zh-rHK/arrays.xml b/res/values-zh-rHK/arrays.xml index 7a487200b1d..a0d4bba70fc 100644 --- a/res/values-zh-rHK/arrays.xml +++ b/res/values-zh-rHK/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "永不" + "1 分鐘後" + "5 分鐘後" + diff --git a/res/values-zh-rTW/arrays.xml b/res/values-zh-rTW/arrays.xml index 95433729c31..f118b70d10e 100644 --- a/res/values-zh-rTW/arrays.xml +++ b/res/values-zh-rTW/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "永不" + "1 分鐘後" + "5 分鐘後" + diff --git a/res/values-zu/arrays.xml b/res/values-zu/arrays.xml index f23133ddc18..7c09cdce996 100644 --- a/res/values-zu/arrays.xml +++ b/res/values-zu/arrays.xml @@ -586,7 +586,9 @@ "0" "1" - - - + + "Ngeke" + "Ngemuva komzuzu o-1" + "Ngemuva kwemizuzu emi-5" + From c9a4f35a7411f477ed6c4658ffd2d3fcc95488c4 Mon Sep 17 00:00:00 2001 From: Bill Yi Date: Tue, 22 Nov 2022 15:59:54 -0800 Subject: [PATCH 09/16] Import translations. DO NOT MERGE ANYWHERE Auto-generated-cl: translation import Change-Id: I9d5dceeb79a553eace466c50494f0e670bcbf28a --- res/values-af/strings.xml | 15 ++++++------ res/values-am/strings.xml | 36 +++++++++++----------------- res/values-ar/strings.xml | 15 ++++++------ res/values-as/strings.xml | 15 ++++++------ res/values-az/strings.xml | 15 ++++++------ res/values-b+sr+Latn/strings.xml | 15 ++++++------ res/values-be/strings.xml | 15 ++++++------ res/values-bg/strings.xml | 15 ++++++------ res/values-bn/strings.xml | 15 ++++++------ res/values-bs/strings.xml | 15 ++++++------ res/values-ca/strings.xml | 15 ++++++------ res/values-cs/strings.xml | 15 ++++++------ res/values-da/strings.xml | 15 ++++++------ res/values-de/strings.xml | 12 +++++----- res/values-el/strings.xml | 15 ++++++------ res/values-en-rAU/strings.xml | 15 ++++++------ res/values-en-rCA/strings.xml | 3 +++ res/values-en-rGB/strings.xml | 15 ++++++------ res/values-en-rIN/strings.xml | 15 ++++++------ res/values-en-rXC/strings.xml | 3 +++ res/values-es-rUS/strings.xml | 17 +++++++------- res/values-es/strings.xml | 19 +++++++-------- res/values-et/strings.xml | 6 +++-- res/values-eu/strings.xml | 15 ++++++------ res/values-fa/strings.xml | 15 ++++++------ res/values-fi/strings.xml | 15 ++++++------ res/values-fr-rCA/strings.xml | 17 +++++++------- res/values-fr/strings.xml | 17 +++++++------- res/values-gl/strings.xml | 15 ++++++------ res/values-gu/strings.xml | 15 ++++++------ res/values-hi/strings.xml | 15 ++++++------ res/values-hr/strings.xml | 15 ++++++------ res/values-hu/strings.xml | 15 ++++++------ res/values-hy/strings.xml | 15 ++++++------ res/values-in/strings.xml | 15 ++++++------ res/values-is/strings.xml | 15 ++++++------ res/values-it/strings.xml | 17 +++++++------- res/values-iw/strings.xml | 15 ++++++------ res/values-ja/strings.xml | 15 ++++++------ res/values-ka/strings.xml | 15 ++++++------ res/values-kk/strings.xml | 15 ++++++------ res/values-km/strings.xml | 15 ++++++------ res/values-kn/strings.xml | 15 ++++++------ res/values-ko/strings.xml | 15 ++++++------ res/values-ky/strings.xml | 17 +++++++------- res/values-lo/strings.xml | 15 ++++++------ res/values-lt/strings.xml | 15 ++++++------ res/values-lv/strings.xml | 40 +++++++++++++------------------- res/values-mk/strings.xml | 15 ++++++------ res/values-ml/strings.xml | 15 ++++++------ res/values-mn/strings.xml | 6 +++-- res/values-mr/strings.xml | 15 ++++++------ res/values-ms/strings.xml | 15 ++++++------ res/values-my/strings.xml | 15 ++++++------ res/values-nb/strings.xml | 15 ++++++------ res/values-ne/strings.xml | 15 ++++++------ res/values-nl/strings.xml | 8 ++++--- res/values-or/strings.xml | 15 ++++++------ res/values-pa/strings.xml | 15 ++++++------ res/values-pl/strings.xml | 15 ++++++------ res/values-pt-rBR/strings.xml | 19 +++++++-------- res/values-pt-rPT/strings.xml | 17 +++++++------- res/values-pt/strings.xml | 19 +++++++-------- res/values-ro/strings.xml | 15 ++++++------ res/values-ru/strings.xml | 15 ++++++------ res/values-si/strings.xml | 15 ++++++------ res/values-sk/strings.xml | 15 ++++++------ res/values-sl/strings.xml | 15 ++++++------ res/values-sq/strings.xml | 15 ++++++------ res/values-sr/strings.xml | 15 ++++++------ res/values-sv/strings.xml | 6 +++-- res/values-sw/strings.xml | 15 ++++++------ res/values-ta/strings.xml | 15 ++++++------ res/values-te/strings.xml | 15 ++++++------ res/values-th/strings.xml | 15 ++++++------ res/values-tl/strings.xml | 15 ++++++------ res/values-tr/strings.xml | 15 ++++++------ res/values-uk/strings.xml | 15 ++++++------ res/values-ur/strings.xml | 15 ++++++------ res/values-uz/strings.xml | 15 ++++++------ res/values-vi/strings.xml | 19 +++++++-------- res/values-zh-rCN/strings.xml | 15 ++++++------ res/values-zh-rHK/strings.xml | 31 ++++++++++++------------- res/values-zh-rTW/strings.xml | 15 ++++++------ res/values-zu/strings.xml | 15 ++++++------ 85 files changed, 613 insertions(+), 691 deletions(-) diff --git a/res/values-af/strings.xml b/res/values-af/strings.xml index 0a268e2ccbc..da2478e4de9 100644 --- a/res/values-af/strings.xml +++ b/res/values-af/strings.xml @@ -588,12 +588,9 @@ "%d persent ingeskryf" "Skryf tans vingerafdruk in %d persent" "Vingerafdruk bygevoeg" - - - - - - + "Jy kan nou jou vingerafdruk gebruik om jou tablet te ontsluit of te verifieer dat dit jy is, soos wanneer jy by apps aanmeld of ’n aankoop goedkeur" + "Jy kan nou jou vingerafdruk gebruik om jou toestel te ontsluit of te verifieer dat dit jy is, soos wanneer jy by apps aanmeld of ’n aankoop goedkeur" + "Jy kan nou jou vingerafdruk gebruik om jou foon te ontsluit of te verifieer dat dit jy is, soos wanneer jy by apps aanmeld of ’n aankoop goedkeur" "Ontsluit slegs wanneer skerm aan is" "Die skerm moet aan wees voordat jy met jou vingerafdruk kan ontsluit. Dit maak onbeplande ontsluiting minder waarskynlik." "Skerm, ontsluit" @@ -3490,8 +3487,7 @@ "Vee %1$s van hierdie toestel af uit" "Sluitskerminstellings" "Voeg gebruikers van die sluitskerm af by" - - + "Skakel oor na admingebruiker wanneer gedok" "Verwyder jouself?" "Vee dié gebruiker uit?" "Verwyder hierdie profiel?" @@ -5673,6 +5669,9 @@ "Skakel eers \"Wys toestelkontroles\" aan as jy wil gebruik" "Wys dubbellynhorlosie as dit beskikbaar is" "Dubbellynhorlosie" + + + diff --git a/res/values-am/strings.xml b/res/values-am/strings.xml index ba26a215684..1f8eb0762cf 100644 --- a/res/values-am/strings.xml +++ b/res/values-am/strings.xml @@ -588,12 +588,9 @@ "የተመዘገበ %d መቶኛ" "የጣት አሻራ %d መቶኛን በመመዝገብ ላይ" "የጣት አሻራ ታክሏል" - - - - - - + "አሁን የእርስዎን ጡባዊ ለመክፈት ወይም ለምሳሌ ወደ መተግበሪያዎች በመለያ ሲገቡ ወይም አንድን ግዢ ሲያጸድቁ እርስዎ መሆንዎን ለማረጋገጥ የጣት አሻራዎን መጠቀም ይችላሉ" + "አሁን የእርስዎን መሣሪያ ለመክፈት ወይም ለምሳሌ ወደ መተግበሪያዎች በመለያ ሲገቡ ወይም አንድን ግዢ ሲያጸድቁ እርስዎ መሆንዎን ለማረጋገጥ የጣት አሻራዎን መጠቀም ይችላሉ" + "አሁን የእርስዎን ስልክ ለመክፈት ወይም ለምሳሌ ወደ መተግበሪያዎች በመለያ ሲገቡ ወይም አንድን ግዢ ሲያጸድቁ እርስዎ መሆንዎን ለማረጋገጥ የጣት አሻራዎን መጠቀም ይችላሉ" "ማያ ገጽ ሲበራ ብቻ ይክፈቱ" "በጣት አሻራዎ ከመክፈትዎ በፊት ማያ ገጹ ክፍት መሆን አለበት። ይህ በስህተት የመከፈትን ዕድል ይቀንሳል።" "ማያ ገጽ፣ ይክፈቱ" @@ -2811,8 +2808,7 @@ "የታሪክ ዝርዝሮች" "የባትሪ አጠቃቀም" "ያለፉት 24 ሰዓቶች አጠቃቀምን ይመልከቱ" - - + "ከመጨረሻው ሙሉ የኃይል ሙሌት በኋላ አጠቃቀምን አሳይ" "የመተግበሪያ የባትሪ አጠቃቀም" "ዝርዝሮችን ተጠቀም" "የኃይል አጠቃቀም አስተካክል" @@ -2993,32 +2989,25 @@ "የባትሪ አጠቃቀም" "የባትሪው ኃይል ሙሉ ከሆነ በኋላ" "የባትሪ አጠቃቀምን ያቀናብሩ" - - + "^1 ጠቅላላ • ከመጨረሻው ሙሉ የኃይል ሙሌት በኋላ\n^2 ዳራ" "^1 ጠቅላላ • ላለፉት 24 ሰዓታት\n^2 ዳራ" "^1 ጠቅላላ • የ^2 ዳራ\nለ^3" - - + "ከመጨረሻው ሙሉ የኃይል ሙሌት በኋላ ጠቅላላ ከአንድ ደቂቃ ያነሰ" "ላለፉት 24 ሰዓቶች ጠቅላላ ከአንድ ደቂቃ ያነሰ" "ለ^1 ጠቅላላ ከአንድ ደቂቃ" - - + "ከመጨረሻው ሙሉ የኃይል ሙሌት በኋላ ዳራ ከአንድ ደቂቃ ያነሰ" "ላለፉት 24 ሰዓታት ዳራ ከአንድ ደቂቃ በታች" "ለ^1 ዳራ ከአንድ ደቂቃ በታች" - - + "^1 ጠቅላላ ከመጨረሻው ሙሉ የኃይል ሙሌት በኋላ" "ላለፉት 24 ሰዓታት ^1 ጠቅላላ" "ለ^2 ጠቅላላ ^1" - - + "ከመጨረሻው ሙሉ የኃይል ሙሌት በኋላ ^1 ዳራ" "ላለፉት 24 ሰዓታት የ^1 ዳራ" "ለ^2 የ^1 ዳራ" - - + "^1 ጠቅላላ • ከመጨረሻው ሙሉ የኃይል ሙሌት በኋላ\nዳራ ከአንድ ደቂቃ ያነሰ" "^1 ጠቅላላ • ላለፉት 24 ሰዓታት\nዳራ ከአንድ ደቂቃ በታች" "^1 ጠቅላላ • ለ^2\nዳራ ከአንድ ደቂቃ በታች" - - + "ከመጨረሻው ሙሉ የኃይል ሙሌት በኋላ ምንም አጠቃቀም የለም" "ላለፉት 24 ሰዓታት ጥቅም ላይ አልዋለም" "ሌሎች ተጠቃሚዎች" @@ -5681,6 +5670,9 @@ "ለመጠቀም መጀመሪያ «የመሣሪያ መቆጣጠሪያዎችን አሳይ» የሚለውን ያብሩ" "የሚገኝ ሲሆን ባለ ሁለት-መስመር ሰዓት አሳይ" "ባለ ሁለት-መስመር ሰዓት" + + + diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml index b937c750b3b..12f7d106262 100644 --- a/res/values-ar/strings.xml +++ b/res/values-ar/strings.xml @@ -604,12 +604,9 @@ "اكتملت عملية التسجيل بنسبة %d في المئة." "تسجيل بصمة الإصبع %d في المئة." "تمت إضافة بصمة الإصبع" - - - - - - + "يمكنك الآن استخدام بصمة إصبعك لفتح قفل جهازك اللوحي أو إثبات هويتك، مثلاً عند تسجيل الدخول إلى التطبيقات أو الموافقة على عملية شراء." + "يمكنك الآن استخدام بصمة إصبعك لفتح قفل جهازك أو إثبات هويتك، مثلاً عند تسجيل الدخول إلى التطبيقات أو الموافقة على عملية شراء." + "يمكنك الآن استخدام بصمة إصبعك لفتح قفل هاتفك أو إثبات هويتك، مثلاً عند تسجيل الدخول إلى التطبيقات أو الموافقة على عملية شراء." "فتح قفل الشاشة عندما تكون مفعَّلة فقط" "يجب تفعيل الشاشة قبل أن تتمكن من فتح قفلها ببصمة إصبعك. يؤدي هذا إلى تقليل احتمال فتح قفل الشاشة بدون قصد." "فتح قفل الشاشة" @@ -3658,8 +3655,7 @@ "حذف %1$s من هذا الجهاز" "إعدادات شاشة القفل" "إضافة المستخدمين من شاشة القفل" - - + "التبديل إلى المستخدم المشرف عند إرساء الجهاز" "هل تريد حذف نفسك؟" "هل تريد حذف هذا المستخدم؟" "هل تريد حذف هذا الملف الشخصي؟" @@ -6021,6 +6017,9 @@ "لتتمكَّن من استخدام عناصر التحكّم، عليك أولاً تفعيل خيار \"إظهار عناصر التحكّم بالأجهزة\"." "إظهار الساعة بخطين عندما تكون متاحة" "ساعة بخطين" + + + diff --git a/res/values-as/strings.xml b/res/values-as/strings.xml index ffa4abdd948..4119248feb1 100644 --- a/res/values-as/strings.xml +++ b/res/values-as/strings.xml @@ -588,12 +588,9 @@ "%d শতাংশ পঞ্জীয়ন কৰা হৈছে" "ফিংগাৰপ্ৰিণ্ট %d শতাংশ পঞ্জীয়ন কৰা হ\'ল" "ফিংগাৰপ্ৰিণ্ট যোগ কৰা হ’ল" - - - - - - + "এতিয়া আপুনি নিজৰ টেবলেটটো আনলক কৰোঁতে অথবা আপুনি এপত ছাইন ইন কৰা অথবা কোনো ক্ৰয়ৰ অনুমোদন জনোৱা আদিৰ দৰে কাৰ্য কৰোঁতে এয়া আপুনিয়েই বুলি সত্যাপন কৰিবলৈ নিজৰ ফিংগাৰপ্ৰিণ্ট ব্যৱহাৰ কৰিব পাৰে" + "এতিয়া আপুনি নিজৰ ডিভাইচটো আনলক কৰোঁতে অথবা আপুনি এপত ছাইন ইন কৰা অথবা কোনো ক্ৰয়ৰ অনুমোদন জনোৱা আদিৰ দৰে কাৰ্য কৰোঁতে এয়া আপুনিয়েই বুলি সত্যাপন কৰিবলৈ নিজৰ ফিংগাৰপ্ৰিণ্ট ব্যৱহাৰ কৰিব পাৰে" + "এতিয়া আপুনি নিজৰ ফ’নটো আনলক কৰোঁতে অথবা আপুনি এপত ছাইন ইন কৰা অথবা কোনো ক্ৰয়ৰ অনুমোদন জনোৱা আদিৰ দৰে কাৰ্য কৰোঁতে এয়া আপুনিয়েই বুলি সত্যাপন কৰিবলৈ নিজৰ ফিংগাৰপ্ৰিণ্ট ব্যৱহাৰ কৰিব পাৰে" "কেৱল স্ক্ৰীন অন হৈ থকা অৱস্থাত আনলক কৰক" "আপোনাৰ ফিংগাৰপ্ৰিণ্টৰ জৰিয়তে আনলক কৰিব পৰা হোৱাৰ পূৰ্বে স্ক্ৰীনখন অন হৈ থাকিবই লাগিব। এইটোৱে ভুলতে আনলক হোৱাৰ সম্ভাৱনা কম কৰে।" "স্ক্ৰীন, আনলক কৰা আছে" @@ -3490,8 +3487,7 @@ "এই ডিভাইচৰ পৰা %1$sক মচক" "লক স্ক্ৰীনৰ ছেটিং" "লক স্ক্ৰীনৰ পৰা নতুন ব্যৱহাৰকাৰী যোগ দিয়ক" - - + "ডক কৰিলে প্ৰশাসক ব্যৱহাৰকাৰীলৈ সলনি কৰক" "নিজেই মচিবনে?" "এই ব্যৱহাৰকাৰীজন মচিবনে?" "এই প্ৰ\'ফাইলটো আঁতৰাইনে?" @@ -5673,6 +5669,9 @@ "ব্যৱহাৰ কৰিবলৈ, প্ৰথমে \"ডিভাইচৰ নিয়ন্ত্ৰণ দেখুৱাওক\" অন কৰক" "যেতিয়া উপলব্ধ হয় দ্বৈত-শাৰীৰ ঘড়ী দেখুৱাব" "দ্বৈত-শাৰীৰ ঘড়ী" + + + diff --git a/res/values-az/strings.xml b/res/values-az/strings.xml index 18550ed73c9..0e70f8be13f 100644 --- a/res/values-az/strings.xml +++ b/res/values-az/strings.xml @@ -588,12 +588,9 @@ "%d faiz qeydiyyatdan keçib" "Barmaq izi qeydiyyatı: %d faiz" "Barmaq izi əlavə edildi" - - - - - - + "İndi tətbiqlərə daxil olmaq və ya alışı təsdiqləmək kimi hallarda planşeti kiliddən çıxarmaq və ya kimlik doğrulaması üçün barmaq izinizdən istifadə edə bilərsiniz" + "İndi tətbiqlərə daxil olmaq və ya alışı təsdiqləmək kimi hallarda cihazı kiliddən çıxarmaq və ya kimlik doğrulaması üçün barmaq izinizdən istifadə edə bilərsiniz" + "İndi tətbiqlərə daxil olmaq və ya alışı təsdiqləmək kimi hallarda telefonu kiliddən çıxarmaq və ya kimlik doğrulaması üçün barmaq izinizdən istifadə edə bilərsiniz" "Yalnız ekran aktiv olduqda kiliddən çıxarın" "Barmaq izinizlə kiliddən çıxarmadan əvvəl ekran aktiv olmalıdır. Bu, təsadüfən kiliddən çıxarılma ehtimalını azaldır." "Ekranı kiliddən çıxarma" @@ -3490,8 +3487,7 @@ "%1$s adlı istifadəçini bu cihazdan silin" "Ekran ayarlarını kilidləyin" "Kilid ekranından istifadəçi əlavə edin" - - + "Doka yerləşdirildikdə admin istifadəçiyə keçin" "Özünüzü silirsiniz?" "Bu istifadəçi silinsin?" "Bu profil silinsin?" @@ -5673,6 +5669,9 @@ "İstifadə etmək üçün əvvəlcə \"Cihaz idarəetmələrini göstər\" seçimini aktiv edin" "Əlçatan olduqda ikisətirli saatı göstərin" "İkisətirli saat" + + + diff --git a/res/values-b+sr+Latn/strings.xml b/res/values-b+sr+Latn/strings.xml index 3b3ae1552b2..4a45d398a22 100644 --- a/res/values-b+sr+Latn/strings.xml +++ b/res/values-b+sr+Latn/strings.xml @@ -592,12 +592,9 @@ "Registrovano je %d posto" "Registrovanje otiska prsta je na %d posto" "Otisak prsta je dodat" - - - - - - + "Sada možete da koristite otisak prsta za otključavanje tableta ili potvrdu identiteta, na primer, kad se prijavljujete u aplikacije ili odobravate kupovinu" + "Sada možete da koristite otisak prsta za otključavanje uređaja ili potvrdu identiteta, na primer, kad se prijavljujete u aplikacije ili odobravate kupovinu" + "Sada možete da koristite otisak prsta za otključavanje telefona ili potvrdu identiteta, na primer, kad se prijavljujete u aplikacije ili odobravate kupovinu" "Otključavanje samo kada je ekran uključen" "Ekran mora da bude uključen da biste mogli da otključate otiskom prsta. To smanjuje verovatnoću za slučajno otključavanje." "Ekran, otključavanje" @@ -3532,8 +3529,7 @@ "Izbriši %1$s sa uređaja" "Podešavanja zaključanog ekrana" "Dodaj korisnike sa zaključanog ekrana" - - + "Pređi na administratora na baznoj stanici" "Želite li da izbrišete sebe?" "Brišete ovog korisnika?" "Uklanjate ovaj profil?" @@ -5760,6 +5756,9 @@ "Da biste koristili, prvo uključite Prikaži kontrole uređaja" "Prikazuje dvolinijski sat kada je dostupan" "Dvolinijski sat" + + + diff --git a/res/values-be/strings.xml b/res/values-be/strings.xml index 62a8a20a31d..6b21521fcb5 100644 --- a/res/values-be/strings.xml +++ b/res/values-be/strings.xml @@ -598,12 +598,9 @@ "Адбітак пальца дададзены" - - - - - - + "Цяпер вы можаце выкарыстоўваць функцыю распазнавання адбіткаў пальца для разблакіроўкі планшэта ці спраўджання вашай асобы, напрыклад падчас уваходу ў праграмы ці ўхвалення куплі" + "Цяпер вы можаце выкарыстоўваць функцыю распазнавання адбіткаў пальца для разблакіроўкі прылады ці спраўджання вашай асобы, напрыклад падчас уваходу ў праграмы ці ўхвалення куплі" + "Цяпер вы можаце выкарыстоўваць функцыю распазнавання адбіткаў пальца для разблакіроўкі тэлефона ці спраўджання вашай асобы, напрыклад падчас уваходу ў праграмы ці ўхвалення куплі" "Разблакіраваць толькі пры ўключаным экране" "Неабходна ўключыць экран, каб разблакіраваць яго адбіткам пальца. Гэта змяншае імавернасць выпадковай разблакіроўкі." "Разблакіроўка экрана" @@ -3576,8 +3573,7 @@ "Выдаліць %1$s з гэтай прылады" "Налады экрана блакіроўкі" "Дадаваць карыстальнікаў з экрана блакіроўкі" - - + "На док-станцыі пераключацца на адміністратара" "Выдаляеце сябе?" "Выдаліць карыстальніка?" "Выдаліць гэты профіль?" @@ -5849,6 +5845,9 @@ "Спачатку ўключыце \"Паказваць элементы кіравання прыладамі\"" "Паказваць двухрадковы дысплэй гадзінніка, калі ён даступны" "Двухрадковы дысплэй гадзінніка" + + + diff --git a/res/values-bg/strings.xml b/res/values-bg/strings.xml index fcfdf47e99f..400706d5eb4 100644 --- a/res/values-bg/strings.xml +++ b/res/values-bg/strings.xml @@ -594,12 +594,9 @@ "Отпечатъкът е добавен" - - - - - - + "Вече можете да използвате отпечатъка си, за да отключвате таблета или да потвърждавате самоличността си, например при влизане в приложения или одобряване на покупки" + "Вече можете да използвате отпечатъка си, за да отключвате устройството или да потвърждавате самоличността си, например при влизане в приложения или одобряване на покупки" + "Вече можете да използвате отпечатъка си, за да отключвате телефона или да потвърждавате самоличността си, например при влизане в приложения или одобряване на покупки" "Отключване само когато екранът е включен" "Екранът трябва да е включен, преди да можете да отключвате с отпечатъка си. По този начин случайното отключване е по-малко вероятно." "Екран, отключване" @@ -3496,8 +3493,7 @@ "Изтриване на %1$s от у-вото" "Настройки на заключения екран" "Добавяне на потребители от заключения екран" - - + "Докинг станция: Превкл. към потр. с админ. достъп" "Искате ли да се изтриете?" "Изтриване на потребителя?" "Ще прем. ли потр. профил?" @@ -5679,6 +5675,9 @@ "За да използвате, първо включете „Показване на контроли за устройства“" "Показване на часовника на два реда, когато е налице" "Часовник на два реда" + + + diff --git a/res/values-bn/strings.xml b/res/values-bn/strings.xml index 24bc6aa06c9..8652f28b69b 100644 --- a/res/values-bn/strings.xml +++ b/res/values-bn/strings.xml @@ -588,12 +588,9 @@ "%d শতাংশ এনরোল করা হয়েছে" "আঙ্গুলের ছাপ নথিভুক্ত করার কাজটি %d শতাংশ সম্পূর্ণ হয়েছে" "ফিঙ্গারপ্রিন্ট যোগ করা হয়েছে" - - - - - - + "অ্যাপে সাইন-ইন করা বা কেনাকাটায় অনুমতি দেওয়ার মতোই এখন ফিঙ্গারপ্রিন্ট ব্যবহার করে ট্যাবলেট আনলক বা আপনার পরিচয় যাচাই করতে পারবেন" + "অ্যাপে সাইন-ইন করা বা কেনাকাটায় অনুমতি দেওয়ার মতোই এখন ফিঙ্গারপ্রিন্ট ব্যবহার করে ডিভাইস আনলক বা আপনার পরিচয় যাচাই করতে পারবেন" + "অ্যাপে সাইন-ইন করা বা কেনাকাটায় অনুমতি দেওয়ার মতোই এখন ফিঙ্গারপ্রিন্ট ব্যবহার করে ফোন আনলক বা আপনার পরিচয় যাচাই করতে পারবেন" "শুধুমাত্র স্ক্রিন চালু থাকা অবস্থাতে আনলক করা" "আপনি নিজের ফিঙ্গারপ্রিন্টের মাধ্যমে আনলক করতে পারার আগে স্ক্রিন অবশ্যই চালু থাকতে হবে। এর ফলে ভুলবশত আনলক হওয়ার ঘটনা কম ঘটে।" "স্ক্রিন, আনলক করুন" @@ -3490,8 +3487,7 @@ "এই ডিভাইস থেকে %1$s মুছে ফেলুন" "লক স্ক্রিন সেটিংস" "লক স্ক্রিন থেকে ব্যবহারকারীদের যোগ করুন" - - + "ডক করা হলে অ্যাডমিন ব্যবহারকারীতে পাল্টান" "নিজেকে মুছবেন?" "অ্যাকাউন্ট মুছতে চান?" "এই প্রোফাইলটি সরাবেন?" @@ -5673,6 +5669,9 @@ "ব্যবহার করতে, প্রথমে \"ডিভাইস নিয়ন্ত্রণ দেখুন\" বিকল্প চালু করুন" "ডবল-লাইন ঘড়ি উপলভ্য থাকলে তা দেখান" "ডবল-লাইন ঘড়ি" + + + diff --git a/res/values-bs/strings.xml b/res/values-bs/strings.xml index 0db3a940c1a..ac4e98ddbd8 100644 --- a/res/values-bs/strings.xml +++ b/res/values-bs/strings.xml @@ -592,12 +592,9 @@ "Prijavljeno je %d posto" "Prijava otiska prsta: %d posto" "Dodan je otisak prsta" - - - - - - + "Sada možete pomoću otiska prsta otključati tablet ili potvrditi svoj identitet, naprimjer kada se prijavljujete u aplikacije ili odobravate kupovinu" + "Sada možete pomoću otiska prsta otključati uređaj ili potvrditi svoj identitet, naprimjer kada se prijavljujete u aplikacije ili odobravate kupovinu" + "Sada možete pomoću otiska prsta otključati telefon ili potvrditi svoj identitet, naprimjer kada se prijavljujete u aplikacije ili odobravate kupovinu" "Otključavanje samo kad je ekran uključen" "Ekran mora biti uključen da možete otključati otiskom prsta. To čini slučajno otključavanje manje vjerovatnim." "Ekran, otključavanje" @@ -3532,8 +3529,7 @@ "Izbrišite %1$s sa uređaja" "Postavke zaključavanja ekrana" "Dodavanje korisnika sa zaključanog ekrana" - - + "Prebacite se na admin. kada je uređaj priključen" "Želite li izbrisati sebe?" "Izbrisati ovog korisnika?" "Ukloniti ovaj profil?" @@ -5760,6 +5756,9 @@ "Da koristite, najprije uključite \"Prikaži kontrole uređaja\"" "Prikaži dvolinijski sat kada je dostupan" "Dvolinijski sat" + + + diff --git a/res/values-ca/strings.xml b/res/values-ca/strings.xml index e55e24e45e6..f9b19922146 100644 --- a/res/values-ca/strings.xml +++ b/res/values-ca/strings.xml @@ -588,12 +588,9 @@ "S\'ha inscrit un %d per cent" "Registre de l\'empremta digital %d per cent" "S\'ha afegit l\'empremta digital" - - - - - - + "Ara pots utilitzar l\'empremta digital per desbloquejar la tauleta o verificar que ets tu, com ara quan inicies la sessió en aplicacions o aproves una compra" + "Ara pots utilitzar l\'empremta digital per desbloquejar el dispositiu o verificar que ets tu, com ara quan inicies la sessió en aplicacions o aproves una compra" + "Ara pots utilitzar l\'empremta digital per desbloquejar el telèfon o verificar que ets tu, com ara quan inicies la sessió en aplicacions o aproves una compra" "Desbloqueja només quan la pantalla estigui activada" "La pantalla ha d\'estar activada abans de poder desbloquejar el dispositiu amb la teva empremta digital. Així és menys probable que hi hagi desbloquejos accidentals." "Pantalla, desbloqueig" @@ -3490,8 +3487,7 @@ "Suprimeix %1$s del dispositiu" "Configuració de la pantalla de bloqueig" "Afegeix usuaris des de la pantalla de bloqueig" - - + "Canvia a l\'usuari administrador quan estigui acoblat" "Et vols suprimir a tu mateix?" "Vols suprimir l\'usuari?" "Vols suprimir el perfil?" @@ -5673,6 +5669,9 @@ "Per utilitzar-ho, primer activa Mostra el control de dispositius" "Mostra el rellotge de doble línia quan estigui disponible" "Rellotge de doble línia" + + + diff --git a/res/values-cs/strings.xml b/res/values-cs/strings.xml index db5cc3b7faf..c19a91554c7 100644 --- a/res/values-cs/strings.xml +++ b/res/values-cs/strings.xml @@ -596,12 +596,9 @@ "Zaregistrováno %d procent" "Registrace otisku prstu: %d procent" "Otisk byl přidán" - - - - - - + "Odteď můžete otiskem prstu odemykat tablet nebo ověřovat svoji identitu, například při přihlašování do aplikací nebo schvalování nákupů" + "Odteď můžete pomocí otisku prstu odemykat zařízení nebo ověřovat svoji identitu, například při přihlašování do aplikací nebo schvalování nákupů" + "Odteď můžete pomocí otisku prstu odemykat telefon nebo ověřovat svoji identitu, například při přihlašování do aplikací nebo schvalování nákupů" "Odemknou jen při zapnuté obrazovce" "Před odemknutím pomocí otisku prstu musí být obrazovka zapnutá. Nezamýšlené odemknutí je tak méně pravděpodobné." "Obrazovka, odemknutí" @@ -3574,8 +3571,7 @@ "Smazat %1$s ze zařízení" "Nastavení obrazovky uzamčení" "Přidávat uživatele z obrazovky uzamčení" - - + "V doku přepnout na administrativního uživatele" "Chcete se smazat?" "Smazat tohoto uživatele?" "Odstranit tento profil?" @@ -5847,6 +5843,9 @@ "Nejprve zapněte zobrazení ovládání zařízení" "Zobrazovat hodiny na dva řádky, je-li to možné" "Hodiny na dva řádky" + + + diff --git a/res/values-da/strings.xml b/res/values-da/strings.xml index 4ced82e5aa9..854fd6a18ae 100644 --- a/res/values-da/strings.xml +++ b/res/values-da/strings.xml @@ -588,12 +588,9 @@ "%d procent konfigureret" "Scanning af fingeraftryk: %d procent" "Fingeraftryk tilføjet" - - - - - - + "Nu kan du bruge dit fingeraftryk til at låse din tablet op eller verificere din identitet, f.eks. når du logger ind i apps eller godkender et køb" + "Nu kan du bruge dit fingeraftryk til at låse din enhed op eller verificere din identitet, f.eks. når du logger ind i apps eller godkender et køb" + "Nu kan du bruge dit fingeraftryk til at låse din telefon op eller verificere din identitet, f.eks. når du logger ind i apps eller godkender et køb" "Lås kun op, når skærmen er tændt" "Skærmen skal være tændt, før du kan låse op med dit fingeraftryk. Det gør det sværere at komme til at låse op ved et uheld." "Skærm, oplåsning" @@ -3490,8 +3487,7 @@ "Slet %1$s fra denne enhed" "Lås skærmindstillinger" "Tilføj brugere fra låseskærm" - - + "Skift til administrator, når sat i dockingstation" "Vil du slette dig selv?" "Vil du slette brugeren?" "Vil du fjerne profilen?" @@ -5673,6 +5669,9 @@ "Du skal først aktivere \"Vis enhedsstyring\"." "Vis uret med to linjer, når det er tilgængeligt" "Ur med to linjer" + + + diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml index be0c69cd165..31e3cd4cee1 100644 --- a/res/values-de/strings.xml +++ b/res/values-de/strings.xml @@ -594,12 +594,9 @@ "Fingerabdruck hinzugefügt" - - - - - - + "Du kannst jetzt deinen Fingerabdruck verwenden, um dein Tablet zu entsperren oder deine Identität zu bestätigen, z. B. um dich in Apps anzumelden oder Käufe zu autorisieren" + "Du kannst jetzt deinen Fingerabdruck verwenden, um dein Gerät zu entsperren oder deine Identität zu bestätigen, z. B. um dich in Apps anzumelden oder Käufe zu autorisieren" + "Du kannst jetzt deinen Fingerabdruck verwenden, um dein Smartphone zu entsperren oder deine Identität zu bestätigen, z. B. um dich in Apps anzumelden oder Käufe zu autorisieren" "Nur entsperren, wenn das Display aktiviert ist" "Das Display muss aktiviert sein, bevor du es mit deinem Fingerabdruck entsperren kannst. Versehentliches Entsperren wird so weniger wahrscheinlich." "Display, entsperren" @@ -5680,6 +5677,9 @@ "Wenn du dies nutzen möchtest, aktiviere zuerst die Option „Gerätesteuerung anzeigen“" "Uhrzeit in zwei Zeilen anzeigen, wenn verfügbar" "Uhrzeit in zwei Zeilen" + + + diff --git a/res/values-el/strings.xml b/res/values-el/strings.xml index c7fce34e72d..962d80b8666 100644 --- a/res/values-el/strings.xml +++ b/res/values-el/strings.xml @@ -588,12 +588,9 @@ "Εγγραφή στο %d τοις εκατό" "Εγγραφή δακτυλικού αποτυπώματος %d τοις εκατό" "Προστέθηκε δακτυλ. αποτύπωμα" - - - - - - + "Μπορείτε πλέον να χρησιμοποιείτε το δακτυλικό σας αποτύπωμα για να ξεκλειδώνετε το tablet σας ή για να επαληθεύετε την ταυτότητά σας, για παράδειγμα, όταν συνδέεστε σε εφαρμογές ή εγκρίνετε μια αγορά." + "Μπορείτε πλέον να χρησιμοποιείτε το δακτυλικό σας αποτύπωμα για να ξεκλειδώνετε τη συσκευή σας ή για να επαληθεύετε την ταυτότητά σας, για παράδειγμα, όταν συνδέεστε σε εφαρμογές ή εγκρίνετε μια αγορά." + "Μπορείτε πλέον να χρησιμοποιείτε το δακτυλικό σας αποτύπωμα για να ξεκλειδώνετε το τηλέφωνό σας ή για να επαληθεύετε την ταυτότητά σας, για παράδειγμα, όταν συνδέεστε σε εφαρμογές ή εγκρίνετε μια αγορά." "Ξεκλείδωμα μόνο όταν η οθόνη είναι ενεργή" "Η οθόνη πρέπει να είναι ενεργή για να μπορέσετε να ξεκλειδώσετε με το δακτυλικό αποτύπωμά σας. Έτσι είναι λιγότερο πιθανό το ακούσιο ξεκλείδωμα." "Οθόνη, Ξεκλείδωμα" @@ -3490,8 +3487,7 @@ "Διαγρ. %1$s από τη συσκ." "Ρυθμίσεις κλειδώματος οθόνης" "Προσθήκη χρηστών από την οθόνη κλειδώματος" - - + "Αλλαγή σε διαχειριστή όταν είναι στη βάση σύνδεσης" "Διαγραφή του εαυτού σας;" "Να διαγραφεί ο χρήστης;" "Κατάργηση του προφίλ;" @@ -5673,6 +5669,9 @@ "Για χρήση, ενεργοποιήστε πρώτα την επιλογή Εμφάνιση στοιχείων ελέγχου συσκευής" "Εμφάνιση ρολογιού διπλής γραμμής όταν είναι διαθέσιμο" "Ρολόι διπλής γραμμής" + + + diff --git a/res/values-en-rAU/strings.xml b/res/values-en-rAU/strings.xml index 289c5e2f8c6..fbd0f1764ca 100644 --- a/res/values-en-rAU/strings.xml +++ b/res/values-en-rAU/strings.xml @@ -588,12 +588,9 @@ "Enrolled %d per cent" "Enrolling fingerprint %d per cent" "Fingerprint added" - - - - - - + "Now you can use your fingerprint to unlock your tablet or verify that it’s you, like when you sign in to apps or approve a purchase" + "Now you can use your fingerprint to unlock your device or verify that it’s you, like when you sign in to apps or approve a purchase" + "Now you can use your fingerprint to unlock your phone or verify that it’s you, like when you sign in to apps or approve a purchase" "Unlock only when screen is on" "The screen must be on before you can unlock with your fingerprint. This makes accidental unlocking less likely." "Screen, unlock" @@ -3490,8 +3487,7 @@ "Delete %1$s from this device" "Lock screen settings" "Add users from lock screen" - - + "Switch to admin user when docked" "Delete yourself?" "Delete this user?" "Remove this profile?" @@ -5673,6 +5669,9 @@ "To use, first turn on ‘Show device controls’" "Show double-line clock when available" "Double-line clock" + + + diff --git a/res/values-en-rCA/strings.xml b/res/values-en-rCA/strings.xml index a8b4affa568..a4c5c8947af 100644 --- a/res/values-en-rCA/strings.xml +++ b/res/values-en-rCA/strings.xml @@ -5669,6 +5669,9 @@ "To use, first turn on \"Show device controls\"" "Show double-line clock when available" "Double-line clock" + + + diff --git a/res/values-en-rGB/strings.xml b/res/values-en-rGB/strings.xml index fba1ded7a46..abc60eca75b 100644 --- a/res/values-en-rGB/strings.xml +++ b/res/values-en-rGB/strings.xml @@ -588,12 +588,9 @@ "Enrolled %d per cent" "Enrolling fingerprint %d per cent" "Fingerprint added" - - - - - - + "Now you can use your fingerprint to unlock your tablet or verify that it’s you, like when you sign in to apps or approve a purchase" + "Now you can use your fingerprint to unlock your device or verify that it’s you, like when you sign in to apps or approve a purchase" + "Now you can use your fingerprint to unlock your phone or verify that it’s you, like when you sign in to apps or approve a purchase" "Unlock only when screen is on" "The screen must be on before you can unlock with your fingerprint. This makes accidental unlocking less likely." "Screen, unlock" @@ -3490,8 +3487,7 @@ "Delete %1$s from this device" "Lock screen settings" "Add users from lock screen" - - + "Switch to admin user when docked" "Delete yourself?" "Delete this user?" "Remove this profile?" @@ -5673,6 +5669,9 @@ "To use, first turn on ‘Show device controls’" "Show double-line clock when available" "Double-line clock" + + + diff --git a/res/values-en-rIN/strings.xml b/res/values-en-rIN/strings.xml index f0fd28d1c87..14e1ada82a2 100644 --- a/res/values-en-rIN/strings.xml +++ b/res/values-en-rIN/strings.xml @@ -588,12 +588,9 @@ "Enrolled %d per cent" "Enrolling fingerprint %d per cent" "Fingerprint added" - - - - - - + "Now you can use your fingerprint to unlock your tablet or verify that it’s you, like when you sign in to apps or approve a purchase" + "Now you can use your fingerprint to unlock your device or verify that it’s you, like when you sign in to apps or approve a purchase" + "Now you can use your fingerprint to unlock your phone or verify that it’s you, like when you sign in to apps or approve a purchase" "Unlock only when screen is on" "The screen must be on before you can unlock with your fingerprint. This makes accidental unlocking less likely." "Screen, unlock" @@ -3490,8 +3487,7 @@ "Delete %1$s from this device" "Lock screen settings" "Add users from lock screen" - - + "Switch to admin user when docked" "Delete yourself?" "Delete this user?" "Remove this profile?" @@ -5673,6 +5669,9 @@ "To use, first turn on ‘Show device controls’" "Show double-line clock when available" "Double-line clock" + + + diff --git a/res/values-en-rXC/strings.xml b/res/values-en-rXC/strings.xml index 0bfe89d03d8..550eb38d0d2 100644 --- a/res/values-en-rXC/strings.xml +++ b/res/values-en-rXC/strings.xml @@ -5669,6 +5669,9 @@ "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‎‎‏‎‏‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‎‏‏‏‏‏‏‎‏‏‎‏‎‏‏‏‎‏‎‏‎‎‎‎‏‎‎‎‎‏‎‎‎‎‎‎‏‏‎To use, first turn on \"Show device controls\"‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‏‎‎‎‎‏‏‏‏‎‎‎‎‏‎‎‎‏‏‏‏‎‏‎‏‎‎‏‎‎‎‏‏‏‏‏‎‏‏‏‎‎‏‏‎‏‎‏‎‏‏‎‎‏‎‎‎‏‏‏‎Show double-line clock when available‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‏‏‏‏‎‏‎‎‏‏‎‏‏‏‏‎‏‎‏‏‎‏‏‎‎‏‎‏‏‏‏‎‏‏‎‏‏‎‏‏‎‏‏‎‎‎‎‎‏‎‏‏‏‏‎‏‎‎‎‏‎Double-line clock‎‏‎‎‏‎" + + + diff --git a/res/values-es-rUS/strings.xml b/res/values-es-rUS/strings.xml index f70c576fc03..9a78c26b6eb 100644 --- a/res/values-es-rUS/strings.xml +++ b/res/values-es-rUS/strings.xml @@ -590,14 +590,11 @@ "Se agregó la huella dactilar" - - - - - - + "Ahora puedes usar tu huella dactilar para desbloquear la tablet o verificar tu identidad, como cuando accedes a apps o apruebas compras" + "Ahora puedes usar tu huella dactilar para desbloquear el dispositivo o verificar tu identidad, como cuando accedes a apps o apruebas compras" + "Ahora puedes usar tu huella dactilar para desbloquear el teléfono o verificar tu identidad, como cuando accedes a apps o apruebas compras" "Desbloquear solo cuando la pantalla está encendida" - "La pantalla debe estar encendida antes de que puedas desbloquearla con la huella dactilar. De este modo, el desbloqueo accidental es menos probable." + "La pantalla debe estar encendida para desbloquearla con la huella dactilar. De este modo, los desbloqueos accidentales son menos probables." "Pantalla, desbloqueo" "Más tarde" "Levanta el dedo y vuelve a tocar" @@ -3492,8 +3489,7 @@ "Borrar a %1$s del disp." "Configuración de pantalla bloqueada" "Agregar usuarios desde la pantalla de bloqueo" - - + "Cambiar a usuario administrador cuando se conecta" "¿Deseas borrarte a ti mismo?" "¿Borrar este usuario?" "¿Eliminar este perfil?" @@ -5675,6 +5671,9 @@ "Para usar, primero activa \"Mostrar controles del dispositivo\"" "Mostrar el reloj de dos líneas cuando esté disponible" "Reloj de dos líneas" + + + diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml index 5751fd093dd..2a9f8a7705d 100644 --- a/res/values-es/strings.xml +++ b/res/values-es/strings.xml @@ -588,14 +588,11 @@ "Registro al %d por ciento" "Registro de la huella digital al %d por ciento" "Huella digital añadida" - - - - - - - "Desbloquear solo cuando la pantalla esté encendida" - "La pantalla debe estar encendida para poder desbloquearla con la huella digital. Así, es menos probable que haya desbloqueos accidentales." + "Ahora puedes usar tu huella digital para desbloquear tu tablet o verificar que eres tú (por ejemplo, al iniciar sesión en aplicaciones o aprobar compras)" + "Ahora puedes usar tu huella digital para desbloquear tu dispositivo o verificar que eres tú (por ejemplo, al iniciar sesión en aplicaciones o aprobar compras)" + "Ahora puedes usar tu huella digital para desbloquear tu teléfono o verificar que eres tú (por ejemplo, al iniciar sesión en aplicaciones o aprobar compras)" + "Desbloquear solo si la pantalla está encendida" + "La pantalla debe estar encendida para desbloquearla con tu huella digital. Esto evita desbloqueos accidentales." "Pantalla, desbloqueo" "Más tarde" "Levanta el dedo y toca de nuevo" @@ -3490,8 +3487,7 @@ "Eliminar a %1$s de este dispositivo" "Ajustes de pantalla de bloqueo" "Añadir usuarios desde la pantalla de bloqueo" - - + "Cambiar al usuario administrador al conectarse" "¿Eliminarte a ti mismo?" "¿Eliminar este usuario?" "¿Quitar este perfil?" @@ -5673,6 +5669,9 @@ "Para usarlos, activa primero \"Mostrar controles de dispositivos\"" "Muestra el reloj en dos líneas cuando está disponible" "Reloj en dos líneas" + + + diff --git a/res/values-et/strings.xml b/res/values-et/strings.xml index 68f6c9530dd..9a19ac4b060 100644 --- a/res/values-et/strings.xml +++ b/res/values-et/strings.xml @@ -3493,8 +3493,7 @@ "Kustuta seadmest %1$s" "Lukustuskuva seaded" "Kasutajate lisamine lukustuskuval" - - + "Vaheta dokkimisel admin.-õigustega kasutajale" "Kas soovite kustutada iseenda?" "Kas kustutada kasutaja?" "Kas eemaldada profiil?" @@ -5676,6 +5675,9 @@ "Kasutamiseks lülitage esmalt sisse valik „Kuva seadme juhtimisvidinad“" "Kuva kaherealine kell, kui see on saadaval" "Kaherealine kell" + + + diff --git a/res/values-eu/strings.xml b/res/values-eu/strings.xml index 74617b869a5..ae62b4acc0e 100644 --- a/res/values-eu/strings.xml +++ b/res/values-eu/strings.xml @@ -588,12 +588,9 @@ "Erregistratze-prozesuaren aurrerapena: ehuneko %d" "Hatz-markaren ehuneko %d erregistratu da" "Gehitu da hatz-marka" - - - - - - + "Orain, tableta desblokeatzeko edo zeu zarela egiaztatzeko erabil dezakezu hatz-marka, hala nola aplikazioetan saioa hastean edo erosketak onartzean" + "Orain, gailua desblokeatzeko edo zeu zarela egiaztatzeko erabil dezakezu hatz-marka, hala nola aplikazioetan saioa hastean edo erosketak onartzean" + "Orain, telefonoa desblokeatzeko edo zeu zarela egiaztatzeko erabil dezakezu hatz-marka, hala nola aplikazioetan saioa hastean edo erosketak onartzean" "Desblokeatu pantaila aktibo badago bakarrik" "Pantailak aktibo egon behar du hatz-markarekin desblokeatu ahal izateko. Horrela, nahi gabe desblokeatzea ekiditen da." "pantaila, desblokeatu" @@ -3490,8 +3487,7 @@ "Ezabatu %1$s gailutik" "Pantaila blokeatuaren ezarpenak" "Gehitu erabiltzaileak pantaila blokeatutik" - - + "Aldatu administratzailea den erabiltzailera gailua oinarrian jarrita dagoenean" "Zeure burua ezabatu nahi duzu?" "Erabiltzaile hau ezabatu?" "Profil hau kendu nahi duzu?" @@ -5673,6 +5669,9 @@ "Erabiltzeko, lehendabizi aktibatu \"Erakutsi gailua kontrolatzeko aukerak\"" "Ahal denean, erakutsi erlojua bi lerrotan" "Bi lerroko erlojua" + + + diff --git a/res/values-fa/strings.xml b/res/values-fa/strings.xml index f1be1e61049..d71f91348a1 100644 --- a/res/values-fa/strings.xml +++ b/res/values-fa/strings.xml @@ -588,12 +588,9 @@ "%d درصد ثبت شده است" "درحال ثبت اثر انگشت: %d درصد" "اثر انگشت اضافه شد" - - - - - - + "ازاین‌پس می‌توانید از اثر انگشتتان برای باز کردن قفل رایانه لوحی یا به‌تأیید رساندن هویتتان (مثلاً هنگام ورود به سیستم برنامه‌ها یا تأیید خریدها) استفاده کنید" + "ازاین‌پس می‌توانید از اثر انگشتتان برای باز کردن قفل دستگاهتان یا به‌تأیید رساندن هویتتان (مثلاً هنگام ورود به سیستم برنامه‌ها یا تأیید خریدها) استفاده کنید" + "ازاین‌پس می‌توانید از اثر انگشتتان برای باز کردن قفل تلفنتان یا به‌تأیید رساندن هویتتان (مثلاً هنگام ورود به سیستم برنامه‌ها یا تأیید خریدها) استفاده کنید" "باز کردن قفل تنها هنگامی که صفحه‌نمایش روشن باشد" "پیش‌از اینکه بتوانید قفل را با اثر انگشتتان باز کنید، صفحه‌نمایش باید روشن باشد. این کار احتمال باز شدن قفل به‌صورت تصادفی را کاهش می‌دهد." "صفحه‌نمایش، باز کردن قفل" @@ -3490,8 +3487,7 @@ "حذف %1$s از این دستگاه" "تنظیمات صفحه قفل" "افزودن کاربران از صفحه قفل" - - + "هنگام اتصال به پایه، به کاربر سرپرست جابه‌جا شود" "حذف خودتان؟" "این کاربر حذف شود؟" "این نمایه حذف شود؟" @@ -5673,6 +5669,9 @@ "برای استفاده، ابتدا «نمایش کنترل‌های دستگاه» را روشن کنید" "نمایش ساعت دو خطی، درصورت دردسترس بودن" "ساعت دو خطی" + + + diff --git a/res/values-fi/strings.xml b/res/values-fi/strings.xml index cf65b8f03e9..65213e6a4cc 100644 --- a/res/values-fi/strings.xml +++ b/res/values-fi/strings.xml @@ -588,12 +588,9 @@ "%d prosenttia otettu käyttöön" "Sormenjäljen käyttöönotosta %d prosenttia valmiina" "Sormenjälki lisätty" - - - - - - + "Voit nyt käyttää sormenjälkeäsi tabletin lukituksen avaamiseen tai henkilöllisyyden todentamiseen esim. kirjautuessasi sovelluksiin tai hyväksyessäsi ostoksen" + "Voit nyt käyttää sormenjälkeäsi laitteen lukituksen avaamiseen tai henkilöllisyyden todentamiseen esim. kirjautuessasi sovelluksiin tai hyväksyessäsi ostoksen" + "Voit nyt käyttää sormenjälkeäsi puhelimen lukituksen avaamiseen tai henkilöllisyyden todentamiseen esim. kirjautuessasi sovelluksiin tai hyväksyessäsi ostoksen" "Avaa lukitus vain, kun näyttö on päällä" "Näytön täytyy olla päällä, jotta voit avata lukituksen sormenjäljellä. Näin on epätodennäköisempää, että lukitus avautuu vahingossa." "Näytön lukituksen avaaminen" @@ -3490,8 +3487,7 @@ "Poista %1$s laitteesta" "Lukitusnäytön asetukset" "Lisää käyttäjiä lukitusnäytöllä" - - + "Vaihda järjestelmänvalvojakäyttäjään telineessä" "Haluatko poistaa itsesi?" "Poistetaanko käyttäjä?" "Poistetaanko profiili?" @@ -5673,6 +5669,9 @@ "Jos haluat käyttää tätä, laita ensin päälle \"Näytä laitteiden hallinta\"" "Näytä kaksirivinen kello, kun saatavilla" "Kaksirivinen kello" + + + diff --git a/res/values-fr-rCA/strings.xml b/res/values-fr-rCA/strings.xml index c811222fd0b..460ceeaa502 100644 --- a/res/values-fr-rCA/strings.xml +++ b/res/values-fr-rCA/strings.xml @@ -588,12 +588,9 @@ "Inscription : %d pour cent" "Inscription de l\'empreinte digitale : %d pour cent" "Empreinte digitale ajoutée" - - - - - - + "Vous pouvez maintenant utiliser votre empreinte digitale pour déverrouiller votre tablette ou vérifier qu\'il s\'agit bien de vous, par exemple pour vous connecter à des applications ou approuver un achat" + "Vous pouvez maintenant utiliser votre empreinte digitale pour déverrouiller votre appareil ou vérifier qu\'il s\'agit bien de vous, par exemple pour vous connecter à des applications ou approuver un achat" + "Vous pouvez maintenant utiliser votre empreinte digitale pour déverrouiller votre téléphone ou vérifier qu\'il s\'agit bien de vous, par exemple pour vous connecter à des applications ou approuver un achat" "Déverrouiller uniquement lorsque l\'écran est allumé" "L\'écran doit être allumé avant que vous puissiez le déverrouiller avec votre empreinte digitale. Cela diminue les risques de déverrouillage accidentel." "Écran, déverrouiller" @@ -3490,8 +3487,7 @@ "Supp. %1$s de l\'appareil" "Paramètres de l\'écran de verrouillage" "Ajouter des utilisateurs à partir de l\'écran de verrouillage" - - + "Activer l\'utilisateur administrateur lorsque connecté" "Vous supprimer?" "Supprimer cet utilisateur?" "Supprimer ce profil?" @@ -5673,6 +5669,9 @@ "Pour les utiliser, activez d\'abord « Afficher les commandes de l\'appareil »" "Afficher l\'horloge à double ligne lorsqu\'elle est accessible" "Horloge à double ligne" + + + @@ -5765,7 +5764,7 @@ "Autoriser l\'accès aux contacts et au journal d\'appels?" "Un appareil Bluetooth, %1$s, souhaite accéder à vos contacts et à votre journal d\'appels. Cela comprend des données à propos des appels entrants et sortants.\n\nVous ne vous êtes jamais connecté à %2$s auparavant." "Luminosité" - "Verrouiller l\'écran" + "Affichage de l\'écran de verrouillage" "Apparence" "Couleur" "Autres paramètres d\'affichage" diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml index 42fa6dfd147..f1945bdef34 100644 --- a/res/values-fr/strings.xml +++ b/res/values-fr/strings.xml @@ -453,7 +453,7 @@ "Votre empreinte faciale sera supprimée de façon définitive et sécurisée.\n\nVous devrez ensuite utiliser un code, un schéma ou un mot de passe pour déverrouiller votre téléphone." "Déverrouillez votre téléphone par reconnaissance faciale" "Empreinte digitale" - "Lors utilisation déverrouillage par empreinte digitale" + "Déverrouillage par empreinte digitale" "Empreinte pour travail" "Gérer empreintes num." "Utiliser empr. dig. pour" @@ -590,12 +590,9 @@ "Enregistrement de l\'empreinte digitale à %d pour cent" "Empreinte digitale ajoutée" - - - - - - + "Vous pouvez désormais utiliser votre empreinte digitale pour déverrouiller votre tablette ou confirmer votre identité, par exemple pour vous connecter à des applis ou approuver un achat" + "Vous pouvez désormais utiliser votre empreinte digitale pour déverrouiller votre appareil ou confirmer votre identité, par exemple pour vous connecter à des applis ou approuver un achat" + "Vous pouvez désormais utiliser votre empreinte digitale pour déverrouiller votre téléphone ou confirmer votre identité, par exemple pour vous connecter à des applis ou approuver un achat" "Déverrouiller uniquement lorsque l\'écran est allumé" "L\'écran doit être allumé pour que vous puissiez le déverrouiller avec votre empreinte digitale. Cela réduit le risque de déverrouillage accidentel." "Déverrouillage de l\'écran" @@ -3492,8 +3489,7 @@ "Supp. %1$s de l\'appareil" "Paramètres de l\'écran de verrouillage" "Ajouter des utilisateurs depuis l\'écran de verrouillage" - - + "Passer en admin quand sur station d\'accueil" "Supprimer cet utilisateur ?" "Supprimer l\'utilisateur ?" "Supprimer ce profil ?" @@ -5675,6 +5671,9 @@ "Pour les utiliser, activez tout d\'abord \"Afficher les commandes de contrôle des appareils\"" "Afficher l\'horloge sur deux lignes lorsqu\'elle est disponible" "Horloge sur deux lignes" + + + diff --git a/res/values-gl/strings.xml b/res/values-gl/strings.xml index f2e3b37c357..98e40d97ae4 100644 --- a/res/values-gl/strings.xml +++ b/res/values-gl/strings.xml @@ -588,12 +588,9 @@ "%d por cento rexistrado" "Rexistrando impresión dixital (%d por cento)" "Engadiuse a impresión dixital" - - - - - - + "Agora podes utilizar a impresión dixital para desbloquear a tableta ou verificar a túa identidade (por exemplo, cando queiras iniciar sesión nunha aplicación ou aprobar unha compra)" + "Agora podes utilizar a impresión dixital para desbloquear o dispositivo ou verificar a túa identidade (por exemplo, cando queiras iniciar sesión nunha aplicación ou aprobar unha compra)" + "Agora podes utilizar a impresión dixital para desbloquear o teléfono ou verificar a túa identidade (por exemplo, cando queiras iniciar sesión nunha aplicación ou aprobar unha compra)" "Desbloquear só cando a pantalla estea acesa" "A pantalla debe estar acesa antes para que poidas desbloqueala coa impresión dixital. Deste xeito, é menos probable que se desbloquee de forma accidental." "Pantalla, desbloqueo" @@ -3490,8 +3487,7 @@ "Eliminar a %1$s do dispositivo" "Configuración da pantalla de bloqueo" "Engadir usuarios desde a pantalla de bloqueo" - - + "Cambiar ao usuario administrador ao poñelo na base" "Queres eliminarte a ti mesmo?" "Eliminar este usuario?" "Quitar este perfil?" @@ -5673,6 +5669,9 @@ "Para usar isto, primeiro activa Mostrar control de dispositivos" "Mostra o reloxo en dúas liñas se está dispoñible" "Reloxo en dúas liñas" + + + diff --git a/res/values-gu/strings.xml b/res/values-gu/strings.xml index ed06f0dad7d..5bfb27c9acd 100644 --- a/res/values-gu/strings.xml +++ b/res/values-gu/strings.xml @@ -588,12 +588,9 @@ "નોંધણી: %d ટકા" "ફિંગરપ્રિન્ટની નોંધણી કરવાની પ્રક્રિયા %d ટકા પૂર્ણ થઈ છે" "ફિંગરપ્રિન્ટ ઉમેરી" - - - - - - + "તમે ઍપમાં સાઇન ઇન કરો કે કોઈ ખરીદીને મંજૂરી આપો તેવા સમયે તમારું ટૅબ્લેટ અનલૉક કરવા અથવા સાઇન ઇન કરનાર તમે જ છો તેની ચકાસણી કરવા માટે, હવે તમે તમારી ફિંગરપ્રિન્ટનો ઉપયોગ કરી શકો છો" + "તમે ઍપમાં સાઇન ઇન કરો કે કોઈ ખરીદીને મંજૂરી આપો તેવા સમયે તમારું ડિવાઇસ અનલૉક કરવા અથવા સાઇન ઇન કરનાર તમે જ છો તેની ચકાસણી કરવા માટે, હવે તમે તમારી ફિંગરપ્રિન્ટનો ઉપયોગ કરી શકો છો" + "તમે ઍપમાં સાઇન ઇન કરો કે કોઈ ખરીદીને મંજૂરી આપો તેવા સમયે તમારો ફોન અનલૉક કરવા અથવા સાઇન ઇન કરનાર તમે જ છો તેની ચકાસણી કરવા માટે, હવે તમે તમારી ફિંગરપ્રિન્ટનો ઉપયોગ કરી શકો છો" "જ્યારે સ્ક્રીન ચાલુ હોય, ત્યારે જ અનલૉક કરો" "તમે તમારી ફિંગરપ્રિન્ટ વડે અનલૉક કરી શકો તે પહેલાં સ્ક્રીન ચાલુ હોવી આવશ્યક છે. આમ કરવાથી આકસ્મિક રીતે અનલૉક થવાની શક્યતા ઘટે છે." "સ્ક્રીન, અનલૉક કરો" @@ -3490,8 +3487,7 @@ "આ ડિવાઇસમાંથી %1$sને કાઢી નાખો" "લૉક સ્ક્રીન સેટિંગ" "લૉક સ્ક્રીનમાંથી વપરાશકર્તાઓને ઉમેરો" - - + "ડૉક કર્યુ હોય ત્યારે ઍડમિન વપરાશકર્તા પર સ્વિચ કરો" "તમને પોતાને કાઢી નાખીએ?" "આ વપરાશકર્તા ડિલીટ કરીએ?" "આ પ્રોફાઇલ દૂર કરીએ?" @@ -5673,6 +5669,9 @@ "ઉપયોગ કરવા માટે, પહેલા \"ડિવાઇસના નિયંત્રણો બતાવો\" ચાલુ કરો" "ઉપલબ્ધ હોય ત્યારે ડબલ-લાઇન ઘડિયાળ બતાવો" "ડબલ-લાઇન ઘડિયાળ" + + + diff --git a/res/values-hi/strings.xml b/res/values-hi/strings.xml index 4eea8d43146..27ccfea49ce 100644 --- a/res/values-hi/strings.xml +++ b/res/values-hi/strings.xml @@ -588,12 +588,9 @@ "%d प्रतिशत रजिस्टर" "फ़िंगरप्रिंट सेट अप करने की प्रक्रिया %d प्रतिशत तक पूरी हो चुकी है" "फ़िंगरप्रिंट जोड़ा गया" - - - - - - + "अब अपने फ़िंगरप्रिंट की मदद से, टैबलेट को अनलॉक किया जा सकता है. इसके अलावा, किसी ऐप्लिकेशन में साइन इन करने, किसी खरीदारी की मंज़ूरी देने या ऐसे और काम करने के दौरान, अपनी पहचान की पुष्टि करने के लिए भी फ़िंगरप्रिंट का इस्तेमाल किया जा सकता है" + "अब अपने फ़िंगरप्रिंट की मदद से, डिवाइस को अनलॉक किया जा सकता है. इसके अलावा, किसी ऐप्लिकेशन में साइन इन करने, किसी खरीदारी की मंज़ूरी देने या ऐसे और काम करने के दौरान, अपनी पहचान की पुष्टि करने के लिए भी फ़िंगरप्रिंट का इस्तेमाल किया जा सकता है" + "अब अपने फ़िंगरप्रिंट की मदद से, फ़ोन को अनलॉक किया जा सकता है. इसके अलावा, किसी ऐप्लिकेशन में साइन इन करने, किसी खरीदारी की मंज़ूरी देने या ऐसे और काम करने के दौरान, अपनी पहचान की पुष्टि करने के लिए भी फ़िंगरप्रिंट का इस्तेमाल किया जा सकता है" "स्क्रीन चालू होने पर ही अनलॉक होगा" "फ़िंगरप्रिंट अनलॉक की सुविधा का इस्तेमाल करने से पहले, आपके डिवाइस की स्क्रीन चालू होनी चाहिए. इससे गलती से डिवाइस अनलॉक होने की संभावना कम होती है." "स्क्रीन, अनलॉक करें" @@ -3490,8 +3487,7 @@ "इस उपकरण से %1$s को मिटाएं" "लॉक स्‍क्रीन सेटिंग" "लॉक स्क्रीन से उपयोगकर्ताओं को जोड़ें" - - + "डिवाइस के डॉक होने पर एडमिन खाते पर जाएं" "खुद को मिटाएं?" "इस उपयोगकर्ता को हटाएं?" "इस प्रोफ़ाइल को निकालें?" @@ -5673,6 +5669,9 @@ "इसका इस्तेमाल करने के लिए, सबसे पहले \"डिवाइस कंट्रोल दिखाएं\" को चालू करें" "उपलब्ध होने पर, दो लाइन में समय दिखाएं" "दो लाइन में समय दिखाएं" + + + diff --git a/res/values-hr/strings.xml b/res/values-hr/strings.xml index e7588ff4cd2..6958f633d9b 100644 --- a/res/values-hr/strings.xml +++ b/res/values-hr/strings.xml @@ -594,12 +594,9 @@ "Otisak prsta je dodan" - - - - - - + "Sad svojim otiskom prsta možete otključati tablet ili potvrditi da ste to vi, na primjer prilikom prijave u aplikacije ili odobravanja kupnje" + "Sad svojim otiskom prsta možete otključati uređaj ili potvrditi da ste to vi, na primjer prilikom prijave u aplikacije ili odobravanja kupnje" + "Sad svojim otiskom prsta možete otključati telefon ili potvrditi da ste to vi, na primjer prilikom prijave u aplikacije ili odobravanja kupnje" "Otključavanje samo kad je zaslon uključen" "Zaslon mora biti uključen da biste ga mogli otključati otiskom prsta. Time se smanjuje mogućnost slučajnog otključavanja." "Zaslon, otključati" @@ -3534,8 +3531,7 @@ "%1$s: brisanje s uređaja" "Postavke zaključavanja zaslona" "Dodavanje korisnika sa zaključanog zaslona" - - + "Na priključnoj stanici prijeđi na administratora" "Izbrisati sebe?" "Želite li izbrisati ovog korisnika?" "Ukloniti profil?" @@ -5762,6 +5758,9 @@ "Za upotrebu najprije uključite opciju \"Prikaži kontrole uređaja\"." "Prikaži sat s dva retka kad je dostupan" "Sat s dva retka" + + + diff --git a/res/values-hu/strings.xml b/res/values-hu/strings.xml index 9c75629b6a8..123c86d8170 100644 --- a/res/values-hu/strings.xml +++ b/res/values-hu/strings.xml @@ -588,12 +588,9 @@ "Regisztrálva %d százalék" "Ujjlenyomat regisztrálása folyamatban – %d százalék" "Ujjlenyomat hozzáadva" - - - - - - + "Mostantól használhatja ujjlenyomatát táblagépe zárolásának feloldásához vagy személyazonossága igazolásához (például amikor alkalmazásokba jelentkezik be, vagy vásárlást hagy jóvá)." + "Mostantól használhatja ujjlenyomatát eszköze zárolásának feloldásához vagy személyazonossága igazolásához (például amikor alkalmazásokba jelentkezik be, vagy vásárlást hagy jóvá)." + "Mostantól használhatja ujjlenyomatát telefonja zárolásának feloldásához vagy személyazonossága igazolásához (például amikor alkalmazásokba jelentkezik be, vagy vásárlást hagy jóvá)." "Csak akkor oldja fel a képernyőt, ha be van kapcsolva a képernyő" "A képernyőnek bekapcsolva kell lennie, hogy feloldhassa az ujjlenyomatával. Így kisebb az esélye a véletlen feloldásoknak." "Képernyő, feloldás" @@ -3490,8 +3487,7 @@ "%1$s törlése" "Lezárási képernyő beállításai" "Felhasználók hozzáadása a lezárási képernyőről" - - + "Dokkoláskor váltás adminisztrátor felhasználóra" "Törli önmagát?" "Törli a felhasználót?" "Eltávolítja a profilt?" @@ -5673,6 +5669,9 @@ "A használatához előbb kapcsolja be az „Eszközvezérlők megjelenítése” beállítást" "Kétsoros óra megjelenítése, amikor rendelkezésre áll" "Kétsoros óra" + + + diff --git a/res/values-hy/strings.xml b/res/values-hy/strings.xml index b7f7b30d117..e86dedd658a 100644 --- a/res/values-hy/strings.xml +++ b/res/values-hy/strings.xml @@ -588,12 +588,9 @@ "Գրանցվել է %d տոկոսով" "Մատնահետքը գրանցվել է %d տոկոսով" "Մատնահետքն ավելացվեց" - - - - - - + "Այժմ կարող եք օգտագործել ձեր մատնահետքը՝ պլանշետն ապակողպելու կամ ձեր ինքնությունը հաստատելու համար, օր․՝ հավելվածներ մտնելիս կամ որևէ գնում հաստատելիս" + "Այժմ կարող եք օգտագործել ձեր մատնահետքը՝ սարքն ապակողպելու կամ ձեր ինքնությունը հաստատելու համար, օր․՝ հավելվածներ մտնելիս կամ որևէ գնում հաստատելիս" + "Այժմ կարող եք օգտագործել ձեր մատնահետքը՝ հեռախոսն ապակողպելու կամ ձեր ինքնությունը հաստատելու համար, օր․՝ հավելվածներ մտնելիս կամ որևէ գնում հաստատելիս" "Ապակողպել, միայն երբ էկրանը միացված է" "Նախքան սարքը մատնահետքով ապակողպելը անհրաժեշտ է միացնել էկրանը։ Սա նվազեցնում է պատահական ապակողպման հավանականությունը։" "Էկրան, ապակողպում" @@ -3490,8 +3487,7 @@ "Ջնջել %1$s-ին այս սարքից" "Էկրանի կողպման կարգավորումները" "Ավելացնել օգտատերեր կողպէկրանից" - - + "Դոկ-կայանում անցնել ադմինիստրատորի ռեժիմին" "Ջնջե՞լ ձեզ:" "Ջնջե՞լ օգտատիրոջը" "Հեռացնե՞լ այս պրոֆիլը:" @@ -5673,6 +5669,9 @@ "Օգտագործելու համար նախ միացրեք «Ցույց տալ սարքի կառավարման տարրերը» կարգավորումը" "Առկայության դեպքում ցույց տալ երկտող ժամացույցը" "Երկտող ժամացույց" + + + diff --git a/res/values-in/strings.xml b/res/values-in/strings.xml index 8af7cdf8655..f463ad6f07b 100644 --- a/res/values-in/strings.xml +++ b/res/values-in/strings.xml @@ -588,12 +588,9 @@ "Terdaftar %d persen" "Mendaftarkan sidik jari %d persen" "Sidik jari ditambahkan" - - - - - - + "Anda kini dapat menggunakan sidik jari untuk membuka kunci tablet atau memverifikasi diri Anda, seperti saat login ke aplikasi atau menyetujui pembelian" + "Anda kini dapat menggunakan sidik jari untuk membuka kunci perangkat atau memverifikasi diri Anda, seperti saat login ke aplikasi atau menyetujui pembelian" + "Anda kini dapat menggunakan sidik jari untuk membuka kunci ponsel atau memverifikasi diri Anda, seperti saat login ke aplikasi atau menyetujui pembelian" "Buka kunci hanya saat layar aktif" "Layar harus aktif sebelum Anda dapat membuka kunci dengan sidik jari. Hal ini mengurangi peristiwa kunci tidak sengaja terbuka." "Layar, Buka kunci" @@ -3490,8 +3487,7 @@ "Hapus %1$s di perangkat" "Setelan layar kunci" "Tambahkan pengguna dari layar kunci" - - + "Beralih ke pengguna admin saat terpasang ke dok" "Hapus diri Anda sendiri?" "Hapus pengguna ini?" "Buang profil ini?" @@ -5673,6 +5669,9 @@ "Untuk menggunakannya, aktifkan \"Tampilkan kontrol perangkat\" terlebih dahulu" "Menampilkan jam dua baris jika tersedia" "Jam dua baris" + + + diff --git a/res/values-is/strings.xml b/res/values-is/strings.xml index fb88c8ed709..166e69e8ceb 100644 --- a/res/values-is/strings.xml +++ b/res/values-is/strings.xml @@ -588,12 +588,9 @@ "%d prósent skráð" "Skráir fingrafar %d prósent" "Fingrafari bætt við" - - - - - - + "Nú geturðu notað fingrafarið til að taka spjaldtölvuna úr lás eða til að staðfesta hver þú ert, t.d. þegar þú skráir þig inn í forrit eða samþykkir kaup" + "Nú geturðu notað fingrafarið til að taka tækið úr lás eða til að staðfesta hver þú ert, t.d. þegar þú skráir þig inn í forrit eða samþykkir kaup" + "Nú geturðu notað fingrafarið til að taka símann úr lás eða til að staðfesta hver þú ert, t.d. þegar þú skráir þig inn í forrit eða samþykkir kaup" "Aðeins taka úr lás ef kveikt er á skjá" "Það verður að vera kveikt á skjánum áður en þú tekur hann úr lás með fingrafarinu þínu. Þetta dregur úr hættu á að taka skjáinn óvart úr lás." "Skjár, taka úr lás" @@ -3490,8 +3487,7 @@ "Eyða %1$s úr þessu tæki" "Stillingar fyrir læstan skjá" "Bæta við notendum af lásskjánum" - - + "Skipta yfir í stjórnanda þegar tækið er í dokku" "Eyða sjálfum/sjálfri þér?" "Viltu eyða þessum notanda?" "Fjarlægja þetta snið?" @@ -5673,6 +5669,9 @@ "Kveiktu fyrst á „Sýna tækjastjórnun“ til að nota þetta" "Sýna klukku í tveimur línum þegar hægt er" "Klukka í tveimur línum" + + + diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml index f6e8688143b..5a8660b4e2e 100644 --- a/res/values-it/strings.xml +++ b/res/values-it/strings.xml @@ -588,14 +588,11 @@ "Completamento registrazione: %d per cento" "Registrazione dell\'impronta al %d percento" "Impronta aggiunta" - - - - - - + "Ora puoi usare l\'impronta per sbloccare il tablet o verificare la tua identità, ad esempio quando accedi alle app o approvi un acquisto" + "Ora puoi usare l\'impronta per sbloccare il dispositivo o verificare la tua identità, ad esempio quando accedi alle app o approvi un acquisto" + "Ora puoi usare l\'impronta per sbloccare il telefono o verificare la tua identità, ad esempio quando accedi alle app o approvi un acquisto" "Sblocca solo quando lo schermo è attivo" - "Devi attivare lo schermo prima di poter sbloccare con la tua impronta. In questo modo si riduce la probabilità di sblocchi accidentali." + "Per usare lo sblocco con l\'impronta, lo schermo deve essere attivo. In questo modo si riduce la probabilità di sblocchi accidentali." "Schermo, sblocco" "Più tardi" "Solleva, quindi tocca di nuovo" @@ -3490,8 +3487,7 @@ "Elimina %1$s da dispositivo" "Impostazioni schermata di blocco" "Aggiungi utenti da schermata di blocco" - - + "Passa a utente amministratore se inserito nel dock" "Eliminare te stesso?" "Eliminare questo utente?" "Rimuovere questo profilo?" @@ -5673,6 +5669,9 @@ "Per usare i controlli, devi prima attivare l\'opzione \"Mostra controlli dei dispositivi\"" "Mostra l\'orologio su due righe quando è disponibile" "Orologio su due righe" + + + diff --git a/res/values-iw/strings.xml b/res/values-iw/strings.xml index ddac746e62f..3c58a5a2a11 100644 --- a/res/values-iw/strings.xml +++ b/res/values-iw/strings.xml @@ -600,12 +600,9 @@ "טביעת האצבע שלך נקלטה" - - - - - - + "עכשיו אפשר להשתמש בטביעת האצבע כדי לבטל את נעילת הטאבלט או כדי לאמת את הזהות, למשל כשנכנסים לחשבון באפליקציות או כשמאשרים רכישה" + "עכשיו אפשר להשתמש בטביעת האצבע כדי לבטל את נעילת המכשיר או כדי לאמת את הזהות, למשל כשנכנסים לחשבון באפליקציות או כשמאשרים רכישה" + "עכשיו אפשר להשתמש בטביעת האצבע כדי לבטל את נעילת הטלפון או כדי לאמת את הזהות, למשל כשנכנסים לחשבון באפליקציות או כשמאשרים רכישה" "ביטול נעילה רק כשהמסך פועל" "המסך צריך להיות מופעל לפני ביטול נעילה עם טביעת אצבע, כדי לצמצם את ביטול הנעילה בטעות." "מסך, ביטול נעילה" @@ -3578,8 +3575,7 @@ "מחיקת %1$s ממכשיר זה" "הגדרות מסך נעילה" "הוספת משתמשים ממסך הנעילה" - - + "מעבר למשתמש עם הרשאת אדמין במהלך עגינה" "האם למחוק אותך?" "למחוק את המשתמש/ת?" "האם להסיר פרופיל זה?" @@ -5851,6 +5847,9 @@ "כדי להשתמש באפשרות הזו, קודם צריך להפעיל את \'הצגת פקדי המכשירים\'" "הצגת השעון עם שתי השורות כשאפשר" "שעון עם שתי שורות" + + + diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml index 9cf3034872e..29d33f86854 100644 --- a/res/values-ja/strings.xml +++ b/res/values-ja/strings.xml @@ -588,12 +588,9 @@ "登録済み: %d パーセント" "指紋の登録中: %d パーセント" "指紋の登録完了" - - - - - - + "指紋認証を使用して、タブレットのロック解除や本人確認(アプリへのログインや購入の承認など)を行えるようになりました" + "指紋認証を使用して、デバイスのロック解除や本人確認(アプリへのログインや購入の承認など)を行えるようになりました" + "指紋認証を使用して、スマートフォンのロック解除や本人確認(アプリへのログインや購入の承認など)を行えるようになりました" "画面が ON のときのみロック解除" "指紋認証を使用するには画面が ON になっている必要があります。これにより、意図しないロック解除が起こりにくくなります。" "画面、ロック解除" @@ -3490,8 +3487,7 @@ "このデバイスから%1$sを削除" "ロック画面の設定" "ロック画面からユーザーを追加" - - + "ホルダー装着時に管理者ユーザーに切り替える" "自分を削除しますか?" "このユーザーを削除しますか?" "プロファイルを削除しますか?" @@ -5673,6 +5669,9 @@ "使用するには、[デバイス コントロールを表示] を ON にしてください" "使用可能な場合はダブルライン時計を表示します" "ダブルライン時計" + + + diff --git a/res/values-ka/strings.xml b/res/values-ka/strings.xml index bbe14504e29..edf457e5bc6 100644 --- a/res/values-ka/strings.xml +++ b/res/values-ka/strings.xml @@ -588,12 +588,9 @@ "რეგისტრირებულია %d პროცენტი" "მიმდინარეობს თითის ანაბეჭდის რეგისტრაცია, %d პროცენტი" "თითის ანაბეჭდი დამატებულია" - - - - - - + "ახლა უკვე შეგიძლიათ თითის ანაბეჭდის გამოყენება ტაბლეტის განსაბლოკად ან თქვენი ვინაობის დასადასტურებლად, მაგალითად, როცა აპებში შედიხართ ან შენაძენს ადასტურებთ" + "ახლა უკვე შეგიძლიათ თითის ანაბეჭდის გამოყენება მოწყობილობის განსაბლოკად ან თქვენი ვინაობის დასადასტურებლად, მაგალითად, როცა აპებში შედიხართ ან შენაძენს ადასტურებთ" + "ახლა უკვე შეგიძლიათ თითის ანაბეჭდის გამოყენება ტელეფონის განსაბლოკად ან თქვენი ვინაობის დასადასტურებლად, მაგალითად, როცა აპებში შედიხართ ან შენაძენს ადასტურებთ" "განბლოკვა მხოლოდ მაშინ, როცა ეკრანი ჩართულია" "ეკრანი ჩართული უნდა იყოს, სანამ თითის ანაბეჭდით განბლოკავთ. ეს ამცირებს შემთხვევით განბლოკვას." "ეკრანის განბლოკვა" @@ -3490,8 +3487,7 @@ "წაშალე %1$s ამ მოწყობილობიდან" "ჩაკეტილი ეკრანის პარამეტრები" "ჩაკეტილი ეკრანიდან მომხმარებლების დამატება" - - + "ადმინისტრატორ მომხმარებელზე გადართვა ჩამაგრებისას" "წავშალო თქვენი ანგარიში?" "წაიშალოს ეს მომხმარებელი?" "გსურთ ამ პროფილის წაშლა?" @@ -5673,6 +5669,9 @@ "გამოსაყენებლად, ჯერ ჩართეთ „მოწყობილობების მართვის საშუალებების ჩვენება“" "ორხაზიანი საათის ჩვენება, როცა ხელმისაწვდომია" "ორხაზიანი საათი" + + + diff --git a/res/values-kk/strings.xml b/res/values-kk/strings.xml index 34e48c1d175..a40ab1aa4c6 100644 --- a/res/values-kk/strings.xml +++ b/res/values-kk/strings.xml @@ -588,12 +588,9 @@ "%d пайыз тіркелді" "Саусақ ізі тіркелуде: %d пайыз." "Саусақ ізі енгізілді" - - - - - - + "Енді планшет құлпын ашу немесе жеке басыңызды растау үшін (мысалы, қолданбаларға кіргенде немесе бірдеңе сатып алғанда) саусақ ізін пайдалана аласыз." + "Енді құрылғы құлпын ашу немесе жеке басыңызды растау үшін (мысалы, қолданбаларға кіргенде немесе бірдеңе сатып алғанда) саусақ ізін пайдалана аласыз." + "Енді телефон құлпын ашу немесе жеке басыңызды растау үшін (мысалы, қолданбаларға кіргенде немесе бірдеңе сатып алғанда) саусақ ізін пайдалана аласыз." "Экран қосулы кезде ғана құлпын ашу" "Саусақ ізімен құлпын ашпас бұрын экран қосулы болуы керек. Мұндайда кездейсоқ ашып қою сирек болады." "Экран құлпын ашу" @@ -3490,8 +3487,7 @@ "%1$s осы құралдан жою" "Құлып экранының параметрлері" "Құлыптаулы экраннан пайдаланушыларды қосу" - - + "Қондырылғанда әкімші пайдаланушыға ауысу" "Өзіңізді жоясыз ба?" "Пайдаланушы жойылсын ба?" "Осы профил. жою керек пе?" @@ -5673,6 +5669,9 @@ "Пайдалану үшін алдымен \"Құрылғыны басқару элементтерін көрсету\" параметрін қосыңыз." "Қолжетімді болған кезде, екі қатарлы сағатты көрсету" "Екі қатарлы сағат" + + + diff --git a/res/values-km/strings.xml b/res/values-km/strings.xml index 9e5d61c6c78..b7c7ef4a011 100644 --- a/res/values-km/strings.xml +++ b/res/values-km/strings.xml @@ -588,12 +588,9 @@ "ចុះឈ្មោះបាន %d ភាគរយ" "កំពុងចុះឈ្មោះ​ស្នាមម្រាមដៃ %d ភាគរយ" "បានបញ្ចូល​ស្នាមម្រាមដៃ​រួចហើយ" - - - - - - + "ឥឡូវនេះ អ្នកអាចប្រើ​ស្នាមម្រាមដៃរបស់អ្នក ដើម្បីដោះសោ​ថេប្លេតរបស់អ្នក ឬផ្ទៀងផ្ទាត់​ថាជាអ្នក ដូចជានៅពេលអ្នក​ចូលគណនីកម្មវិធី ឬយល់ព្រមលើ​ការទិញជាដើម" + "ឥឡូវនេះ អ្នកអាចប្រើ​ស្នាមម្រាមដៃរបស់អ្នក ដើម្បីដោះសោ​ឧបករណ៍របស់អ្នក ឬផ្ទៀងផ្ទាត់​ថាជាអ្នក ដូចជានៅពេលអ្នក​ចូលគណនីកម្មវិធី ឬយល់ព្រមលើ​ការទិញជាដើម" + "ឥឡូវនេះ អ្នកអាចប្រើ​ស្នាមម្រាមដៃរបស់អ្នក ដើម្បីដោះសោ​ទូរសព្ទរបស់អ្នក ឬផ្ទៀងផ្ទាត់​ថាជាអ្នក ដូចជានៅពេលអ្នក​ចូលគណនីកម្មវិធី ឬយល់ព្រមលើ​ការទិញជាដើម" "ដោះសោតែនៅពេលដែលអេក្រង់បើកប៉ុណ្ណោះ" "អេក្រង់ត្រូវតែបើក មុនពេលអ្នកអាចដោះសោដោយប្រើស្នាមម្រាមដៃរបស់អ្នក។ ការធ្វើបែបនេះធ្វើឱ្យការដោះសោដោយចៃដន្យមិនទំនងជាកើតឡើង។" "អេក្រង់ ដោះសោ" @@ -3490,8 +3487,7 @@ "លុប %1$s ពី​ឧបករណ៍​នេះ" "ការកំណត់អេក្រង់ចាក់សោ" "បញ្ចូល​អ្នក​ប្រើប្រាស់​ពី​អេក្រង់​ចាក់សោ" - - + "ប្ដូរទៅអ្នកប្រើប្រាស់ដែលជាអ្នកគ្រប់គ្រងពេលភ្ជាប់" "លុប​ខ្លួន​ឯង​ផ្ទាល់?" "លុបអ្នកប្រើប្រាស់​នេះ?" "លុប​ប្រវត្តិ​រូប​នេះ?" @@ -5673,6 +5669,9 @@ "ដើម្បីប្រើ សូមបើក \"បង្ហាញផ្ទាំងគ្រប់គ្រងឧបករណ៍\" ជាមុនសិន" "បង្ហាញ​នាឡិកា​ពីរជួរ នៅពេល​ដែលមាន" "នាឡិកា​ពីរជួរ" + + + diff --git a/res/values-kn/strings.xml b/res/values-kn/strings.xml index 12ad9fa3859..8ab671e2e3e 100644 --- a/res/values-kn/strings.xml +++ b/res/values-kn/strings.xml @@ -588,12 +588,9 @@ "ಶೇಕಡಾ %d ನೋಂದಣಿ ಮಾಡಲಾಗಿದೆ" "ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ನೋಂದಣಿ ಶೇಕಡಾ %d ಆಗಿದೆ" "ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಸೇರಿಸಲಾಗಿದೆ" - - - - - - + "ನೀವು ಆ್ಯಪ್‌ಗಳಿಗೆ ಸೈನ್ ಇನ್ ಮಾಡಿದಾಗ ಅಥವಾ ಖರೀದಿಯೊಂದನ್ನು ಅನುಮೋದಿಸಿದಾಗ, ನಿಮ್ಮ ಟ್ಯಾಬ್ಲೆಟ್ ಅನ್ನು ಅನ್‌ಲಾಕ್ ಮಾಡಲು ಅಥವಾ ಅದು ನೀವೇ ಎಂಬುದನ್ನು ದೃಢೀಕರಿಸಲು ಈಗ ನೀವು ನಿಮ್ಮ ಫಿಂಗರ್‌ ಪ್ರಿಂಟ್ ಅನ್ನು ಬಳಸಬಹುದು" + "ನೀವು ಆ್ಯಪ್‌ಗಳಿಗೆ ಸೈನ್ ಇನ್ ಮಾಡಿದಾಗ ಅಥವಾ ಖರೀದಿಯೊಂದನ್ನು ಅನುಮೋದಿಸಿದಾಗ, ನಿಮ್ಮ ಸಾಧನವನ್ನು ಅನ್‌ಲಾಕ್ ಮಾಡಲು ಅಥವಾ ಅದು ನೀವೇ ಎಂಬುದನ್ನು ದೃಢೀಕರಿಸಲು ಈಗ ನೀವು ನಿಮ್ಮ ಫಿಂಗರ್‌ ಪ್ರಿಂಟ್ ಅನ್ನು ಬಳಸಬಹುದು" + "ನೀವು ಆ್ಯಪ್‌ಗಳಿಗೆ ಸೈನ್ ಇನ್ ಮಾಡಿದಾಗ ಅಥವಾ ಖರೀದಿಯೊಂದನ್ನು ಅನುಮೋದಿಸಿದಾಗ, ನಿಮ್ಮ ಫೋನ್ ಅನ್ನು ಅನ್‌ಲಾಕ್ ಮಾಡಲು ಅಥವಾ ಅದು ನೀವೇ ಎಂಬುದನ್ನು ದೃಢೀಕರಿಸಲು ಈಗ ನೀವು ನಿಮ್ಮ ಫಿಂಗರ್‌ ಪ್ರಿಂಟ್ ಅನ್ನು ಬಳಸಬಹುದು" "ಸ್ಕ್ರೀನ್ ಆನ್ ಆಗಿರುವಾಗ ಮಾತ್ರ ಅನ್‌ಲಾಕ್ ಮಾಡಿ" "ನಿಮ್ಮ ಫಿಂಗರ್‌ ಪ್ರಿಂಟ್ ಮೂಲಕ ಅನ್‌ಲಾಕ್ ಮಾಡುವ ಮೊದಲು ಸ್ಕ್ರೀನ್ ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಬೇಕು. ಇದು ಆಕಸ್ಮಿಕ ಅನ್‌ಲಾಕ್ ಮಾಡುವ ಸಾಧ್ಯತೆಯನ್ನು ಕಡಿಮೆ ಮಾಡುತ್ತದೆ." "ಸ್ಕ್ರೀನ್, ಅನ್‌ಲಾಕ್‌" @@ -3490,8 +3487,7 @@ "ಈ ಸಾಧನದಿಂದ %1$s ಅಳಿಸಿ" "ಪರದೆ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಲಾಕ್ ಮಾಡಿ" "ಲಾಕ್ ಸ್ಕ್ರೀನ್‌ನಿಂದ ಬಳಕೆದಾರರನ್ನು ಸೇರಿಸಿ" - - + "ಡಾಕ್ ಮಾಡಿದಾಗ ನಿರ್ವಾಹಕ ಬಳಕೆದಾರರಿಗೆ ಬದಲಾಯಿಸಿ" "ನಿಮ್ಮನ್ನು ಅಳಿಸುವುದೇ?" "ಈ ಬಳಕೆದಾರರನ್ನು ಅಳಿಸುವುದೇ?" "ಈ ಪ್ರೊಫೈಲ್ ತೆಗೆದುಹಾಕುವುದೇ?" @@ -5673,6 +5669,9 @@ "ಅದನ್ನು ಬಳಸಲು, \"ಸಾಧನ ನಿಯಂತ್ರಣಗಳನ್ನು ತೋರಿಸಿ\" ಎಂಬುದನ್ನು ಮೊದಲು ಆನ್ ಮಾಡಿ" "ಲಭ್ಯವಿದ್ದಾಗ ಡಬಲ್ ಲೈನ್ ಗಡಿಯಾರವನ್ನು ತೋರಿಸಿ" "ಡಬಲ್ ಲೈನ್ ಗಡಿಯಾರ" + + + diff --git a/res/values-ko/strings.xml b/res/values-ko/strings.xml index bafa7b077c3..9f0c26f9e71 100644 --- a/res/values-ko/strings.xml +++ b/res/values-ko/strings.xml @@ -594,12 +594,9 @@ "지문 추가됨" - - - - - - + "이제 지문을 사용하여 태블릿을 잠금 해제하거나 앱 로그인, 구매 승인 등을 위해 본인 인증을 진행할 수 있습니다." + "이제 지문을 사용하여 기기를 잠금 해제하거나 앱 로그인, 구매 승인 등을 위해 본인 인증을 진행할 수 있습니다." + "이제 지문을 사용하여 휴대전화를 잠금 해제하거나 앱 로그인, 구매 승인 등을 위해 본인 인증을 진행할 수 있습니다." "화면이 켜져 있을 때만 잠금 해제" "지문으로 잠금 해제하려면 먼저 화면이 켜져 있어야 합니다. 이를 설정하면 실수로 잠금 해제될 가능성이 작아집니다." "화면 잠금 해제" @@ -3496,8 +3493,7 @@ "이 기기에서 %1$s님 삭제" "잠금 화면 설정" "잠금 화면에서 사용자 추가" - - + "도킹 시 관리자로 전환" "본인을 삭제하시겠습니까?" "사용자를 삭제하시겠습니까?" "프로필을 삭제할까요?" @@ -5679,6 +5675,9 @@ "사용하려면 먼저 \'기기 제어 표시\'를 켜세요." "사용 가능한 경우 두 줄 시계 표시" "두 줄 시계" + + + diff --git a/res/values-ky/strings.xml b/res/values-ky/strings.xml index 453cda003c6..689a98d4c62 100644 --- a/res/values-ky/strings.xml +++ b/res/values-ky/strings.xml @@ -588,12 +588,9 @@ "%d пайыз катталды" "Манжа изи катталууда: %d пайыз" "Манжа изи кошулду" - - - - - - + "Эми манжаңыздын изи менен планшетиңиздин кулпусун ачып же колдонмолорго кирүүдө өзүңүздү же сатып алууну ырастай аласыз" + "Эми манжаңыздын изи менен түзмөгүңүздүн кулпусун ачып же колдонмолорго кирүүдө өзүңүздү же сатып алууну ырастай аласыз" + "Эми манжаңыздын изи менен телефонуңуздун кулпусун ачып же колдонмолорго кирүүдө өзүңүздү же сатып алууну ырастай аласыз" "Кулпусу экран күйүп турганда гана ачылсын" "Кулпуну манжа изи менен ачуу үчүн экран күйгүзүлүшү керек. Бул кулпуну кокустан ачып алуунун алдын алат." "Экран, кулпуну ачуу" @@ -3490,8 +3487,7 @@ "%1$s бул түзмөктөн жок кылуу" "Экранды кулпулоо параметрлери" "Кулпуланган экрандан колдонуучуларды кошуу" - - + "Док бекетке туташканда админге которулуңуз" "Өзүңүздү жок кылалыбы?" "Бул колдонуучуну өчүрөсүзбү?" "Профилди алып салалыбы?" @@ -3548,7 +3544,7 @@ "Башка төлөм колдонмосу ачылып турбаса" "Тийгизип төлөө терминалында ушуну колдонуңуз:" "Терминалдан төлөө" - "Төлөм колдонмосун жөндөп туруп, телефондун арткы бетин тийбей төлөө белгиси түшүрүлгөн терминалга жакындатыңыз." + "Төлөм колдонмосун жөндөп туруп, телефондун арткы бетин тийгизип төлөө белгиси түшүрүлгөн терминалга жакындатыңыз." "Түшүндүм" "Дагы…" "Демейки төлөм колдонмосун коюу" @@ -5673,6 +5669,9 @@ "Колдонуу үчүн адегенде \"Түзмөктү башкаруу элементтерин көрсөтүү\" параметрин күйгүзүңүз" "Кош саптуу саат жеткиликтүү болгондо көрүнөт" "Кош саптуу саат" + + + diff --git a/res/values-lo/strings.xml b/res/values-lo/strings.xml index aa18d5becdd..872f97fd5bd 100644 --- a/res/values-lo/strings.xml +++ b/res/values-lo/strings.xml @@ -588,12 +588,9 @@ "ລົງທະບຽນແລ້ວ %d ເປີເຊັນ" "ກຳລັງລົງທະບຽນລາຍນິ້ວມື %d ເປີເຊັນ" "ເພີ່ມລາຍນິ້ວມືແລ້ວ" - - - - - - + "ຕອນນີ້ທ່ານສາມາດໃຊ້ລາຍນິ້ວມືຂອງທ່ານເພື່ອປົດລັອກແທັບເລັດຂອງທ່ານ ຫຼື ຢັ້ງຢືນວ່າແມ່ນທ່ານໄດ້ແລ້ວ, ເຊັ່ນ: ໃນເວລາທີ່ທ່ານເຂົ້າສູ່ລະບົບຫາແອັບ ຫຼື ອະນຸມັດການສັ່ງຊື້" + "ຕອນນີ້ທ່ານສາມາດໃຊ້ລາຍນິ້ວມືຂອງທ່ານເພື່ອປົດລັອກອຸປະກອນຂອງທ່ານ ຫຼື ຢັ້ງຢືນວ່າແມ່ນທ່ານໄດ້ແລ້ວ, ເຊັ່ນ: ໃນເວລາທີ່ທ່ານເຂົ້າສູ່ລະບົບຫາແອັບ ຫຼື ອະນຸມັດການສັ່ງຊື້" + "ຕອນນີ້ທ່ານສາມາດໃຊ້ລາຍນິ້ວມືຂອງທ່ານເພື່ອປົດລັອກໂທລະສັບຂອງທ່ານ ຫຼື ຢັ້ງຢືນວ່າແມ່ນທ່ານໄດ້ແລ້ວ, ເຊັ່ນ: ໃນເວລາທີ່ທ່ານເຂົ້າສູ່ລະບົບຫາແອັບ ຫຼື ອະນຸມັດການສັ່ງຊື້" "ປົດລັອກສະເພາະເມື່ອໜ້າຈໍເປີດຢູ່ເທົ່ານັ້ນ" "ໜ້າຈໍຈະຕ້ອງເປີດຢູ່ທ່ານຈຶ່ງຈະສາມາດປົດລັອກດ້ວຍລາຍນິ້ວມືຂອງທ່ານໄດ້. ການດຳເນີນການນີ້ເຮັດໃຫ້ບໍ່ເກີດການປົດລັອກໂດຍບໍ່ຕັ້ງໃຈ." "ປົດລັອກໜ້າຈໍ" @@ -3490,8 +3487,7 @@ "ລຶບ %1$s ອອກຈາກອຸປະກອນນີ້" "ການ​ຕັ້ງ​ຄ່າ​ຫນ້າ​ຈໍລັອກ" "ເພີ່ມຜູ້ໃຊ້ຈາກໜ້າຈໍລັອກ" - - + "ປ່ຽນໄປເປັນຜູ້ໃຊ້ທີ່ເບິ່ງແຍງລະບົບເມື່ອວາງໃສ່ແທ່ນສາກ" "ລຶບໂຕທ່ານເອງ?" "ລຶບຜູ້ໃຊ້ນີ້ອອກບໍ?" "ລຶບ​ໂປຣ​ໄຟລ໌​ນີ້​ບໍ?" @@ -5673,6 +5669,9 @@ "ເພື່ອໃຊ້, ທຳອິດໃຫ້ເປີດໃຊ້ \"ສະແດງການຄວບຄຸມອຸປະກອນ\" ກ່ອນ" "ສະແດງໂມງສອງແຖວເມື່ອສາມາດໃຊ້ໄດ້" "ໂມງສອງແຖວ" + + + diff --git a/res/values-lt/strings.xml b/res/values-lt/strings.xml index d84fb0c707b..ef4a622e164 100644 --- a/res/values-lt/strings.xml +++ b/res/values-lt/strings.xml @@ -596,12 +596,9 @@ "Užregistruota %d proc." "Registracija kontroliniu kodu: %d proc." "Kontrolinis kodas pridėtas" - - - - - - + "Dabar galite naudoti piršto atspaudą, kad atrakintumėte planšetinį kompiuterį ar patvirtintumėte savo tapatybę, pvz., kai prisijungiate prie programų ar patvirtinate pirkinį" + "Dabar galite naudoti piršto atspaudą, kad atrakintumėte įrenginį ar patvirtintumėte savo tapatybę, pvz., kai prisijungiate prie programų ar patvirtinate pirkinį" + "Dabar galite naudoti piršto atspaudą, kad atrakintumėte telefoną ar patvirtintumėte savo tapatybę, pvz., kai prisijungiate prie programų ar patvirtinate pirkinį" "Atrakinti tik tada, kai ekranas įjungtas" "Ekranas turi būti įjungtas, kad būtų galima atrakinti piršto atspaudu. Tai sumažina netyčinio atrakinimo tikimybę." "Ekranas, atrakinti" @@ -3574,8 +3571,7 @@ "Ištrinti %1$s iš šio įr." "Užrakinimo ekrano nustatymai" "Pridėti naudotojų iš užrakinimo ekrano" - - + "Perjungti į naud. administr., kai prij. prie doko" "Ištrinti save?" "Ištrinti šį naudotoją?" "Pašalinti šį profilį?" @@ -5847,6 +5843,9 @@ "Jei norite naudoti, pirmiausia įjunkite parinktį „Rodyti įrenginio valdiklius“" "Rodyti vertikalųjį laikrodį, kai jis pasiekiamas" "Vertikalusis laikrodis" + + + diff --git a/res/values-lv/strings.xml b/res/values-lv/strings.xml index 25dff6a4021..81ae3cfd297 100644 --- a/res/values-lv/strings.xml +++ b/res/values-lv/strings.xml @@ -592,12 +592,9 @@ "Reģistrēšanas progresa procenti: %d" "Pirksta nospieduma reģistrēšana: %d procenti" "Pirksta nospiedums pievienots" - - - - - - + "Tagad varat izmantot pirksta nospiedumu, lai atbloķētu planšetdatoru vai apstiprinātu savu identitāti, piemēram, pierakstoties lietotnēs vai apstiprinot pirkumu." + "Tagad varat izmantot pirksta nospiedumu, lai atbloķētu ierīci vai apstiprinātu savu identitāti, piemēram, pierakstoties lietotnēs vai apstiprinot pirkumu." + "Tagad varat izmantot pirksta nospiedumu, lai atbloķētu tālruni vai apstiprinātu savu identitāti, piemēram, pierakstoties lietotnēs vai apstiprinot pirkumu." "Atbloķēt tikai tad, kad ekrāns ir aktivizēts" "Ekrānam ir jābūt aktivizētam, lai varētu to atbloķēt, izmantojot pirksta nospiedumu. Tādējādi tiek samazināta nejaušas atbloķēšanas iespējamība." "Ekrāns, atbloķēšana" @@ -2842,8 +2839,7 @@ "Vēstures dati" "Akumulatora lietojums" "Skatīt lietojumu pēdējo 24 stundu laikā" - - + "Lietojums kopš pēdējās pilnas uzlādes" "Akumulatora lietojums lietotnēm" "Izmantot detaļas" "Noregulēt strāvas patēriņu" @@ -2957,7 +2953,7 @@ "Jūsu ierīce nevar pārvaldīt akumulatora darbību kā parasti, jo lietotne %1$s arvien pieprasa atrašanās vietas datus, kad neizmantojat lietotni.\n\nLai novērstu šo problēmu, varat izslēgt atrašanās vietas datus šai lietotnei." "Izslēgt" "Ekrāns" - "Zibspuldze" + "Lukturītis" "Kamera" "Wi-Fi" "Bluetooth" @@ -3031,32 +3027,25 @@ "Akumulatora lietojums" "Kopš pilnas uzlādes" "Akumulatora lietojuma pārvaldīšana" - - + "Kopā: ^1 • Fonā: ^2\n (kopš pēdējās pilnās uzlādes)" "Kopā: ^1 • Lietojums fonā: ^2\n(pēdējo 24 h laikā)" "Kopā: ^1 • Lietojums fonā: ^2\n(šajā periodā: ^3)" - - + "Mazāk par minūti ilgs kopējais lietojums kopš pēdējās pilnās uzlādes" "Mazāk nekā minūti ilgs kopējais lietojums pēdējo 24 h laikā" "Mazāk nekā minūti ilgs kopējais lietojums šajā periodā: ^1" - - + "Mazāk par minūti ilgs lietojums fonā kopš pēdējās pilnās uzlādes" "Mazāk nekā minūti ilgs lietojums fonā pēdējo 24 h laikā" "Mazāk nekā minūti ilgs lietojums fonā šajā periodā: ^1" - - + "Kopā: ^1 (kopš pēdējās pilnās uzlādes)" "Kopā: ^1 (pēdējo 24 h laikā)" "^1 ilgs kopējais lietojums šajā periodā: ^2" - - + "Lietojums fonā: ^1 (kopš pēdējās pilnās uzlādes)" "Lietojums fonā pēdējo 24 h laikā: ^1" "Lietojums fonā: ^1 (šajā periodā: ^2)" - - + "Kopā: ^1 • Lietojuma ilgums fonā nepārsniedza minūti\n(kopš pēdējās pilnās uzlādes)" "Kopā: ^1 • Mazāk nekā minūti ilgs lietojums fonā\npēdējo 24 h laikā" "Kopā: ^1 • Mazāk nekā minūti ilgs lietojums fonā\n(šajā periodā: ^2)" - - + "Nav lietots kopš pēdējās pilnās uzlādes" "Nav lietots pēdējo 24 h laikā" "Citi lietotāji" @@ -5048,7 +5037,7 @@ "ekrāna izgriezums" "Ierīces noklusējuma iestatījums" "Neizdevās lietot pārklājumu" - "Īpaša piekļuve lietotnēm" + "Īpaša lietotņu piekļuve" %d lietotnēs var izmantot neierobežotu datu apjomu %d lietotnē var izmantot neierobežotu datu apjomu @@ -5768,6 +5757,9 @@ "Lai izmantotu vadīklas, vispirms ieslēdziet iestatījumu “Rādīt ierīču vadīklas”." "Rādīt pulksteni divās rindās, ja tas ir pieejams" "Pulkstenis divās rindās" + + + diff --git a/res/values-mk/strings.xml b/res/values-mk/strings.xml index d9aa83ab628..7e68db559e7 100644 --- a/res/values-mk/strings.xml +++ b/res/values-mk/strings.xml @@ -592,12 +592,9 @@ "Отпечатокот е додаден" - - - - - - + "Сега може да го користите отпечатокот за да го отклучите таблетот или да потврдите дека сте вие, како кога се најавувате на апликации или одобрувате купување" + "Сега може да го користите отпечатокот за да го отклучите уредот или да потврдите дека сте вие, како кога се најавувате на апликации или одобрувате купување" + "Сега може да го користите отпечатокот за да го отклучите телефонот или да потврдите дека сте вие, како кога се најавувате на апликации или одобрувате купување" "Отклучете само кога екранот е вклучен" "Екранот мора да биде вклучен пред да може да го отклучите со отпечаток. Ова го прави случајното отклучување да биде помалку веројатно." "Екран, отклучување" @@ -3494,8 +3491,7 @@ "Избриши го %1$s од тука" "Поставки на екранот за заклучување" "Додавање корисници од заклучен екран" - - + "Префрли се на администраторски корисник кога уредот е приклучен на док" "Избриши се себеси?" "Да се избрише корисникот?" "Да се отстрани профилот?" @@ -5677,6 +5673,9 @@ "За да користите, прво вклучете „Прикажувај контроли за уреди“" "Прикажувај часовник со двојна линија кога е достапен" "Часовник со двојна линија" + + + diff --git a/res/values-ml/strings.xml b/res/values-ml/strings.xml index 3ec5d65245c..ee92fad1214 100644 --- a/res/values-ml/strings.xml +++ b/res/values-ml/strings.xml @@ -588,12 +588,9 @@ "%d ശതമാനം എൻറോൾ ചെയ്തു" "ഫിംഗർപ്രിന്റ് എൻറോൾ ചെയ്യൽ %d ശതമാനം ആയി" "ഫിംഗർപ്രിന്റ് ചേർത്തു" - - - - - - + "ടാബ്‌ലെറ്റ് അൺലോക്ക് ചെയ്യാനോ ആപ്പുകളിലേക്ക് സൈൻ ഇൻ ചെയ്യുന്നത് പോലുള്ള സന്ദർഭങ്ങളിൽ ഇത് നിങ്ങൾ തന്നെയാണെന്ന് പരിശോധിച്ചുറപ്പിക്കാനോ ഇപ്പോൾ നിങ്ങളുടെ ഫിംഗർപ്രിന്റ് ഉപയോഗിക്കാനാകും" + "ഉപകരണം അൺലോക്ക് ചെയ്യാനോ ആപ്പുകളിലേക്ക് സൈൻ ഇൻ ചെയ്യുന്നത് പോലുള്ള സന്ദർഭങ്ങളിൽ ഇത് നിങ്ങൾ തന്നെയാണെന്ന് പരിശോധിച്ചുറപ്പിക്കാനോ ഇപ്പോൾ നിങ്ങളുടെ ഫിംഗർപ്രിന്റ് ഉപയോഗിക്കാനാകും" + "ഫോൺ അൺലോക്ക് ചെയ്യാനോ ആപ്പുകളിലേക്ക് സൈൻ ഇൻ ചെയ്യുന്നത് പോലുള്ള സന്ദർഭങ്ങളിൽ ഇത് നിങ്ങൾ തന്നെയാണെന്ന് പരിശോധിച്ചുറപ്പിക്കാനോ ഇപ്പോൾ നിങ്ങളുടെ ഫിംഗർപ്രിന്റ് ഉപയോഗിക്കാനാകും" "സ്ക്രീൻ ഓണായിരിക്കുമ്പോൾ മാത്രം അൺലോക്ക് ചെയ്യുക" "നിങ്ങളുടെ ഫിംഗർപ്രിന്റ് ഉപയോഗിച്ച് അൺലോക്ക് ചെയ്യുന്നതിന് മുമ്പ് സ്ക്രീൻ ഓണായിരിക്കണം. ഇത്, അവിചാരിതമായി അൺലോക്ക് ചെയ്യുന്നതിനുള്ള സാധ്യത കുറയ്ക്കുന്നു." "സ്ക്രീൻ അൺലോക്ക്" @@ -3490,8 +3487,7 @@ "ഫോണിൽ നിന്നും %1$s-നെ മായ്ക്കൂ" "ലോക്ക് സ്ക്രീൻ ക്രമീകരണം" "ലോക്ക് സ്ക്രീനിൽ നിന്ന് ഉപയോക്താക്കളെ ചേർക്കുക" - - + "ഡോക്ക് ചെയ്യുമ്പോൾ അഡ്‌മിൻ ഉപയോക്താവിലേക്ക് മാറുക" "നിങ്ങളെ സ്വയം ഇല്ലാതാക്കണോ?" "ഈ ഉപയോക്താവിനെ ഇല്ലാതാക്കണോ?" "ഈ പ്രൊഫൈൽ നീക്കംചെയ്യണോ?" @@ -5673,6 +5669,9 @@ "ഉപയോഗിക്കാൻ, ആദ്യം \"ഉപകരണ നിയന്ത്രണങ്ങൾ കാണിക്കുക\" ഓണാക്കുക" "ലഭ്യമാകുമ്പോൾ ഡബിൾലൈൻ ക്ലോക്ക് കാണിക്കുക" "ഡബിൾലൈൻ ക്ലോക്ക്" + + + diff --git a/res/values-mn/strings.xml b/res/values-mn/strings.xml index 165245c897a..bb8b4b6161d 100644 --- a/res/values-mn/strings.xml +++ b/res/values-mn/strings.xml @@ -3487,8 +3487,7 @@ "%1$s-г энэ төхөөрөмжөөс устгах" "Дэлгэц түгжих тохиргоо" "Түгжигдсэн дэлгэцээс хэрэглэгч нэмэх" - - + "Суурилуулах үед админ хэрэглэгч рүү сэлгэх" "Өөрийгөө устгах уу?" "Энэ хэрэглэгчийг устгах уу?" "Энэ профайлыг устгах уу?" @@ -5670,6 +5669,9 @@ "Ашиглахын тулд эхлээд \"Төхөөрөмжийн хяналтыг харуулах\"-г асаана уу" "Боломжтой үед нь хоёр зураастай цаг харуулах" "Хоёр зураастай цаг" + + + diff --git a/res/values-mr/strings.xml b/res/values-mr/strings.xml index 5e4119931aa..41fd2da93ad 100644 --- a/res/values-mr/strings.xml +++ b/res/values-mr/strings.xml @@ -588,12 +588,9 @@ "%d टक्के नोंदणी झाली आहे" "फिंगरप्रिंटची %d टक्के नोंदणी झाली आहे" "फिंगरप्रिंट जोडली" - - - - - - + "ॲप्समध्ये साइन इन करणे किंवा खरेदी मंजूर करणे यांसारख्या गोष्टी करताना तुमचा टॅबलेट अनलॉक करण्यासाठी किंवा ते तुम्हीच आहात याची पडताळणी करण्यासाठी, आता तुम्ही तुमची फिंगरप्रिंट वापरू शकता" + "ॲप्समध्ये साइन इन करणे किंवा खरेदी मंजूर करणे यांसारख्या गोष्टी करताना तुमचे डिव्हाइस अनलॉक करण्यासाठी किंवा ते तुम्हीच आहात याची पडताळणी करण्यासाठी, आता तुम्ही तुमची फिंगरप्रिंट वापरू शकता" + "ॲप्समध्ये साइन इन करणे किंवा खरेदी मंजूर करणे यांसारख्या गोष्टी करताना तुमचा फोन अनलॉक करण्यासाठी किंवा ते तुम्हीच आहात याची पडताळणी करण्यासाठी, आता तुम्ही तुमची फिंगरप्रिंट वापरू शकता" "फक्त स्क्रीन सुरू असताना अनलॉक करा" "तुमची फिंगरप्रिंट वापरून तुम्ही अनलॉक करण्यापूर्वी स्क्रीन सुरू असणे आवश्यक आहे. हे चुकून अनलॉक होण्याची शक्यता कमी करते." "स्क्रीन, अनलॉक करा" @@ -3490,8 +3487,7 @@ "या डिव्हाइसवरुन %1$s हटवा" "लॉक स्क्रीन सेटिंग्ज" "लॉक स्‍क्रीनवरून वापरकर्ते जोडा" - - + "डॉक केले असेल तेव्हा ॲडमिन वापरकर्त्यावर स्विच करा" "आपल्या स्वत:ला हटवायचे?" "हा वापरकर्ता हटवायचा का?" "हे प्रोफाईल काढायचे?" @@ -5673,6 +5669,9 @@ "वापरण्यासाठी, सर्वप्रथम \"डिव्हाइस नियंत्रणे दाखवा\" सुरू करा" "उपलब्ध असताना, ड्युअल क्लॉक दाखवा" "ड्युअल क्लॉक" + + + diff --git a/res/values-ms/strings.xml b/res/values-ms/strings.xml index 352580f8e18..30cc36fe52c 100644 --- a/res/values-ms/strings.xml +++ b/res/values-ms/strings.xml @@ -588,12 +588,9 @@ "%d peratus didaftarkan" "Mendaftarkan cap jari %d peratus" "Cap jari ditambahkan" - - - - - - + "Kini anda boleh menggunakan cap jari anda untuk membuka kunci tablet atau mengesahkan identiti anda, misalnya ketika anda log masuk ke apl atau meluluskan pembelian" + "Kini anda boleh menggunakan cap jari anda untuk membuka kunci peranti anda atau mengesahkan identiti anda, seperti ketika anda log masuk ke apl atau meluluskan pembelian" + "Kini anda boleh menggunakan cap jari anda untuk membuka kunci telefon anda atau mengesahkan identiti anda, seperti ketika anda log masuk ke apl atau meluluskan pembelian" "Hanya buka kunci apabila skrin dihidupkan" "Skrin perlu dihidupkan sebelum anda boleh membuka kunci dengan cap jari anda. Tindakan ini dapat mengurangkan kemungkinan kunci terbuka secara tidak sengaja." "Skrin, Buka Kunci" @@ -3490,8 +3487,7 @@ "Padam %1$s dari peranti" "Tetapan skrin kunci" "Tambahkan pengguna daripada skrin kunci" - - + "Tukar kepada pengguna pentadbir apabila didok" "Padam diri anda sendiri?" "Padamkan pengguna ini?" "Alih keluar profil ini?" @@ -5673,6 +5669,9 @@ "Untuk penggunaan, hidupkan \"Tunjukkan kawalan peranti\" terlebih dahulu" "Tunjukkan jam dua baris apabila tersedia" "Jam dua baris" + + + diff --git a/res/values-my/strings.xml b/res/values-my/strings.xml index dfa6d325f27..be38251f070 100644 --- a/res/values-my/strings.xml +++ b/res/values-my/strings.xml @@ -588,12 +588,9 @@ "စာရင်းသွင်းပြီး %d ရာခိုင်နှုန်း" "လက်ဗွေ စာရင်းသွင်းခြင်း %d ရာခိုင်နှုန်း" "လက်ဗွေကို ထည့်ပြီးပါပြီ" - - - - - - + "အက်ပ်များသို့ လက်မှတ်ထိုးဝင်သောအခါ (သို့) ပစ္စည်းဝယ်ယူသောအခါကဲ့သို့တွင် သင်ဖြစ်ကြောင်းအတည်ပြုရန် (သို့) တက်ဘလက်ဖွင့်ရန်အတွက် သင့်လက်ဗွေကို ယခုသုံးနိုင်ပါပြီ" + "အက်ပ်များသို့ လက်မှတ်ထိုးဝင်သောအခါ (သို့) ပစ္စည်းဝယ်ယူသောအခါကဲ့သို့တွင် သင်ဖြစ်ကြောင်းအတည်ပြုရန် (သို့) စက်ဖွင့်ရန်အတွက် သင့်လက်ဗွေကို ယခုသုံးနိုင်ပါပြီ" + "အက်ပ်များသို့ လက်မှတ်ထိုးဝင်သောအခါ (သို့) ပစ္စည်းဝယ်ယူသောအခါကဲ့သို့တွင် သင်ဖြစ်ကြောင်းအတည်ပြုရန် (သို့) ဖုန်းဖွင့်ရန်အတွက် သင့်လက်ဗွေကို ယခုသုံးနိုင်ပါပြီ" "ဖန်သားပြင်ဖွင့်ထားမှသာ လော့ခ်ဖွင့်ရန်" "သင့်လက်ဗွေဖြင့် လော့ခ်မဖွင့်မီ ဖန်သားပြင်ကို ဖွင့်ထားရမည်။ ၎င်းက မတော်တဆ လော့ခ်ပွင့်ခြင်းကို လျော့နည်းစေမည်။" "ဖန်သားပြင်၊ လော့ခ်ဖွင့်ရန်" @@ -3490,8 +3487,7 @@ "ဤစက်မှ %1$sကို ဖျက်ရန်" "လော့ခ်မျက်နှာပြင် ဆက်တင်များ" "လော့ခ်မျက်နှာပြင်မှနေ၍ အသုံးပြုသူများကို ထည့်ရန်" - - + "တပ်ဆင်ထားချိန်တွင် စီမံခန့်ခွဲသူသို့ ပြောင်းရန်" "သင့်ကို ဖယ်ရှားမလား။" "ဤအသုံးပြုသူကို ဖျက်မလား။" "ဒီပရိုဖိုင်ကို ဖယ်ရှားရမလား?" @@ -5673,6 +5669,9 @@ "အသုံးပြုရန်အတွက် \"စက်ထိန်းစနစ် ပြရန်\" ကို ဦးစွာဖွင့်ပါ" "နှစ်လိုင်းပြနာရီကို ရနိုင်ပါက ပြပါ" "နှစ်လိုင်းပြနာရီ" + + + diff --git a/res/values-nb/strings.xml b/res/values-nb/strings.xml index 7587c399176..c6e62b55f1d 100644 --- a/res/values-nb/strings.xml +++ b/res/values-nb/strings.xml @@ -588,12 +588,9 @@ "Registrert %d prosent" "Registrerer fingeravtrykket: %d prosent" "Fingeravtrykket er lagt til" - - - - - - + "Nå kan du bruke fingeravtrykket til å låse opp nettbrettet eller bekrefte at det er deg, for eksempel når du logger på apper eller godkjenner kjøp" + "Nå kan du bruke fingeravtrykket til å låse opp enheten eller bekrefte at det er deg, for eksempel når du logger på apper eller godkjenner kjøp" + "Nå kan du bruke fingeravtrykket til å låse opp telefonen eller bekrefte at det er deg, for eksempel når du logger på apper eller godkjenner kjøp" "Lås bare opp enheten når skjermen er på" "Skjermen må være på før du kan låse opp enheten med fingeravtrykket. Dermed reduseres sannsynligheten for at enheten låses opp ved et uhell." "Skjerm, opplåsing" @@ -3490,8 +3487,7 @@ "Slett %1$s fra denne enheten" "Innstillinger for låseskjermen" "Legg til brukere fra låseskjermen" - - + "Bytt til administratorbruker under dokking" "Vil du slette deg selv?" "Vil du slette brukeren?" "Fjerne denne profilen?" @@ -5673,6 +5669,9 @@ "For å bruke, slå først på «Vis enhetsstyring»" "Vis klokken på to linjer når det er tilgjengelig" "Klokke på to linjer" + + + diff --git a/res/values-ne/strings.xml b/res/values-ne/strings.xml index a24dc468ebd..b3a60d73e8c 100644 --- a/res/values-ne/strings.xml +++ b/res/values-ne/strings.xml @@ -588,12 +588,9 @@ "%d प्रतिशत दर्ता गरिएको छ" "फिंगरप्रिन्ट दर्ता गर्ने कार्य %d पूरा भयो" "फिंगरप्रिन्ट हालियो" - - - - - - + "तपाईं अब ट्याब्लेट अनलक गर्ने वा आफ्नो पहिचान पुष्टि गर्ने प्रयोजनका लागि (जस्तै, एपहरूमा साइन इन गर्दा वा कुनै खरिद अनुमोदन गर्दा) आफ्नो फिंगरप्रिन्ट प्रयोग गर्न सक्नुहुन्छ" + "तपाईं अब डिभाइस अनलक गर्ने वा आफ्नो पहिचान पुष्टि गर्ने प्रयोजनका लागि (जस्तै, एपहरूमा साइन इन गर्दा वा कुनै खरिद अनुमोदन गर्दा) आफ्नो फिंगरप्रिन्ट प्रयोग गर्न सक्नुहुन्छ" + "तपाईं अब फोन अनलक गर्ने वा आफ्नो पहिचान पुष्टि गर्ने प्रयोजनका लागि (जस्तै, एपहरूमा साइन इन गर्दा वा कुनै खरिद अनुमोदन गर्दा) आफ्नो फिंगरप्रिन्ट प्रयोग गर्न सक्नुहुन्छ" "स्क्रिन अन हुँदा मात्र अनलक गरियोस्" "स्क्रिन अन भएपछि मात्र तपाईं आफ्नो फिंगरप्रिन्ट प्रयोग गरी अनलक गर्न सक्नुहुन्छ। यसमा गल्तीले अनलक हुने सम्भावना कम हुन्छ।" "स्क्रिन, अनलक" @@ -3490,8 +3487,7 @@ "यस उपकरणबाट %1$s हटाउनुहोस्" "लक स्क्रिन सेटिङहरू" "लक स्क्रिनबाट प्रयोगकर्ताहरू थप्नुहोस्" - - + "डक गरिएका बेला एड्मिन खाता प्रयोग गर्नुहोस्" "आफैंलाई हटाउने हो?" "यो प्रयोगकर्ता हटाउने हो?" "यो प्रोफाइल हटाउने?" @@ -5673,6 +5669,9 @@ "तपाईं यसलाई प्रयोग गर्न चाहनुहुन्छ भने सर्वप्रथम \"डिभाइस नियन्त्रण गर्ने विजेटहरू देखाइयोस्\" अन गर्नुहोस्" "उपलब्ध भएका बेला दुई हरफको घडी देखाइयोस्" "दुई हरफको घडी" + + + diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml index b9ea92ea106..7d12025b1e0 100644 --- a/res/values-nl/strings.xml +++ b/res/values-nl/strings.xml @@ -522,7 +522,7 @@ "Ga naar een plek met zachter licht en probeer het opnieuw" "Je hebt het maximale aantal pogingen bereikt" "Gebruik je vingerafdruk om je tablet te ontgrendelen of te bevestigen dat jij het bent als je bijvoorbeeld inlogt bij apps" - "Gebruik je vingerafdruk om je apparaat te ontgrendelen of te bevestigen dat jij het bent als je inlogt bij apps" + "Gebruik je vingerafdruk om je apparaat te ontgrendelen of te bevestigen dat jij het bent als je inlogt bij apps." "Gebruik je vingerafdruk om je telefoon te ontgrendelen of te bevestigen dat jij het bent als je inlogt bij apps" "Ontgrendelen via gezichtsherkenning en vingerafdruk" "Tik om in te stellen" @@ -3487,8 +3487,7 @@ "%1$s verwijderen van dit apparaat" "Instellingen voor vergrendelscherm" "Gebruikers toevoegen vanaf vergrendelscherm" - - + "Overschakelen naar beheerder indien gedockt" "Wil je jezelf verwijderen?" "Gebruiker verwijderen?" "Dit profiel verwijderen?" @@ -5670,6 +5669,9 @@ "Als je dit wilt gebruiken, zet je eerst Apparaatbediening tonen aan" "Klok met 2 regels laten zien als die beschikbaar is" "Klok met 2 regels" + + + diff --git a/res/values-or/strings.xml b/res/values-or/strings.xml index 613340f4d85..7db760856c3 100644 --- a/res/values-or/strings.xml +++ b/res/values-or/strings.xml @@ -588,12 +588,9 @@ "%d ଶତକଡ଼ା ପଞ୍ଜିକରଣ କରାଯାଇଛି" "ଟିପଚିହ୍ନ ପଞ୍ଜିକରଣ କରିବା ଶତକଡ଼ା %d ସମ୍ପୂର୍ଣ୍ଣ ହୋଇଛି" "ଟିପଚିହ୍ନ ଯୋଗ କରାଯାଇଛି" - - - - - - + "ଆପଣ ଆପ୍ସରେ ସାଇନ ଇନ କରିବା କିମ୍ବା ଏକ କ୍ରୟକୁ ଅନୁମୋଦନ ଦେବା ପରି କାର୍ଯ୍ୟ କରିବା ସମୟରେ, ଆପଣଙ୍କ ଟାବଲେଟକୁ ଅନଲକ କରିବା କିମ୍ବା ଏହା ଆପଣ ବୋଲି ଯାଞ୍ଚ କରିବା ପାଇଁ ବର୍ତ୍ତମାନ ଆପଣଙ୍କ ଟିପଚିହ୍ନକୁ ଆପଣ ବ୍ୟବହାର କରିପାରିବେ" + "ଆପଣ ଆପ୍ସରେ ସାଇନ ଇନ କରିବା କିମ୍ବା ଏକ କ୍ରୟକୁ ଅନୁମୋଦନ ଦେବା ପରି କାର୍ଯ୍ୟ କରିବା ସମୟରେ, ଆପଣଙ୍କ ଡିଭାଇସକୁ ଅନଲକ କରିବା କିମ୍ବା ଏହା ଆପଣ ବୋଲି ଯାଞ୍ଚ କରିବା ପାଇଁ ବର୍ତ୍ତମାନ ଆପଣଙ୍କ ଟିପଚିହ୍ନକୁ ଆପଣ ବ୍ୟବହାର କରିପାରିବେ" + "ଆପଣ ଆପ୍ସରେ ସାଇନ ଇନ କରିବା କିମ୍ବା ଏକ କ୍ରୟକୁ ଅନୁମୋଦନ ଦେବା ପରି କାର୍ଯ୍ୟ କରିବା ସମୟରେ, ଆପଣଙ୍କ ଫୋନକୁ ଅନଲକ କରିବା କିମ୍ବା ଏହା ଆପଣ ବୋଲି ଯାଞ୍ଚ କରିବା ପାଇଁ ବର୍ତ୍ତମାନ ଆପଣଙ୍କ ଟିପଚିହ୍ନକୁ ଆପଣ ବ୍ୟବହାର କରିପାରିବେ" "ସ୍କ୍ରିନ ସକ୍ରିୟ ଥିବା ସମୟରେ କେବଳ ଅନଲକ କରନ୍ତୁ" "ଆପଣ ଆପଣଙ୍କ ଟିପଚିହ୍ନ ମାଧ୍ୟମରେ ଅନଲକ କରିବା ପୂର୍ବରୁ ସ୍କ୍ରିନ ସକ୍ରିୟ ଥିବା ଆବଶ୍ୟକ। ଭୁଲବଶତଃ ଅନଲକ ହେବା ସମ୍ଭାବନାକୁ ଏହା କମ୍ କରେ।" "ସ୍କ୍ରିନ, ଅନଲକ କରନ୍ତୁ" @@ -3490,8 +3487,7 @@ "ଏହି ଡିଭାଇସ୍‌ରୁ %1$s ଙ୍କୁ ଡିଲିଟ୍‍ କରନ୍ତୁ" "ଲକ ସ୍କ୍ରିନ ସେଟିଂସ" "ଲକ୍‌ ସ୍କ୍ରିନ୍‌ରୁ ଉପଯୋଗକର୍ତ୍ତାଙ୍କୁ ଯୋଗ କରନ୍ତୁ" - - + "ଡକ ହୋଇଥିବା ସମୟରେ ଆଡମିନ ୟୁଜରକୁ ସ୍ୱିଚ କରନ୍ତୁ" "ନିଜକୁ ଡିଲିଟ୍‌ କରିବେ?" "ଏହି ୟୁଜରଙ୍କୁ ଡିଲିଟ୍‍ କରିବେ?" "ଏହି ପ୍ରୋଫାଇଲ୍‌କୁ କାଢ଼ିଦେବେ?" @@ -5673,6 +5669,9 @@ "ବ୍ୟବହାର କରିବା ପାଇଁ, ପ୍ରଥମେ \"ଡିଭାଇସ ନିୟନ୍ତ୍ରଣଗୁଡ଼ିକୁ ଦେଖାନ୍ତୁ\"କୁ ଚାଲୁ କରନ୍ତୁ" "ଉପଲବ୍ଧ ହେଲେ ଡବଲ-ଲାଇନ ଘଣ୍ଟା ଦେଖାନ୍ତୁ" "ଡବଲ-ଲାଇନ ଘଣ୍ଟା" + + + diff --git a/res/values-pa/strings.xml b/res/values-pa/strings.xml index 85a26f76f53..0e58ed097dd 100644 --- a/res/values-pa/strings.xml +++ b/res/values-pa/strings.xml @@ -588,12 +588,9 @@ "%d ਪ੍ਰਤੀਸ਼ਤ ਦਰਜ ਕੀਤਾ ਗਿਆ" "ਫਿੰਗਰਪ੍ਰਿੰਟ ਦਰਜ ਕਰਨ ਦੀ ਪ੍ਰਕਿਰਿਆ %d ਫ਼ੀਸਦ ਹੋ ਗਈ ਹੈ" "ਫਿੰਗਰਪ੍ਰਿੰਟ ਸ਼ਾਮਲ ਹੋ ਗਿਆ" - - - - - - + "ਹੁਣ ਤੁਸੀਂ ਆਪਣਾ ਟੈਬਲੈੱਟ ਅਣਲਾਕ ਕਰਨ ਜਾਂ ਆਪਣੀ ਪਛਾਣ ਦੀ ਪੁਸ਼ਟੀ ਕਰਨ ਲਈ ਆਪਣਾ ਫਿੰਗਰਪ੍ਰਿੰਟ ਵਰਤ ਸਕਦੇ ਹੋ, ਜਿਵੇਂ ਕਿ ਜਦੋਂ ਤੁਸੀਂ ਐਪਾਂ ਵਿੱਚ ਸਾਈਨ-ਇਨ ਕਰਦੇ ਹੋ ਜਾਂ ਕਿਸੇ ਖਰੀਦ ਨੂੰ ਮਨਜ਼ੂਰੀ ਦਿੰਦੇ ਹੋ" + "ਹੁਣ ਤੁਸੀਂ ਆਪਣਾ ਡੀਵਾਈਸ ਅਣਲਾਕ ਕਰਨ ਜਾਂ ਆਪਣੀ ਪਛਾਣ ਦੀ ਪੁਸ਼ਟੀ ਕਰਨ ਲਈ ਆਪਣਾ ਫਿੰਗਰਪ੍ਰਿੰਟ ਵਰਤ ਸਕਦੇ ਹੋ, ਜਿਵੇਂ ਕਿ ਜਦੋਂ ਤੁਸੀਂ ਐਪਾਂ ਵਿੱਚ ਸਾਈਨ-ਇਨ ਕਰਦੇ ਹੋ ਜਾਂ ਕਿਸੇ ਖਰੀਦ ਨੂੰ ਮਨਜ਼ੂਰੀ ਦਿੰਦੇ ਹੋ" + "ਹੁਣ ਤੁਸੀਂ ਆਪਣਾ ਫ਼ੋਨ ਅਣਲਾਕ ਕਰਨ ਜਾਂ ਆਪਣੀ ਪਛਾਣ ਦੀ ਪੁਸ਼ਟੀ ਕਰਨ ਲਈ ਆਪਣਾ ਫਿੰਗਰਪ੍ਰਿੰਟ ਵਰਤ ਸਕਦੇ ਹੋ, ਜਿਵੇਂ ਕਿ ਜਦੋਂ ਤੁਸੀਂ ਐਪਾਂ ਵਿੱਚ ਸਾਈਨ-ਇਨ ਕਰਦੇ ਹੋ ਜਾਂ ਕਿਸੇ ਖਰੀਦ ਨੂੰ ਮਨਜ਼ੂਰੀ ਦਿੰਦੇ ਹੋ" "ਸਿਰਫ਼ ਸਕ੍ਰੀਨ ਦੇ ਚਾਲੂ ਹੋਣ \'ਤੇ ਹੀ ਅਣਲਾਕ ਕਰੋ" "ਤੁਹਾਡੇ ਵੱਲੋਂ ਆਪਣੇ ਫਿੰਗਰਪ੍ਰਿੰਟ ਨਾਲ ਅਣਲਾਕ ਕਰਨ ਤੋਂ ਪਹਿਲਾਂ, ਸਕ੍ਰੀਨ ਚਾਲੂ ਹੋਣੀ ਚਾਹੀਦੀ ਹੈ। ਇਸ ਵਿੱਚ ਗਲਤੀ ਨਾਲ ਅਣਲਾਕ ਹੋਣ ਦੀ ਸੰਭਾਵਨਾ ਘੱਟ ਜਾਂਦੀ ਹੈ।" "ਸਕ੍ਰੀਨ, ਅਣਲਾਕ ਕਰੋ" @@ -3490,8 +3487,7 @@ "%1$s ਨੂੰ ਇਸ ਡੀਵਾਈਸ ਤੋਂ ਮਿਟਾਓ" "ਲਾਕ ਸਕ੍ਰੀਨ ਸੈਟਿੰਗਾਂ" "ਲਾਕ ਸਕ੍ਰੀਨ ਤੋਂ ਵਰਤੋਂਕਾਰਾਂ ਨੂੰ ਸ਼ਾਮਲ ਕਰੋ" - - + "ਡੌਕ ਕੀਤੇ ਜਾਣ \'ਤੇ ਪ੍ਰਸ਼ਾਸਕ ਵਰਤੋਂਕਾਰ \'ਤੇ ਸਵਿੱਚ ਕਰੋ" "ਕੀ ਖੁਦ ਨੂੰ ਹਟਾਉਣਾ ਹੈ?" "ਇਹ ਵਰਤੋਂਕਾਰ ਮਿਟਾਉਣਾ ਹੈ?" "ਕੀ ਇਹ ਪ੍ਰੋਫਾਈਲ ਹਟਾਉਣੀ ਹੈ?" @@ -5673,6 +5669,9 @@ "ਵਰਤੋਂ ਕਰਨ ਲਈ, ਪਹਿਲਾਂ \"ਡੀਵਾਈਸ ਕੰਟਰੋਲ ਦਿਖਾਓ\" ਨੂੰ ਚਾਲੂ ਕਰੋ" "ਉਪਲਬਧ ਹੋਣ \'ਤੇ ਡਬਲ-ਲਾਈਨ ਘੜੀ ਦਿਖਾਓ" "ਡਬਲ-ਲਾਈਨ ਘੜੀ" + + + diff --git a/res/values-pl/strings.xml b/res/values-pl/strings.xml index e61b7ddf77c..11cad4f30d5 100644 --- a/res/values-pl/strings.xml +++ b/res/values-pl/strings.xml @@ -596,12 +596,9 @@ "Zarejestrowano %d procent" "Rejestruję odcisk palca – %d procent" "Odcisk palca dodany" - - - - - - + "Możesz teraz używać odcisku palca do odblokowywania tabletu oraz weryfikacji tożsamości, na przykład podczas logowania się w aplikacjach i zatwierdzania zakupów" + "Możesz teraz używać odcisku palca do odblokowywania urządzenia oraz weryfikacji tożsamości, na przykład podczas logowania się w aplikacjach i zatwierdzania zakupów" + "Możesz teraz używać odcisku palca do odblokowywania telefonu oraz weryfikacji tożsamości, na przykład podczas logowania się w aplikacjach i zatwierdzania zakupów" "Odblokowuj tylko przy włączonym ekranie" "Zanim odblokujesz urządzenie odciskiem palca, ekran musi zostać włączony. Dzięki temu trudniej przypadkowo odblokować urządzenie." "Ekran, odblokowywanie" @@ -3574,8 +3571,7 @@ "Usuń użytkownika %1$s z tego urządzenia" "Ustawienia ekranu blokady" "Dodawaj użytkowników na ekranie blokady" - - + "Po zadokowaniu przełącz się na administratora" "Chcesz usunąć siebie?" "Usunąć tego użytkownika?" "Usunąć ten profil?" @@ -5847,6 +5843,9 @@ "Aby tego użyć, musisz najpierw włączyć „Pokazuj sterowanie urządzeniami”" "Pokazuj zegar dwuwierszowy, jeśli jest dostępny" "Zegar dwuwierszowy" + + + diff --git a/res/values-pt-rBR/strings.xml b/res/values-pt-rBR/strings.xml index eb9e6be892b..12873168246 100644 --- a/res/values-pt-rBR/strings.xml +++ b/res/values-pt-rBR/strings.xml @@ -594,12 +594,9 @@ "Impressão digital adicionada" - - - - - - + "Agora, você pode usar a impressão digital para desbloquear o tablet ou confirmar sua identidade, como ao fazer login em apps ou aprovar uma compra" + "Agora, você pode usar a impressão digital para desbloquear o dispositivo ou confirmar sua identidade, como ao fazer login em apps ou aprovar uma compra" + "Agora, você pode usar a impressão digital para desbloquear o smartphone ou confirmar sua identidade, como ao fazer login em apps ou aprovar uma compra" "Desbloquear somente quando a tela estiver ativada" "A tela precisa estar ativada para desbloquear o dispositivo com sua impressão digital. Isso diminui as chances de desbloqueio acidental." "Tela, Desbloqueio" @@ -3496,8 +3493,7 @@ "Excluir %1$s do dispositivo" "Configurações de tela de bloqueio" "Adicionar usuários na tela de bloqueio" - - + "Mudar para usuário admin quando encaixado na base" "Excluir a si mesmo?" "Excluir este usuário?" "Remover este perfil?" @@ -5653,8 +5649,8 @@ "Padrão do sistema" "Essa opção não é mais válida. Tente novamente." "controles do dispositivo" - "Cartões e passes" - "cartões e passes" + "Cartões de pagamento e de transporte" + "cartões e tickets" "Aperte o botão liga/desliga e o mantenha pressionado" "Mantenha o botão liga/desliga pressionado para acessar" "Menu liga/desliga" @@ -5679,6 +5675,9 @@ "Para usar, ative a opção \"Mostrar controles do dispositivo\"" "Mostrar o relógio de duas linhas quando disponível" "Relógio de duas linhas" + + + diff --git a/res/values-pt-rPT/strings.xml b/res/values-pt-rPT/strings.xml index 5f1ada2db38..721b3353790 100644 --- a/res/values-pt-rPT/strings.xml +++ b/res/values-pt-rPT/strings.xml @@ -588,12 +588,9 @@ "%d por cento de inscrições" "Inscrição da impressão digital: %d por cento" "Impressão digital adicionada" - - - - - - + "Já pode usar a impressão digital para desbloquear o tablet ou validar a sua identidade, como quando inicia sessão em apps ou aprova uma compra" + "Já pode usar a impressão digital para desbloquear o dispositivo ou validar a sua identidade, como quando inicia sessão em apps ou aprova uma compra" + "Já pode usar a impressão digital para desbloquear o telemóvel ou validar a sua identidade, como quando inicia sessão em apps ou aprova uma compra" "Desbloquear apenas quando o ecrã está ligado" "O ecrã tem de estar ativado antes de poder desbloquear com a sua impressão digital. Isto torna o desbloqueio acidental menos provável." "Ecrã, desbloqueio" @@ -2189,7 +2186,7 @@ "Sem apps." "Armaz. interno" "A recalcular tamanho..." - "Eliminar dados da app?" + "Apagar dados da app?" "Os dados desta app, incluindo ficheiros e definições, vão ser eliminados permanentemente deste dispositivo" "OK" "Cancelar" @@ -3490,8 +3487,7 @@ "Eliminar %1$s deste dispositivo" "Definições do ecrã de bloqueio" "Adicionar utilizadores a partir do ecrã de bloqueio" - - + "Mudar p/ utilizador administrador quando ancorado" "Eliminar-se a si próprio?" "Eliminar este utilizador?" "Remover este perfil?" @@ -5673,6 +5669,9 @@ "Para usar, ative primeiro a opção \"Mostrar controlos de dispositivos\"" "Apresente o relógio de duas linhas quando estiver disponível" "Relógio de duas linhas" + + + diff --git a/res/values-pt/strings.xml b/res/values-pt/strings.xml index eb9e6be892b..12873168246 100644 --- a/res/values-pt/strings.xml +++ b/res/values-pt/strings.xml @@ -594,12 +594,9 @@ "Impressão digital adicionada" - - - - - - + "Agora, você pode usar a impressão digital para desbloquear o tablet ou confirmar sua identidade, como ao fazer login em apps ou aprovar uma compra" + "Agora, você pode usar a impressão digital para desbloquear o dispositivo ou confirmar sua identidade, como ao fazer login em apps ou aprovar uma compra" + "Agora, você pode usar a impressão digital para desbloquear o smartphone ou confirmar sua identidade, como ao fazer login em apps ou aprovar uma compra" "Desbloquear somente quando a tela estiver ativada" "A tela precisa estar ativada para desbloquear o dispositivo com sua impressão digital. Isso diminui as chances de desbloqueio acidental." "Tela, Desbloqueio" @@ -3496,8 +3493,7 @@ "Excluir %1$s do dispositivo" "Configurações de tela de bloqueio" "Adicionar usuários na tela de bloqueio" - - + "Mudar para usuário admin quando encaixado na base" "Excluir a si mesmo?" "Excluir este usuário?" "Remover este perfil?" @@ -5653,8 +5649,8 @@ "Padrão do sistema" "Essa opção não é mais válida. Tente novamente." "controles do dispositivo" - "Cartões e passes" - "cartões e passes" + "Cartões de pagamento e de transporte" + "cartões e tickets" "Aperte o botão liga/desliga e o mantenha pressionado" "Mantenha o botão liga/desliga pressionado para acessar" "Menu liga/desliga" @@ -5679,6 +5675,9 @@ "Para usar, ative a opção \"Mostrar controles do dispositivo\"" "Mostrar o relógio de duas linhas quando disponível" "Relógio de duas linhas" + + + diff --git a/res/values-ro/strings.xml b/res/values-ro/strings.xml index a1733fd9c21..57c5397d73a 100644 --- a/res/values-ro/strings.xml +++ b/res/values-ro/strings.xml @@ -598,12 +598,9 @@ "Amprentă adăugată" - - - - - - + "Acum îți poți folosi amprenta pentru a-ți debloca tableta sau pentru a-ți confirma identitatea, de exemplu, când te conectezi la aplicații sau aprobi o achiziție" + "Acum îți poți folosi amprenta pentru a-ți debloca dispozitivul sau pentru a-ți confirma identitatea, de exemplu, când te conectezi la aplicații sau aprobi o achiziție" + "Acum îți poți folosi amprenta pentru a-ți debloca telefonul sau pentru a-ți confirma identitatea, de exemplu, când te conectezi la aplicații sau aprobi o achiziție" "Deblochează numai când ecranul este activ" "Ecranul trebuie să fie activat ca să poți debloca folosind amprenta. Astfel, scade riscul de deblocare accidentală." "Ecran, Deblocare" @@ -3538,8 +3535,7 @@ "Șterge %1$s de pe dispozitiv" "Setările ecranului de blocare" "Adaugă utilizatori din ecranul de blocare" - - + "Treci la administrator când este andocat" "Te excluzi ca utilizator?" "Ștergi utilizatorul?" "Elimini acest profil?" @@ -5766,6 +5762,9 @@ "Pentru a folosi funcția, mai întâi activează opțiunea Afișează comenzile dispozitivului" "Afișează ceasul cu două linii când este disponibil" "Ceas cu două linii" + + + diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml index 863889a271c..bac662fdd56 100644 --- a/res/values-ru/strings.xml +++ b/res/values-ru/strings.xml @@ -596,12 +596,9 @@ "Процент выполнения: %d" "Процент выполнения задачи по добавлению отпечатка пальца: %d." "Отпечаток добавлен" - - - - - - + "Теперь вы можете использовать отпечаток пальца, чтобы разблокировать планшет и подтверждать свою личность, например для входа в приложения и одобрения покупок." + "Теперь вы можете использовать отпечаток пальца, чтобы разблокировать устройство и подтверждать свою личность, например для входа в приложения и одобрения покупок." + "Теперь вы можете использовать отпечаток пальца, чтобы разблокировать телефон и подтверждать свою личность, например для входа в приложения и одобрения покупок." "Разблокировка только при включенном экране" "Разблокировать устройство можно, только когда экран включен. Это снижает вероятность случайной разблокировки." "Экран, разблокировка" @@ -3574,8 +3571,7 @@ "Удалить пользователя %1$s" "Заблокированный экран" "Добавить пользователя ­на заблокированном экране" - - + "На док-станции переключаться на администратора" "Удалить ваш профиль?" "Удалить пользователя?" "Удалить профиль?" @@ -5847,6 +5843,9 @@ "Чтобы использовать эту функцию, включите параметр \"Показывать виджеты управления устройством\"" "Показывать вертикальные часы, если они доступны" "Вертикальные часы" + + + diff --git a/res/values-si/strings.xml b/res/values-si/strings.xml index 0859475a25e..2f78ea5dfd6 100644 --- a/res/values-si/strings.xml +++ b/res/values-si/strings.xml @@ -588,12 +588,9 @@ "ලියාපදිංචි වූයේ සියයට %dයි" "ඇඟිලි සලකුණ සියයට %dක් ලියාපදිංචි කරමින්" "ඇඟිලි සලකුණ එක් කරන ලදී" - - - - - - + "දැන් ඔබට ඔබේ ටැබ්ලටය අගුළු හැරීමට හෝ ඔබ යෙදුම් වෙත පුරනය වන විට හෝ මිල දී ගැනීමක් අනුමත කරන විට ඒ ඔබ බව සත්‍යාපනය කිරීමට ඔබේ ඇඟිලි සලකුණ භාවිතා කළ හැක" + "දැන් ඔබට ඔබේ උපාංගය අගුළු හැරීමට හෝ ඔබ යෙදුම් වෙත පුරනය වන විට හෝ මිල දී ගැනීමක් අනුමත කරන විට ඒ ඔබ බව සත්‍යාපනය කිරීමට ඔබේ ඇඟිලි සලකුණ භාවිතා කළ හැක" + "දැන් ඔබට ඔබේ දුරකථනය අගුළු හැරීමට හෝ ඔබ යෙදුම් වෙත පුරනය වන විට හෝ මිල දී ගැනීමක් අනුමත කරන විට ඒ ඔබ බව සත්‍යාපනය කිරීමට ඔබේ ඇඟිලි සලකුණ භාවිතා කළ හැක" "තිරය ක්‍රියාත්මක විට පමණක් අගුළු හරින්න" "ඔබට ඔබේ ඇඟිලි සලකුණ සමග අගුළු හැරීමට පෙර තිරය ක්‍රියාත්මක විය යුතු වේ. මෙය අහම්බෙන් අගුළු හැරීමේ හැකියාව අඩු කරයි." "තිර, අගුළු හැරීම" @@ -3490,8 +3487,7 @@ "මෙම උපාංගයෙන් %1$s මකන්න" "අගුලු තිර සැකසීම්" "අගුලු තිරයෙන් පරිශීලකයන් එක් කරන්න" - - + "ඈඳූ වූ විට පරිපාලක පරිශීලක වෙත මාරු වන්න" "ඔබව මකන්නද?" "මෙම පරිශීලකයා මකන්නද?" "මෙම පැතිකඩ ඉවත් කරන්නද?" @@ -5673,6 +5669,9 @@ "භාවිත කිරීමට, පළමුව \"උපාංග පාලන පෙන්වන්න\" ක්‍රියාත්මක කරන්න" "ලබා ගත හැකි විට ද්විත්ව රේඛා ඔරලෝසුව පෙන්වන්න" "ද්විත්ව රේඛා ඔරලෝසුව" + + + diff --git a/res/values-sk/strings.xml b/res/values-sk/strings.xml index 4ba315ec8bf..8e3e20438f9 100644 --- a/res/values-sk/strings.xml +++ b/res/values-sk/strings.xml @@ -602,12 +602,9 @@ "Odtlačok prsta bol pridaný" - - - - - - + "Teraz môžete odomykať tablet alebo overovať svoju totožnosť odtlačkom prsta, napríklad pri prihlasovaní do aplikácií alebo schvaľovaní nákupov" + "Teraz môžete odomykať zariadenie alebo overovať svoju totožnosť odtlačkom prsta, napríklad pri prihlasovaní do aplikácií alebo schvaľovaní nákupov" + "Teraz môžete odomykať telefón alebo overovať svoju totožnosť odtlačkom prsta, napríklad pri prihlasovaní do aplikácií alebo schvaľovaní nákupov" "Odomykať, iba keď je obrazovka zapnutá" "Ak chcete obrazovku odomknúť odtlačkom prsta, musí byť najprv zapnutá. Zníži sa tým pravdepodobnosť náhodného odomknutia." "Obrazovka, odomknutie" @@ -3580,8 +3577,7 @@ "Odstrániť zo zariadenia (%1$s)" "Nastavenia uzamknutej obrazovky" "Pridávať používateľov z uzamknutej obrazovky" - - + "V doku prepnúť na používateľa s oprávnen. správcu" "Chcete odstrániť svoj profil?" "Chcete odstrániť používateľa?" "Odstrániť tento profil?" @@ -5853,6 +5849,9 @@ "Ak ho chcete použiť, najprv musíte zapnúť Zobraziť ovládanie zariadení" "Zobrazovať hodiny na dva riadky (keď sú k dispozícii)" "Hodiny na dva riadky" + + + diff --git a/res/values-sl/strings.xml b/res/values-sl/strings.xml index da55634001a..27cc23a0ea1 100644 --- a/res/values-sl/strings.xml +++ b/res/values-sl/strings.xml @@ -602,12 +602,9 @@ "Prstni odtis je dodan" - - - - - - + "Zdaj lahko s prstnim odtisom odklenete tablični računalnik ali potrdite svojo identiteto, na primer ob prijavi v aplikacije ali odobritvi nakupa." + "Zdaj lahko s prstnim odtisom odklenete napravo ali potrdite svojo identiteto, na primer ob prijavi v aplikacije ali odobritvi nakupa." + "Zdaj lahko s prstnim odtisom odklenete telefon ali potrdite svojo identiteto, na primer ob prijavi v aplikacije ali odobritvi nakupa." "Odklepanje samo pri vklopljenem zaslonu" "Zaslon mora biti vklopljen, preden lahko odklenete s prstnim odtisom. Tako zmanjšate verjetnost nenamernega odklepanja." "Zaslon, odklepanje" @@ -3580,8 +3577,7 @@ "Izbris up. %1$s iz napr." "Nastavitve zaklepanja zaslona" "Dodajanje uporabnikov na zaklenjenem zaslonu" - - + "Preklopi na skrbniš. uporabnika, ko je v nosilcu" "Želite izbrisati sebe?" "Želite izbrisati uporabnika?" "Odstranitev profila?" @@ -5853,6 +5849,9 @@ "Za uporabo najprej vklopite »Prikaži kontrolnike naprave«." "Prikaz ure v dveh vrsticah, ko je na voljo" "Ura v dveh vrsticah" + + + diff --git a/res/values-sq/strings.xml b/res/values-sq/strings.xml index e1f040bd863..e7e2d2a1e2c 100644 --- a/res/values-sq/strings.xml +++ b/res/values-sq/strings.xml @@ -588,12 +588,9 @@ "Regjistruar %d për qind" "Regjistrimi i gjurmës së gishtit: %d për qind" "Gjurma e gishtit u shtua" - - - - - - + "Tani mund të përdorësh gjurmën tënde të gishtit për të shkyçur tabletin tënd ose për të verifikuar që je ti, si për shembull kur identifikohesh në aplikacione ose kur miraton një blerje" + "Tani mund të përdorësh gjurmën tënde të gishtit për të shkyçur pajisjen tënde ose për të verifikuar që je ti, si për shembull kur identifikohesh në aplikacione ose kur miraton një blerje" + "Tani mund të përdorësh gjurmën tënde të gishtit për të shkyçur telefonin tënd ose për të verifikuar që je ti, si për shembull kur identifikohesh në aplikacione ose kur miraton një blerje" "Shkyç vetëm kur ekrani është i ndezur" "Ekrani duhet të jetë i ndezur para se të mund ta shkyçësh me gjurmën tënde të gishtit. Kjo bën që shkyçja aksidentale të ketë më pak gjasë të ndodhë." "Ekrani; Shkyçja" @@ -3490,8 +3487,7 @@ "Fshije %1$s nga pajisja" "Cilësimet e ekranit të kyçjes" "Shto përdoruesit nga ekrani i kyçjes" - - + "Kalo te përdoruesi administrator kur stacionohet" "Do e fshish veten?" "Të fshihet ky përdorues?" "Të hiqet ky profil?" @@ -5673,6 +5669,9 @@ "Për ta përdorur, fillimisht aktivizo \"Shfaq kontrollet e pajisjes\"" "Shfaq orën analoge kur ofrohet" "Orë analoge" + + + diff --git a/res/values-sr/strings.xml b/res/values-sr/strings.xml index 7532b2afd47..72fd24e7e95 100644 --- a/res/values-sr/strings.xml +++ b/res/values-sr/strings.xml @@ -592,12 +592,9 @@ "Регистровано је %d посто" "Регистровање отиска прста је на %d посто" "Отисак прста је додат" - - - - - - + "Сада можете да користите отисак прста за откључавање таблета или потврду идентитета, на пример, кад се пријављујете у апликације или одобравате куповину" + "Сада можете да користите отисак прста за откључавање уређаја или потврду идентитета, на пример, кад се пријављујете у апликације или одобравате куповину" + "Сада можете да користите отисак прста за откључавање телефона или потврду идентитета, на пример, кад се пријављујете у апликације или одобравате куповину" "Откључавање само када је екран укључен" "Екран мора да буде укључен да бисте могли да откључате отиском прста. То смањује вероватноћу за случајно откључавање." "Екран, откључавање" @@ -3532,8 +3529,7 @@ "Избриши %1$s са уређаја" "Подешавања закључаног екрана" "Додај кориснике са закључаног екрана" - - + "Пређи на администратора на базној станици" "Желите ли да избришете себе?" "Бришете овог корисника?" "Уклањате овај профил?" @@ -5760,6 +5756,9 @@ "Да бисте користили, прво укључите Прикажи контроле уређаја" "Приказује дволинијски сат када је доступан" "Дволинијски сат" + + + diff --git a/res/values-sv/strings.xml b/res/values-sv/strings.xml index 457c9c5dafa..efe24b73e24 100644 --- a/res/values-sv/strings.xml +++ b/res/values-sv/strings.xml @@ -3487,8 +3487,7 @@ "Ta bort %1$s från enheten" "Inställningar för låsskärm" "Lägg till användare från låsskärmen" - - + "Byt till administratörsanvändare vid dockning" "Vill du ta bort dig själv?" "Ska användaren raderas?" "Vill du ta bort profilen?" @@ -5670,6 +5669,9 @@ "Aktivera först Visa enhetsstyrning för att använda" "Visa klocka på två rader när så är möjligt" "Klocka på två rader" + + + diff --git a/res/values-sw/strings.xml b/res/values-sw/strings.xml index 50d1777b102..9131f67f51a 100644 --- a/res/values-sw/strings.xml +++ b/res/values-sw/strings.xml @@ -588,12 +588,9 @@ "Imeandikishwa kwa asilimia %d" "Imeandikisha asilimia %d ya alama ya kidole" "Alama ya kidole imeongezwa" - - - - - - + "Sasa unaweza kutumia alama ya kidole chako kufungua kompyuta kibao yako au kuthibitisha kuwa ni wewe, kama vile unapoingia katika akaunti kwenye programu au unapoidhinisha ununuzi" + "Sasa unaweza kutumia alama ya kidole chako kufungua kifaa chako au kuthibitisha kuwa ni wewe, kama vile unapoingia katika akaunti kwenye programu au unapoidhinisha ununuzi" + "Sasa unaweza kutumia alama ya kidole chako kufungua simu yako au kuthibitisha kuwa ni wewe, kama vile unapoingia katika akaunti kwenye programu au unapoidhinisha ununuzi" "Fungua tu skrini inapowashwa" "Ni lazima skrini iwashwe kabla uweze kufungua kwa kutumia alama yako ya kidole. Hali hii hupunguza uwezekano wa kufungua kwa bahati mbaya." "Skrini, Fungua" @@ -3490,8 +3487,7 @@ "Futa %1$s kutoka kwenye kifaa hiki" "Mipangilio ya kufunga skrini" "Ongeza watumiaji skrini ikiwa imefungwa" - - + "Rudisha kwa mtumiaji msimamizi wakati kimeambatishwa" "Ungependa kujifuta?" "Ungependa kumfuta mtumiaji huyu?" "Ungependa kuondoa wasifu?" @@ -5674,6 +5670,9 @@ "Ili utumie, washa kwanza \"Onyesha vidhibiti vya vifaa\"" "Onyesha saa yenye mistari miwili inapopatikana" "Saa yenye mistari miwili" + + + diff --git a/res/values-ta/strings.xml b/res/values-ta/strings.xml index 3e0c8f56856..b0095c08d62 100644 --- a/res/values-ta/strings.xml +++ b/res/values-ta/strings.xml @@ -588,12 +588,9 @@ "%d சதவீதம் பதிவுசெய்யப்பட்டுள்ளது" "கைரேகை %d சதவீதம் பதிவுசெய்யப்பட்டது" "கைரேகை சேர்க்கப்பட்டது" - - - - - - + "இப்போது உங்கள் கைரேகையைப் பயன்படுத்தி டேப்லெட்டை அன்லாக் செய்யலாம் அல்லது ஆப்ஸில் உள்நுழைதல், பர்ச்சேஸை அங்கீகரித்தல் போன்ற செயல்பாடுகளின்போது அது நீங்கள்தான் என்பதை உறுதிப்படுத்தலாம்" + "இப்போது உங்கள் கைரேகையைப் பயன்படுத்தி சாதனத்தை அன்லாக் செய்யலாம் அல்லது ஆப்ஸில் உள்நுழைதல், பர்ச்சேஸை அங்கீகரித்தல் போன்ற செயல்பாடுகளின்போது அது நீங்கள்தான் என்பதை உறுதிப்படுத்தலாம்" + "இப்போது உங்கள் கைரேகையைப் பயன்படுத்தி மொபைலை அன்லாக் செய்யலாம் அல்லது ஆப்ஸில் உள்நுழைதல், பர்ச்சேஸை அங்கீகரித்தல் போன்ற செயல்பாடுகளின்போது அது நீங்கள்தான் என்பதை உறுதிப்படுத்தலாம்" "திரை இயக்கத்தில் இருக்கும்போது மட்டும் அன்லாக் செய்தல்" "உங்கள் கைரேகை மூலம் அன்லாக் செய்யும் முன்பு திரை இயக்கத்தில் இருக்க வேண்டும். இது தற்செயலாக அன்லாக் செய்யப்படுவதைக் குறைக்கும்." "திரையை அன்லாக் செய்யும்" @@ -3490,8 +3487,7 @@ "சாதனத்திலிருந்து %1$s ஐ நீக்கு" "லாக் ஸ்கிரீன் அமைப்புகள்" "லாக் ஸ்கிரீனிலிருந்து பயனர்களைச் சேர்" - - + "இணைந்திருக்கும்போது நிர்வாகப் பயனருக்கு மாறும்" "உங்களை நீக்கவா?" "இந்தப் பயனரை நீக்கவா?" "இதை அகற்றவா?" @@ -5673,6 +5669,9 @@ "பயன்படுத்த வேண்டுமெனில் \"சாதனக் கட்டுப்பாடுகளைக் காட்டு\" என்பதை முதலில் இயக்கவும்" "இயக்கத்தில் இருக்கும்போது இரட்டை-வரிக் கடிகாரத்தைக் காட்டும்" "இரட்டை-வரிக் கடிகாரம்" + + + diff --git a/res/values-te/strings.xml b/res/values-te/strings.xml index 5b86cfe4b45..1b359858706 100644 --- a/res/values-te/strings.xml +++ b/res/values-te/strings.xml @@ -588,12 +588,9 @@ "%d శాతం ఎన్‌రోల్ చేయబడింది" "వేలిముద్ర %d శాతం ఎన్‌రోల్ అవుతోంది" "వేలిముద్ర జోడించబడింది" - - - - - - + "ఇప్పుడు మీరు మీ టాబ్లెట్‌ను అన్‌లాక్ చేయడానికి లేదా మీరు యాప్‌లకు సైన్ ఇన్ చేయడం లేదా కొనుగోలును ఆమోదించడం వంటివి చేసినప్పుడు, అది మీరేనని వెరిఫై చేయడానికి మీ వేలిముద్రను ఉపయోగించవచ్చు" + "ఇప్పుడు మీరు మీ పరికరాన్ని అన్‌లాక్ చేయడానికి లేదా మీరు యాప్‌లకు సైన్ ఇన్ చేయడం లేదా కొనుగోలును ఆమోదించడం వంటివి చేసినప్పుడు, అది మీరేనని వెరిఫై చేయడానికి మీ వేలిముద్రను ఉపయోగించవచ్చు" + "ఇప్పుడు మీరు మీ ఫోన్‌ను అన్‌లాక్ చేయడానికి లేదా మీరు యాప్‌లకు సైన్ ఇన్ చేయడం లేదా కొనుగోలును ఆమోదించడం వంటివి చేసినప్పుడు, అది మీరేనని వెరిఫై చేయడానికి మీ వేలిముద్రను ఉపయోగించవచ్చు" "స్క్రీన్ ఆన్‌లో ఉన్నప్పుడు మాత్రమే అన్‌లాక్ చేయండి" "మీరు మీ వేలిముద్రతో అన్‌లాక్ చేయడానికి ముందు స్క్రీన్ తప్పనిసరిగా ఆన్‌లో ఉండాలి. ఇది ప్రమాదవశాత్తూ అన్‌లాక్ అయ్యే అవకాశం తక్కువగా ఉంటుంది." "స్క్రీన్, అన్‌లాక్" @@ -3490,8 +3487,7 @@ "ఈ పరికరం నుండి %1$sని తొలగించు" "లాక్ స్క్రీన్ సెట్టింగ్‌లు" "లాక్ స్క్రీన్ నుండి యూజ‌ర్‌ల‌ను జోడించండి" - - + "డాక్ చేసినప్పుడు అడ్మిన్ యూజర్‌కు స్విచ్ అవ్వండి" "మిమ్మల్ని తొలగించాలా?" "ఈ యూజర్‌ను తొలగించాలా?" "ఈ ప్రొఫైల్‌ను తీసివేయాలా?" @@ -5673,6 +5669,9 @@ "ఉపయోగించడానికి, ముందుగా \"డివైజ్ కంట్రోల్స్‌ను చూపించండి\" ఆప్షన్‌ను ఆన్ చేయండి" "అందుబాటులో ఉన్నప్పుడు, డబుల్ లైన్ గడియారం చూపండి" "డబుల్ లైన్ గడియారం" + + + diff --git a/res/values-th/strings.xml b/res/values-th/strings.xml index e8752097281..6cd995c3e7f 100644 --- a/res/values-th/strings.xml +++ b/res/values-th/strings.xml @@ -588,12 +588,9 @@ "ลงทะเบียนแล้ว %d เปอร์เซ็นต์" "กำลังลงทะเบียนลายนิ้วมือ %d เปอร์เซ็นต์" "เพิ่มลายนิ้วมือแล้ว" - - - - - - + "ตอนนี้คุณสามารถใช้ลายนิ้วมือเพื่อปลดล็อกแท็บเล็ตหรือยืนยันว่าเป็นคุณ เช่น เมื่อลงชื่อเข้าใช้แอปหรืออนุมัติการซื้อ" + "ตอนนี้คุณสามารถใช้ลายนิ้วมือเพื่อปลดล็อกอุปกรณ์หรือยืนยันว่าเป็นคุณ เช่น เมื่อลงชื่อเข้าใช้แอปหรืออนุมัติการซื้อ" + "ตอนนี้คุณสามารถใช้ลายนิ้วมือเพื่อปลดล็อกโทรศัพท์หรือยืนยันว่าเป็นคุณ เช่น เมื่อลงชื่อเข้าใช้แอปหรืออนุมัติการซื้อ" "ปลดล็อกเฉพาะเวลาที่หน้าจอเปิดอยู่เท่านั้น" "หน้าจอต้องเปิดอยู่จึงจะปลดล็อกด้วยลายนิ้วมือได้ ซึ่งจะช่วยลดการปลดล็อกโดยไม่ได้ตั้งใจ" "ปลดล็อกหน้าจอ" @@ -3490,8 +3487,7 @@ "ลบ %1$s จากอุปกรณ์นี้" "การตั้งค่าหน้าจอล็อก" "เพิ่มผู้ใช้จากหน้าจอล็อก" - - + "เปลี่ยนเป็นผู้ใช้ที่ดูแลระบบเมื่อวางบนแท่นชาร์จ" "ลบตัวคุณเองไหม" "ลบผู้ใช้รายนี้ใช่ไหม" "นำโปรไฟล์นี้ออกใช่ไหม" @@ -5673,6 +5669,9 @@ "หากต้องการใช้งาน ให้เปิด \"แสดงระบบควบคุมอุปกรณ์\" ก่อน" "แสดงนาฬิกาแบบสองบรรทัดเมื่อเป็นไปได้" "นาฬิกาแบบสองบรรทัด" + + + diff --git a/res/values-tl/strings.xml b/res/values-tl/strings.xml index f7900ce2784..2c8c7c48ec3 100644 --- a/res/values-tl/strings.xml +++ b/res/values-tl/strings.xml @@ -588,12 +588,9 @@ "Na-enroll ang %d (na) porsyento" "Pag-enroll ng fingerprint: %d porsyento" "Naidagdag na ang fingerprint" - - - - - - + "Magagamit mo na ang iyong fingerprint para i-unlock ang tablet mo o i-verify na ikaw ito, halimbawa, kapag nagsa-sign in ka sa mga app o nag-aapruba ng pagbili" + "Magagamit mo na ang iyong fingerprint para i-unlock ang device mo o i-verify na ikaw ito, halimbawa, kapag nagsa-sign in ka sa mga app o nag-aapruba ng pagbili" + "Magagamit mo na ang iyong fingerprint para i-unlock ang telepono mo o i-verify na ikaw ito, halimbawa, kapag nagsa-sign in ka sa mga app o nag-aapruba ng pagbili" "Mag-unlock lang kapag naka-on ang screen" "Naka-on dapat ang screen bago mo magawang mag-unlock gamit ang iyong fingerprint. Binabawasan nito ang posibilidad ng aksidenteng pag-unlock." "Screen, I-unlock" @@ -3490,8 +3487,7 @@ "Tanggal %1$s dito device" "Mga setting ng lock screen" "Magdagdag ng mga user mula sa lock screen" - - + "Lumipat sa admin user kapag naka-dock" "I-delete ang iyong sarili?" "I-delete ang user na ito?" "Alisin ang profile?" @@ -5673,6 +5669,9 @@ "Para magamit, i-on muna ang \"Ipakita ang mga kontrol ng device\"" "Ipakita ang orasang may dalawang linya kapag available" "Orasang may dalawang linya" + + + diff --git a/res/values-tr/strings.xml b/res/values-tr/strings.xml index f7dc5637131..5cf361fc5ab 100644 --- a/res/values-tr/strings.xml +++ b/res/values-tr/strings.xml @@ -588,12 +588,9 @@ "Kaydolma işlemi yüzde %d tamamlandı" "Parmak izi kaydı yüzde %d" "Parmak izi eklendi" - - - - - - + "Artık tabletinizin kilidini açarken veya uygulamalarda oturum açmak ya da satın alma işlemlerini onaylamak gibi işlemler için kimliğinizi doğrularken parmak izinizi kullanabilirsiniz" + "Artık cihazınızın kilidini açarken veya uygulamalarda oturum açmak ya da satın alma işlemlerini onaylamak gibi işlemler için kimliğinizi doğrularken parmak izinizi kullanabilirsiniz" + "Artık telefonunuzun kilidini açarken veya uygulamalarda oturum açmak ya da satın alma işlemlerini onaylamak gibi işlemler için kimliğinizi doğrularken parmak izinizi kullanabilirsiniz" "Yalnızca ekran açıkken kilidi aç" "Parmak izinizi kullanarak kilidi açabilmeniz için önce ekranı açmanız gerekir. Bu şekilde, yanlışlıkla kilit açma ihtimali azalır." "Ekran kilidini açma" @@ -3490,8 +3487,7 @@ "Bu cihazdan sil: %1$s" "Kilit ekranı ayarları" "Kilit ekranından kullanıcı eklensin" - - + "Yuvaya yerleştirildiğinde yönetici kullanıcıya geç" "Kendinizi silmek istiyor musunuz?" "Bu kullanıcı silinsin mi?" "Bu profil kaldırılsın mı?" @@ -5673,6 +5669,9 @@ "Kullanmak için önce \"Cihaz denetimlerini göster\" seçeneğini etkinleştirin" "Kullanılabilir olduğunda çift çizgili saati göster" "Çift çizgili saat" + + + diff --git a/res/values-uk/strings.xml b/res/values-uk/strings.xml index 5b06609a278..c6fd299d808 100644 --- a/res/values-uk/strings.xml +++ b/res/values-uk/strings.xml @@ -600,12 +600,9 @@ "Реєстрацію відбитка пальця завершено на стільки відсотків: %d" "Відбиток додано" - - - - - - + "Тепер за допомогою відбитка пальця можна розблоковувати планшет або підтверджувати свою особу (наприклад, щоб входити в додатки чи схвалювати покупки)" + "Тепер за допомогою відбитка пальця можна розблоковувати пристрій або підтверджувати свою особу (наприклад, щоб входити в додатки чи схвалювати покупки)" + "Тепер за допомогою відбитка пальця можна розблоковувати телефон або підтверджувати свою особу (наприклад, щоб входити в додатки чи схвалювати покупки)" "Розблоковувати, лише коли екран увімкнено" "Перш ніж розблоковувати пристрій відбитком пальця, потрібно ввімкнути екран. Це зменшить імовірність випадкового розблокування." "Екран, розблокування" @@ -3578,8 +3575,7 @@ "%1$s – видалити з пристрою" "Параметри блокування екрана" "Додавати користувачів на заблокованому екрані" - - + "Переходити в режим адміністратора в док-станції" "Видалити ваш профіль?" "Видалити користувача?" "Видалити цей профіль?" @@ -5851,6 +5847,9 @@ "Щоб використовувати елементи керування, спершу ввімкніть опцію \"Показувати елементи керування пристроями\"" "Показувати дворядковий годинник, коли можливо" "Дворядковий годинник" + + + diff --git a/res/values-ur/strings.xml b/res/values-ur/strings.xml index 463dedaf447..366c8f77d1b 100644 --- a/res/values-ur/strings.xml +++ b/res/values-ur/strings.xml @@ -588,12 +588,9 @@ "اندراج: %d فیصد" "فنگر پرنٹ اندراج کرنے کی کارروائی %d فیصد مکمل ہو چکی ہے" "فنگر پرنٹ شامل ہو گیا" - - - - - - + "اب آپ اپنا ٹیبلیٹ غیر مقفل کرنے یا اس بات کی توثیق کرنے کیلئے اپنے فنگر پرنٹ کا استعمال کر سکتے ہیں کہ یہ آپ ہی ہیں، جیسے جب آپ ایپس میں سائن ان کرتے ہیں یا کسی خریداری کی منظوری دیتے ہیں" + "اب آپ اپنا آلہ غیر مقفل کرنے یا اس بات کی توثیق کرنے کیلئے اپنے فنگر پرنٹ کا استعمال کر سکتے ہیں کہ یہ آپ ہی ہیں، جیسے جب آپ ایپس میں سائن ان کرتے ہیں یا کسی خریداری کی منظوری دیتے ہیں" + "اب آپ اپنا فون غیر مقفل کرنے یا اس بات کی توثیق کرنے کیلئے اپنے فنگر پرنٹ کا استعمال کر سکتے ہیں کہ یہ آپ ہی ہیں، جیسے جب آپ ایپس میں سائن ان کرتے ہیں یا کسی خریداری کی منظوری دیتے ہیں" "اسکرین آن ہونے پر ہی غیر مقفل کریں۔" "آپ کے فنگر پرنٹ سے غیر مقفل کرنے کے لیے اسکرین کو فعال ہونا چاہیے۔ اس سے حادثاتی طور پر غیر مقفل ہونے کا امکان کم ہو جاتا ہے۔" "اسکرین کو غیر مقفل کریں" @@ -3490,8 +3487,7 @@ "اس آلہ سے %1$s حذف کریں" "قفل اسکرین کی ترتیبات" "مقفل اسکرین سے صارفین کو شامل کریں" - - + "ڈاک ہونے پر منتظم صارف پر سوئچ کریں" "اپنے آپ کو حذف کریں؟" "اس صارف کو حذف کریں؟" "یہ پروفائل ہٹا دیں؟" @@ -5673,6 +5669,9 @@ "استعمال کرنے کے لیے، پہلے \"آلہ کے کنٹرولز دکھائیں\" کو آن کریں" "دستیاب ہونے پر دو لائن والی گھڑی دکھائیں" "دو لائن والی گھڑی" + + + diff --git a/res/values-uz/strings.xml b/res/values-uz/strings.xml index cfe53eb1bee..7ab77dfa87f 100644 --- a/res/values-uz/strings.xml +++ b/res/values-uz/strings.xml @@ -594,12 +594,9 @@ "Barmoq izi qo‘shildi" - - - - - - + "Endi planshetni qulfdan chiqarish, ilovaga kirish yoki xaridni tasdiqlash kabi hisob tekshiruvida barmoq izidan foydalanishingiz mumkin" + "Endi qurilmani qulfdan chiqarish, ilovaga kirish yoki xaridni tasdiqlash kabi hisob tekshiruvida barmoq izidan foydalanishingiz mumkin" + "Endi telefonni qulfdan chiqarish, ilovaga kirish yoki xaridni tasdiqlash kabi hisob tekshiruvida barmoq izidan foydalanishingiz mumkin" "Faqat ekran yoniqligida qulfdan chiqarilsin" "Barmoq izingiz bilan ocha olishingiz mumkin oldin ekran yoniq boʻlishi kerak. Bu tasodifiy qulfni ochish ehtimolini kamaytiradi." "Ekran, qulfdan chiqarish" @@ -3496,8 +3493,7 @@ "Olib tashlash (%1$s)" "Qulflangan ekran sozlamalari" "Foydalanuvchilarni ekran qulfidan qo‘shish" - - + "Dok-stantsiyasiga ulanganda administratorga oʻtish" "Profilingiz o‘chirilsinmi?" "Olib tashlansinmi?" "Profil o‘chirilsinmi?" @@ -5679,6 +5675,9 @@ "Ishlatish uchun avval “Qurilma boshqaruvini chiqarish” sozlamasini yoqing" "Imkon boʻlganda ikki chiziqli soat chiqsin" "Ikki chiziqli soat" + + + diff --git a/res/values-vi/strings.xml b/res/values-vi/strings.xml index 85c7271943f..527338fb0e9 100644 --- a/res/values-vi/strings.xml +++ b/res/values-vi/strings.xml @@ -594,12 +594,9 @@ "Đã thêm vân tay" - - - - - - + "Giờ đây, bạn có thể dùng vân tay để mở khoá máy tính bảng hoặc xác minh danh tính, chẳng hạn như khi bạn đăng nhập vào ứng dụng hoặc phê duyệt giao dịch mua" + "Giờ đây, bạn có thể dùng vân tay để mở khoá thiết bị hoặc xác minh danh tính, chẳng hạn như khi bạn đăng nhập vào ứng dụng hoặc phê duyệt giao dịch mua" + "Giờ đây, bạn có thể dùng vân tay để mở khoá điện thoại hoặc xác minh danh tính, chẳng hạn như khi bạn đăng nhập vào ứng dụng hoặc phê duyệt giao dịch mua" "Chỉ mở khoá khi màn hình đang bật" "Màn hình phải bật thì bạn mới có thể mở khoá bằng vân tay. Yêu cầu này nhằm giảm thiểu tình trạng mở khoá ngoài ý muốn." "Màn hình, mở khoá" @@ -3496,8 +3493,7 @@ "Xóa %1$s khỏi thiết bị" "Cài đặt màn hình khóa" "Thêm người dùng từ màn hình khóa" - - + "Chuyển sang người dùng quản trị khi gắn vào đế sạc" "Xóa chính bạn?" "Xóa người dùng này?" "Xóa hồ sơ này?" @@ -4408,7 +4404,7 @@ "Cảnh báo" "Ok" "Đóng" - "Gửi phản hồi về thiết bị này" + "Gửi ý kiến phản hồi về thiết bị này" "Nhập mã PIN quản trị" "Đang bật" "Đang tắt" @@ -5593,7 +5589,7 @@ "Đã xóa đề xuất" "Hủy" "Sắp hết bộ nhớ. Đã dùng %1$s – Còn trống %2$s" - "Gửi phản hồi" + "Gửi ý kiến phản hồi" "Bạn có muốn cung cấp phản hồi về nội dung đề xuất này cho chúng tôi không?" "Đã sao chép %1$svào bảng nhớ tạm." @@ -5679,6 +5675,9 @@ "Để sử dụng, trước tiên, hãy bật tuỳ chọn \"Hiển thị các nút điều khiển thiết bị\"" "Hiện đồng hồ kép khi có" "Đồng hồ kép" + + + diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml index 6eb8c941276..1f4657d0c38 100644 --- a/res/values-zh-rCN/strings.xml +++ b/res/values-zh-rCN/strings.xml @@ -588,12 +588,9 @@ "当前注册进度为百分之 %d" "指纹注册进度为百分之 %d" "指纹已添加" - - - - - - + "现在您可以使用指纹解锁平板电脑或在需要时验证自己的身份,例如在登录应用或批准购买时" + "现在您可以使用指纹解锁设备或在需要时验证自己的身份,例如在登录应用或批准购买时" + "现在您可以使用指纹解锁手机或在需要时验证自己的身份,例如在登录应用或批准购买时" "仅在屏幕开启时解锁" "屏幕必须开启,然后您才能使用指纹解锁。这样可以降低意外解锁的可能性。" "屏幕, 解锁, Screen, Unlock" @@ -3490,8 +3487,7 @@ "将%1$s从此设备中删除" "锁定屏幕设置" "从锁定屏幕中添加用户" - - + "插入基座时切换到管理员用户" "是否删除自己?" "要删除此用户吗?" "要移除此个人资料吗?" @@ -5673,6 +5669,9 @@ "需要先开启“显示设备控制器”才能使用" "显示双行时钟(若可用)" "双行时钟" + + + diff --git a/res/values-zh-rHK/strings.xml b/res/values-zh-rHK/strings.xml index eea9300bc7a..0173f458d79 100644 --- a/res/values-zh-rHK/strings.xml +++ b/res/values-zh-rHK/strings.xml @@ -590,12 +590,9 @@ "已加入指紋" - - - - - - + "現在可使用指紋解鎖平板電腦或驗證身分,例如用來登入應用程式或核准購買交易" + "現在可使用指紋解鎖裝置或驗證身分,例如用來登入應用程式或核准購買交易" + "現在可使用指紋解鎖手機或驗證身分,例如用來登入應用程式或核准購買交易" "僅在螢幕開啟時解鎖" "您必須先開啟螢幕,才可以使用指紋解鎖,以避免意外解鎖。" "螢幕解鎖" @@ -2814,7 +2811,7 @@ "詳細記錄" "電池電量" "查看過去 24 小時的使用情況" - "查看自上次充飽電後的電池用量" + "查看上次充滿電後的使用情況" "應用程式電池用量" "詳細使用狀況" "調整電力使用" @@ -2995,25 +2992,25 @@ "電池用量" "上次充滿電後" "管理電池用量" - "自上次充飽電後使用電池的時間總長度為 ^1 • 在背景使用電池的時間長度為 ^2\n" + "總時間長度為 ^1 • 上次充滿電後在背景使用電池的時間長度為 ^2\n" "總共使用 ^1 • 背景使用 ^2\n(過去 24 小時)" "總共使用 ^1 • 背景使用 ^2\n(^3)" - "自上次充飽電後使用電池的時間總長度不到一分鐘" + "上次充滿電後使用電池的總時間長度少於一分鐘" "過去 24 小時使用電池的總時間長度少於一分鐘" "^1 這段期間內使用電池的總時間長度少於一分鐘" - "自上次充飽電後在背景使用電池的時間長度不到一分鐘" + "上次充滿電後在背景使用電池的時間長度少於一分鐘" "過去 24 小時在背景使用電池的時間長度少於一分鐘" "^1 這段期間內在背景使用電池的時間長度少於一分鐘" - "自上次充飽電後使用電池的時間總長度為 ^1" + "上次充滿電後使用電池的總時間長度為 ^1" "過去 24 小時總共使用了 ^1" "^2這段期間內使用電池的總時間長度為 ^1" - "自上次充飽電後在背景使用電池的時間長度為 ^1" + "上次充滿電後在背景使用電池的時間長度為 ^1" "過去 24 小時在背景使用電池的時間長度為 ^1" "^2 這段期間內在背景使用電池的時間長度為 ^1" - "自上次充飽電後使用電池的時間總長度為 ^1 • 在背景使用電池的時間長度不到一分鐘\n" + "總時間長度為 ^1 • 上次充滿電後在背景使用電池的時間長度\n少於一分鐘" "總共使用了 ^1 • 背景使用時間少於一分鐘\n(過去 24 小時)" "總共使用 ^1 • 背景使用時間不到一分鐘\n(^2)" - "自上次充飽電後未曾使用" + "上次充滿電後沒有使用電池" "過去 24 小時未使用電池" "其他使用者" @@ -3493,8 +3490,7 @@ "將 %1$s 從這部裝置中刪除" "上鎖畫面設定" "在上鎖畫面加入使用者" - - + "放上插座後切換至管理員使用者" "您要刪除自己嗎?" "要刪除這名使用者嗎?" "移除這個設定檔?" @@ -5676,6 +5672,9 @@ "如要使用,請先啟用「顯示裝置控制」" "雙線時鐘 (如有)" "雙線時鐘" + + + diff --git a/res/values-zh-rTW/strings.xml b/res/values-zh-rTW/strings.xml index a06c7c9e4f6..aef716518e8 100644 --- a/res/values-zh-rTW/strings.xml +++ b/res/values-zh-rTW/strings.xml @@ -590,12 +590,9 @@ "指紋新增成功" - - - - - - + "現在只要使用自己的指紋就能解鎖平板電腦或驗證身分,以便執行某些特定操作,例如登入應用程式或核准購買交易" + "現在只要使用自己的指紋就能解鎖裝置或驗證身分,以便執行某些特定操作,例如登入應用程式或核准購買交易" + "現在只要使用自己的指紋就能解鎖手機或驗證身分,以便執行某些特定操作,例如登入應用程式或核准購買交易" "螢幕亮起時才能解鎖裝置" "必須先讓螢幕亮起,才能使用指紋解鎖裝置。這麼做可降低意外解鎖的可能性。" "螢幕解鎖" @@ -3492,8 +3489,7 @@ "將 %1$s 從這個裝置中刪除" "螢幕鎖定設定" "在螢幕鎖定畫面中新增使用者" - - + "插入座架後切換成管理員使用者" "你要刪除自己嗎?" "要刪除這位使用者嗎?" "移除這個設定檔?" @@ -5675,6 +5671,9 @@ "如要使用,請先開啟「顯示裝置控制」" "顯示雙行時鐘 (如果可用的話)" "雙行時鐘" + + + diff --git a/res/values-zu/strings.xml b/res/values-zu/strings.xml index 397873106f8..776f22eb7e7 100644 --- a/res/values-zu/strings.xml +++ b/res/values-zu/strings.xml @@ -588,12 +588,9 @@ "Kubhaliswe amaphesenti angu-%d" "Iphesenti elingu-%d lokubhalisela izigxivizo zeminwe" "Izigxivizo zeminwe zingeziwe" - - - - - - + "Manje ungasebenzisa isigxivizo somunwe wakho ukuvula ithebulethi yakho noma ukuqinisekisa ukuthi nguwe, njengalapho ungena ngemvume kuma-app noma ugunyaza ukuthenga" + "Manje ungasebenzisa isigxivizo somunwe wakho ukuvula idivayisi yakho noma ukuqinisekisa ukuthi nguwe, njengalapho ungena ngemvume kuma-app noma ugunyaza ukuthenga" + "Manje ungasebenzisa isigxivizo somunwe wakho ukuvula ifoni yakho noma ukuqinisekisa ukuthi nguwe, njengalapho ungena ngemvume kuma-app noma ugunyaza ukuthenga" "Vula kuphela uma isikrini sivuliwe" "Isikrini kufanele sivulwe ngaphambi kokuthi uvule ngesigxivizo somunwe. Lokhu kwenza ukuvula ngephutha kungabi bikho kangako." "Ukuvula, Isikrini" @@ -3491,8 +3488,7 @@ "Susa i-%1$s kule divayisi" "Khiya izilungiselelo zesikrini" "Engeza abasebenzisi kusuka esikrinini sokukhiya" - - + "Gukukela kumsebenzisi ongumphathi lapho kudokhiwe" "Zisuse wena?" "Susa lo msebenzisi?" "Susa le phrofayela?" @@ -5674,6 +5670,9 @@ "Ukuze usebenzise, qala ngokuvula okuthi \"Bonisa izilawuli zedivayisi\"" "Bonisa iwashi lolayini okabili uma litholakala" "Iwashi lolayini okabili" + + + From 5cfec6757206b4bdc2493ed0858e9698095d8c22 Mon Sep 17 00:00:00 2001 From: ykhung Date: Wed, 23 Nov 2022 00:50:45 +0800 Subject: [PATCH 10/16] Add FUELGAUGE_BATTERY_SAVER_SCHEDULE for saver schedule page metric Bug: 260074438 Test: make test RunSettingsRoboTests Change-Id: Ib7e55b6638d1b10a47cbf25f5dbbb40b3f4962f2 --- .../batterysaver/BatterySaverScheduleSettings.java | 2 +- .../batterysaver/BatterySaverScheduleSettingsTest.java | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSettings.java b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSettings.java index 738229937db..0eca3a6eca3 100644 --- a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSettings.java +++ b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSettings.java @@ -167,7 +167,7 @@ public class BatterySaverScheduleSettings extends RadioButtonPickerFragment { @Override public int getMetricsCategory() { - return 0; + return SettingsEnums.FUELGAUGE_BATTERY_SAVER_SCHEDULE; } private void logPowerSaver() { diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSettingsTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSettingsTest.java index 270a6252ef4..dc9cac40bdd 100644 --- a/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSettingsTest.java +++ b/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleSettingsTest.java @@ -1,5 +1,6 @@ package com.android.settings.fuelgauge.batterysaver; +import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; @@ -82,6 +83,12 @@ public final class BatterySaverScheduleSettingsTest { verifySchedule("key_battery_saver_percentage", expectedPercentage); } + @Test + public void getMetricsCategory_returnExpectedResult() { + assertThat(mBatterySaverScheduleSettings.getMetricsCategory()) + .isEqualTo(SettingsEnums.FUELGAUGE_BATTERY_SAVER_SCHEDULE); + } + private void setSchedule(int scheduleType, int schedulePercentage) { Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.AUTOMATIC_POWER_SAVE_MODE, scheduleType); From 24f0f2c2dad085441a0507863c80e020f6ac1367 Mon Sep 17 00:00:00 2001 From: Kuan Wang Date: Fri, 18 Nov 2022 15:16:51 +0800 Subject: [PATCH 11/16] Clean up unused files for Battery Usage in SettingsGoogle, which have been moved into Settings. Test: make RunSettingsRoboTests Bug: 256123455 Change-Id: I21fe684b9b3a2a748c5d10353e68e15ddf281838 --- res/layout/battery_usage_graph.xml | 53 ------------------- res/values/strings.xml | 9 ---- .../fuelgauge/PowerUsageFeatureProvider.java | 13 ----- .../PowerUsageFeatureProviderImpl.java | 12 ----- .../fuelgauge/batteryusage/BatteryEntry.java | 3 -- 5 files changed, 90 deletions(-) delete mode 100644 res/layout/battery_usage_graph.xml diff --git a/res/layout/battery_usage_graph.xml b/res/layout/battery_usage_graph.xml deleted file mode 100644 index e79c7b94f85..00000000000 --- a/res/layout/battery_usage_graph.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - diff --git a/res/values/strings.xml b/res/values/strings.xml index 0fd961702ad..32bc6899d83 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -4582,8 +4582,6 @@ Battery What has been using the battery - - Battery usage data isn\u2019t available. %1$s - %2$s @@ -4631,8 +4629,6 @@ Screen usage since full charge - - Battery usage since full charge %1$s left (New ML est) @@ -4800,8 +4796,6 @@ Voice calls - - Used for ^1 Screen usage ^1 @@ -4870,9 +4864,6 @@ Other users - - Battery left estimate is based on your device usage - Estimated time left diff --git a/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java b/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java index 7a33a6231b2..2faacb749f8 100644 --- a/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java +++ b/src/com/android/settings/fuelgauge/PowerUsageFeatureProvider.java @@ -20,10 +20,8 @@ import android.content.Context; import android.content.Intent; import android.util.SparseIntArray; -import com.android.settings.fuelgauge.batteryusage.BatteryHistEntry; import com.android.settingslib.fuelgauge.Estimate; -import java.util.Map; import java.util.Set; /** @@ -103,12 +101,6 @@ public interface PowerUsageFeatureProvider { */ String getOldEstimateDebugString(String timeRemaining); - /** - * Returns the string to show in the advanced usage battery page when enhanced estimates are - * enabled. This string notifies users that the estimate is using enhanced prediction. - */ - String getAdvancedUsageScreenInfoString(); - /** * Returns a signal to indicate if the device will need to warn the user they may not make it * to their next charging time. @@ -143,11 +135,6 @@ public interface PowerUsageFeatureProvider { */ Intent getResumeChargeIntent(); - /** - * Returns battery history data with corresponding timestamp key. - */ - Map> getBatteryHistory(Context context); - /** * Returns {@link Set} for hidding applications background usage time. */ diff --git a/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java b/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java index 3fe4275fa3c..ff1edecac8c 100644 --- a/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java +++ b/src/com/android/settings/fuelgauge/PowerUsageFeatureProviderImpl.java @@ -24,10 +24,8 @@ import android.util.ArraySet; import android.util.SparseIntArray; import com.android.internal.util.ArrayUtils; -import com.android.settings.fuelgauge.batteryusage.BatteryHistEntry; import com.android.settingslib.fuelgauge.Estimate; -import java.util.Map; import java.util.Set; /** Implementation of {@code PowerUsageFeatureProvider} */ @@ -122,11 +120,6 @@ public class PowerUsageFeatureProviderImpl implements PowerUsageFeatureProvider return null; } - @Override - public String getAdvancedUsageScreenInfoString() { - return null; - } - @Override public boolean getEarlyWarningSignal(Context context, String id) { return false; @@ -158,11 +151,6 @@ public class PowerUsageFeatureProviderImpl implements PowerUsageFeatureProvider return false; } - @Override - public Map> getBatteryHistory(Context context) { - return null; - } - @Override public Set getHideBackgroundUsageTimeSet(Context context) { return new ArraySet<>(); diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryEntry.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryEntry.java index af67610d2ec..cb870f4d174 100644 --- a/src/com/android/settings/fuelgauge/batteryusage/BatteryEntry.java +++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryEntry.java @@ -70,9 +70,6 @@ public class BatteryEntry { } } - public static final int MSG_UPDATE_NAME_ICON = 1; - public static final int MSG_REPORT_FULLY_DRAWN = 2; - private static final String TAG = "BatteryEntry"; private static final String PACKAGE_SYSTEM = "android"; From b189b04c61b61da69cd70d4c5008f21146be66e7 Mon Sep 17 00:00:00 2001 From: Sunny Shao Date: Wed, 23 Nov 2022 10:35:47 +0800 Subject: [PATCH 12/16] Add page id enum of dialog under Open by default page - Add SettingsEnums.PROGRESS_DIALOG - Add SettingsEnums.SUPPORTED_LINKS_DIALOG Fixes: 260073786 Fixes: 260073725 Test: compilation Change-Id: I060025c72a4c03dde1f9be5fa3215fceb98779cd --- .../applications/intentpicker/ProgressDialogFragment.java | 3 ++- .../intentpicker/SupportedLinksDialogFragment.java | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/com/android/settings/applications/intentpicker/ProgressDialogFragment.java b/src/com/android/settings/applications/intentpicker/ProgressDialogFragment.java index c8f4c0b789d..6c5974558ad 100644 --- a/src/com/android/settings/applications/intentpicker/ProgressDialogFragment.java +++ b/src/com/android/settings/applications/intentpicker/ProgressDialogFragment.java @@ -19,6 +19,7 @@ package com.android.settings.applications.intentpicker; import static android.content.pm.verify.domain.DomainVerificationUserState.DOMAIN_STATE_NONE; import android.app.Dialog; +import android.app.settings.SettingsEnums; import android.content.Context; import android.content.DialogInterface; import android.content.pm.verify.domain.DomainOwner; @@ -113,7 +114,7 @@ public class ProgressDialogFragment extends InstrumentedDialogFragment { @Override public int getMetricsCategory() { - return 0; + return SettingsEnums.PROGRESS_DIALOG; } /** diff --git a/src/com/android/settings/applications/intentpicker/SupportedLinksDialogFragment.java b/src/com/android/settings/applications/intentpicker/SupportedLinksDialogFragment.java index dd5b746d75f..e67fa049155 100644 --- a/src/com/android/settings/applications/intentpicker/SupportedLinksDialogFragment.java +++ b/src/com/android/settings/applications/intentpicker/SupportedLinksDialogFragment.java @@ -17,6 +17,7 @@ package com.android.settings.applications.intentpicker; import android.app.Dialog; +import android.app.settings.SettingsEnums; import android.content.Context; import android.content.pm.PackageManager; import android.content.pm.verify.domain.DomainVerificationManager; @@ -73,7 +74,7 @@ public class SupportedLinksDialogFragment extends InstrumentedDialogFragment { @Override public int getMetricsCategory() { - return 0; + return SettingsEnums.SUPPORTED_LINKS_DIALOG; } /** Display the dialog. */ From 08d0f0439c9de83aeb64c7ff947fe9179f701401 Mon Sep 17 00:00:00 2001 From: Arc Wang Date: Wed, 23 Nov 2022 14:19:13 +0800 Subject: [PATCH 13/16] Add page id enum for storage settings - Add SettingsEnums.PRIVATE_VOLUME_FORGET - Add SettingsEnums.PRIVATE_VOLUME_FORMAT - Add SettingsEnums.PRIVATE_VOLUME_UNMOUNT - Add SettingsEnums.PUBLIC_VOLUME_SETTINGS Bug: 260051818 Test: compilation Change-Id: If6188eb1de1e17702007d9d87c52b811972d5f7d --- src/com/android/settings/deviceinfo/PrivateVolumeForget.java | 2 +- src/com/android/settings/deviceinfo/PrivateVolumeFormat.java | 2 +- src/com/android/settings/deviceinfo/PrivateVolumeUnmount.java | 2 +- src/com/android/settings/deviceinfo/PublicVolumeSettings.java | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/com/android/settings/deviceinfo/PrivateVolumeForget.java b/src/com/android/settings/deviceinfo/PrivateVolumeForget.java index bd0772c668d..759c7d80997 100644 --- a/src/com/android/settings/deviceinfo/PrivateVolumeForget.java +++ b/src/com/android/settings/deviceinfo/PrivateVolumeForget.java @@ -48,7 +48,7 @@ public class PrivateVolumeForget extends InstrumentedFragment { @Override public int getMetricsCategory() { - return SettingsEnums.DEVICEINFO_STORAGE; + return SettingsEnums.PRIVATE_VOLUME_FORGET; } @Override diff --git a/src/com/android/settings/deviceinfo/PrivateVolumeFormat.java b/src/com/android/settings/deviceinfo/PrivateVolumeFormat.java index dadff3c1dbb..3820eb65334 100644 --- a/src/com/android/settings/deviceinfo/PrivateVolumeFormat.java +++ b/src/com/android/settings/deviceinfo/PrivateVolumeFormat.java @@ -44,7 +44,7 @@ public class PrivateVolumeFormat extends InstrumentedFragment { @Override public int getMetricsCategory() { - return SettingsEnums.DEVICEINFO_STORAGE; + return SettingsEnums.PRIVATE_VOLUME_FORMAT; } @Override diff --git a/src/com/android/settings/deviceinfo/PrivateVolumeUnmount.java b/src/com/android/settings/deviceinfo/PrivateVolumeUnmount.java index 738c3ca520a..dccb12dd4ec 100644 --- a/src/com/android/settings/deviceinfo/PrivateVolumeUnmount.java +++ b/src/com/android/settings/deviceinfo/PrivateVolumeUnmount.java @@ -40,7 +40,7 @@ public class PrivateVolumeUnmount extends InstrumentedFragment { @Override public int getMetricsCategory() { - return SettingsEnums.DEVICEINFO_STORAGE; + return SettingsEnums.PRIVATE_VOLUME_UNMOUNT; } @Override diff --git a/src/com/android/settings/deviceinfo/PublicVolumeSettings.java b/src/com/android/settings/deviceinfo/PublicVolumeSettings.java index d43b2541db7..4fd63af281a 100644 --- a/src/com/android/settings/deviceinfo/PublicVolumeSettings.java +++ b/src/com/android/settings/deviceinfo/PublicVolumeSettings.java @@ -95,7 +95,7 @@ public class PublicVolumeSettings extends SettingsPreferenceFragment { @Override public int getMetricsCategory() { - return SettingsEnums.DEVICEINFO_STORAGE; + return SettingsEnums.PUBLIC_VOLUME_SETTINGS; } @Override From f6d712c7b7f70c191c946a3ff52bb84608446406 Mon Sep 17 00:00:00 2001 From: Arc Wang Date: Wed, 23 Nov 2022 14:44:53 +0800 Subject: [PATCH 14/16] Remove isSticky true for SplitPlaceholderRule SplitPlaceholderRule#isSticky determines whether the placeholder will show on top in a smaller window size after it first appeared in a split with sufficient minimum width. This change will show Settings homepage while users rotate device to portrait mode and show Settings 1-pane UI. Bug: 256115335 Test: manual visual 1. Set font size and display size to large. 2. Launch Setting app in landscape and rotate to portrait. Change-Id: Ie955f8b8db3bbe42dba6300608774582ef150590 --- .../activityembedding/ActivityEmbeddingRulesController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/com/android/settings/activityembedding/ActivityEmbeddingRulesController.java b/src/com/android/settings/activityembedding/ActivityEmbeddingRulesController.java index ad0d4eab03f..03bff7bfa30 100644 --- a/src/com/android/settings/activityembedding/ActivityEmbeddingRulesController.java +++ b/src/com/android/settings/activityembedding/ActivityEmbeddingRulesController.java @@ -207,7 +207,7 @@ public class ActivityEmbeddingRulesController { final SplitPlaceholderRule placeholderRule = new SplitPlaceholderRule( activityFilters, intent, - true /* stickyPlaceholder */, + false /* stickyPlaceholder */, SplitRule.FINISH_ADJACENT, ActivityEmbeddingUtils.getMinCurrentScreenSplitWidthPx(mContext), ActivityEmbeddingUtils.getMinSmallestScreenSplitWidthPx(mContext), From 505be79cc5d9d530dd5c6f49ff468469c8c27ab9 Mon Sep 17 00:00:00 2001 From: Milton Wu Date: Wed, 23 Nov 2022 13:33:23 +0800 Subject: [PATCH 15/16] Fix FingerprintEnrollIntroFragment buttons 1. Fix FingerprintEnrollIntroFragment button status not sync after rotation. 2. Finetune code orders in FingerprintEnrollmentActivity.onCreate(), 3. Refine some API names and java doc Bug: 260205364 Test: atest AutoCredentialViewModelTest FingerprintEnrollIntroViewModelTest Test: Manually test rotation with different display size Change-Id: Ib992e10a1c90e3bbac6cf73114df4e96b5ab0a03 --- .../view/FingerprintEnrollIntroFragment.java | 51 ++++-- .../view/FingerprintEnrollmentActivity.java | 37 +++-- .../ui/viewmodel/AutoCredentialViewModel.java | 34 ++-- .../FingerprintEnrollIntroViewModel.java | 6 +- .../AutoCredentialViewModelTest.java | 154 ++++++++---------- .../FingerprintEnrollIntroViewModelTest.java | 8 +- 6 files changed, 150 insertions(+), 140 deletions(-) diff --git a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollIntroFragment.java b/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollIntroFragment.java index 14d859dbffc..ecec36f50de 100644 --- a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollIntroFragment.java +++ b/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollIntroFragment.java @@ -44,6 +44,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.StringRes; import androidx.fragment.app.Fragment; +import androidx.lifecycle.LiveData; import androidx.lifecycle.ViewModelProvider; import com.android.settings.R; @@ -120,15 +121,6 @@ public class FingerprintEnrollIntroFragment extends Fragment { footerTitle2.setText( R.string.security_settings_fingerprint_enroll_introduction_footer_title_2); - return mView; - } - - @Override - public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - - final Context context = view.getContext(); - final TextView footerLink = mView.findViewById(R.id.footer_learn_more); footerLink.setMovementMethod(LinkMovementMethod.getInstance()); final String footerLinkStr = getContext().getString( @@ -139,18 +131,28 @@ public class FingerprintEnrollIntroFragment extends Fragment { // footer buttons mPrimaryFooterButton = new FooterButton.Builder(context) .setText(R.string.security_settings_fingerprint_enroll_introduction_agree) - .setListener(mViewModel::onNextButtonClick) .setButtonType(FooterButton.ButtonType.OPT_IN) .setTheme(R.style.SudGlifButton_Primary) .build(); mSecondaryFooterButton = new FooterButton.Builder(context) - .setListener(mViewModel::onSkipOrCancelButtonClick) .setButtonType(FooterButton.ButtonType.NEXT) .setTheme(R.style.SudGlifButton_Primary) .build(); getFooterBarMixin().setPrimaryButton(mPrimaryFooterButton); getFooterBarMixin().setSecondaryButton(mSecondaryFooterButton, true /* usePrimaryStyle */); + return mView; + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + final Context context = view.getContext(); + + mPrimaryFooterButton.setOnClickListener(mViewModel::onNextButtonClick); + mSecondaryFooterButton.setOnClickListener(mViewModel::onSkipOrCancelButtonClick); + if (mViewModel.canAssumeUdfps()) { mFooterMessage6.setVisibility(View.VISIBLE); mIconShield.setVisibility(View.VISIBLE); @@ -158,7 +160,7 @@ public class FingerprintEnrollIntroFragment extends Fragment { mFooterMessage6.setVisibility(View.GONE); mIconShield.setVisibility(View.GONE); } - mSecondaryFooterButton.setText(getContext(), + mSecondaryFooterButton.setText(context, mViewModel.getEnrollmentRequest().isAfterSuwOrSuwSuggestedAction() ? R.string.security_settings_fingerprint_enroll_introduction_cancel : R.string.security_settings_fingerprint_enroll_introduction_no_thanks); @@ -174,18 +176,31 @@ public class FingerprintEnrollIntroFragment extends Fragment { setHeaderText(getActivity(), R.string.security_settings_fingerprint_enroll_introduction_title); } + observePageStatusLiveDataIfNeed(); + } - mViewModel.getPageStatusLiveData().observe(this, this::updateFooterButtons); + private void observePageStatusLiveDataIfNeed() { + final LiveData statusLiveData = + mViewModel.getPageStatusLiveData(); + final FingerprintEnrollIntroStatus status = statusLiveData.getValue(); + if (status != null && status.hasScrollToBottom()) { + // Do not requireScrollWithButton() again when "I agree" or "Done" button is visible, + // because if we requireScrollWithButton() again, it will become "More" after scroll-up. + return; + } final RequireScrollMixin requireScrollMixin = getLayout() .getMixin(RequireScrollMixin.class); requireScrollMixin.requireScrollWithButton(getActivity(), mPrimaryFooterButton, getMoreButtonTextRes(), mViewModel::onNextButtonClick); - requireScrollMixin.setOnRequireScrollStateChangedListener(scrollNeeded -> { - if (!scrollNeeded) { - mViewModel.setHasScrolledToBottom(); - } - }); + + // Always set true to setHasScrolledToBottom() before registering listener through + // setOnRequireScrollStateChangedListener(), because listener will not be called if first + // scrollNeeded is true + mViewModel.setHasScrolledToBottom(true); + requireScrollMixin.setOnRequireScrollStateChangedListener( + scrollNeeded -> mViewModel.setHasScrolledToBottom(!scrollNeeded)); + statusLiveData.observe(this, this::updateFooterButtons); } @Override diff --git a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollmentActivity.java b/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollmentActivity.java index 991aeba74d2..1f67100afcf 100644 --- a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollmentActivity.java +++ b/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollmentActivity.java @@ -95,14 +95,9 @@ public class FingerprintEnrollmentActivity extends FragmentActivity { mViewModel = viewModelProvider.get(FingerprintEnrollmentViewModel.class); mViewModel.setRequest(new EnrollmentRequest(getIntent(), getApplicationContext())); mViewModel.setSavedInstanceState(savedInstanceState); - getLifecycle().addObserver(mViewModel); mAutoCredentialViewModel = viewModelProvider.get(AutoCredentialViewModel.class); mAutoCredentialViewModel.setCredentialModel(savedInstanceState, getIntent()); - mAutoCredentialViewModel.getGenerateChallengeFailLiveData().observe(this, - this::onGenerateChallengeFail); - - mViewModel.getSetResultLiveData().observe(this, this::onSetActivityResult); checkCredential(); // Theme @@ -113,16 +108,10 @@ public class FingerprintEnrollmentActivity extends FragmentActivity { // fragment setContentView(R.layout.biometric_enrollment_container); - final FingerprintEnrollIntroViewModel fingerprintEnrollIntroViewModel = + final FingerprintEnrollIntroViewModel introViewModel = viewModelProvider.get(FingerprintEnrollIntroViewModel.class); - fingerprintEnrollIntroViewModel.setEnrollmentRequest(mViewModel.getRequest()); - fingerprintEnrollIntroViewModel.setUserId(mAutoCredentialViewModel.getUserId()); - - // Clear ActionLiveData in FragmentViewModel to prevent getting previous action when - // recreate - fingerprintEnrollIntroViewModel.clearActionLiveData(); - fingerprintEnrollIntroViewModel.getActionLiveData().observe( - this, this::observeIntroAction); + introViewModel.setEnrollmentRequest(mViewModel.getRequest()); + introViewModel.setUserId(mAutoCredentialViewModel.getUserId()); if (savedInstanceState == null) { final String tag = "FingerprintEnrollIntroFragment"; getSupportFragmentManager().beginTransaction() @@ -131,9 +120,21 @@ public class FingerprintEnrollmentActivity extends FragmentActivity { tag) .commit(); } + + // observe LiveData + getLifecycle().addObserver(mViewModel); + mViewModel.getSetResultLiveData().observe(this, this::onSetActivityResult); + + mAutoCredentialViewModel.getGenerateChallengeFailedLiveData().observe(this, + this::onGenerateChallengeFailed); + + // Clear ActionLiveData in FragmentViewModel to prevent getting previous action during + // recreate, like press 'I agree' then press 'back' in FingerprintEnrollFindSensor activity. + introViewModel.clearActionLiveData(); + introViewModel.getActionLiveData().observe(this, this::observeIntroAction); } - private void onGenerateChallengeFail(@NonNull Boolean isFail) { + private void onGenerateChallengeFailed(@NonNull Boolean ignoredBoolean) { onSetActivityResult(new ActivityResult(RESULT_CANCELED, null)); } @@ -148,7 +149,7 @@ public class FingerprintEnrollmentActivity extends FragmentActivity { private void checkCredential() { switch (mAutoCredentialViewModel.checkCredential()) { case CREDENTIAL_FAIL_NEED_TO_CHOOSE_LOCK: { - final Intent intent = mAutoCredentialViewModel.getChooseLockIntent(this, + final Intent intent = mAutoCredentialViewModel.createChooseLockIntent(this, mViewModel.getRequest().isSuw(), mViewModel.getRequest().getSuwExtras()); if (!mViewModel.isWaitingActivityResult().compareAndSet(false, true)) { Log.w(TAG, "chooseLock, fail to set isWaiting flag to true"); @@ -157,7 +158,7 @@ public class FingerprintEnrollmentActivity extends FragmentActivity { return; } case CREDENTIAL_FAIL_NEED_TO_CONFIRM_LOCK: { - final boolean launched = mAutoCredentialViewModel.getConfirmLockLauncher( + final boolean launched = mAutoCredentialViewModel.createConfirmLockLauncher( this, LAUNCH_CONFIRM_LOCK_ACTIVITY, getString(R.string.security_settings_fingerprint_preference_title) @@ -215,7 +216,7 @@ public class FingerprintEnrollmentActivity extends FragmentActivity { final Intent intent = new Intent(this, isSuw ? SetupFingerprintEnrollFindSensor.class : FingerprintEnrollFindSensor.class); - intent.putExtras(mAutoCredentialViewModel.getCredentialIntentExtra()); + intent.putExtras(mAutoCredentialViewModel.createCredentialIntentExtra()); intent.putExtras(mViewModel.getNextActivityBaseIntentExtras()); mNextActivityLauncher.launch(intent); } diff --git a/src/com/android/settings/biometrics2/ui/viewmodel/AutoCredentialViewModel.java b/src/com/android/settings/biometrics2/ui/viewmodel/AutoCredentialViewModel.java index a443e69a855..3b7a436fe5c 100644 --- a/src/com/android/settings/biometrics2/ui/viewmodel/AutoCredentialViewModel.java +++ b/src/com/android/settings/biometrics2/ui/viewmodel/AutoCredentialViewModel.java @@ -68,7 +68,7 @@ public class AutoCredentialViewModel extends AndroidViewModel { private static final boolean DEBUG = false; /** - * Valid credential, activity doesn't need to do anything. + * Valid credential, activity does nothing. */ public static final int CREDENTIAL_VALID = 0; @@ -170,7 +170,7 @@ public class AutoCredentialViewModel extends AndroidViewModel { @NonNull private final LockPatternUtils mLockPatternUtils; @NonNull private final ChallengeGenerator mChallengeGenerator; private CredentialModel mCredentialModel = null; - @NonNull private final MutableLiveData mGenerateChallengeFailLiveData = + @NonNull private final MutableLiveData mGenerateChallengeFailedLiveData = new MutableLiveData<>(); public AutoCredentialViewModel( @@ -186,11 +186,13 @@ public class AutoCredentialViewModel extends AndroidViewModel { * Set CredentialModel, the source is coming from savedInstanceState or activity intent */ public void setCredentialModel(@Nullable Bundle savedInstanceState, @NonNull Intent intent) { - mCredentialModel = new CredentialModel( - savedInstanceState != null - ? savedInstanceState.getBundle(KEY_CREDENTIAL_MODEL) - : intent.getExtras(), - SystemClock.elapsedRealtimeClock()); + final Bundle bundle; + if (savedInstanceState != null) { + bundle = savedInstanceState.getBundle(KEY_CREDENTIAL_MODEL); + } else { + bundle = intent.getExtras(); + } + mCredentialModel = new CredentialModel(bundle, SystemClock.elapsedRealtimeClock()); if (DEBUG) { Log.d(TAG, "setCredentialModel " + mCredentialModel + ", savedInstanceState exist:" @@ -206,8 +208,8 @@ public class AutoCredentialViewModel extends AndroidViewModel { } @NonNull - public LiveData getGenerateChallengeFailLiveData() { - return mGenerateChallengeFailLiveData; + public LiveData getGenerateChallengeFailedLiveData() { + return mGenerateChallengeFailedLiveData; } /** @@ -238,7 +240,7 @@ public class AutoCredentialViewModel extends AndroidViewModel { mCredentialModel.setToken(newToken); } catch (IllegalStateException e) { Log.e(TAG, "generateChallenge, IllegalStateException", e); - mGenerateChallengeFailLiveData.postValue(true); + mGenerateChallengeFailedLiveData.postValue(true); return; } @@ -252,7 +254,7 @@ public class AutoCredentialViewModel extends AndroidViewModel { // Check credential again if (!isValidCredential()) { Log.w(TAG, "generateChallenge, invalid Credential"); - mGenerateChallengeFailLiveData.postValue(true); + mGenerateChallengeFailedLiveData.postValue(true); } }); mChallengeGenerator.generateChallenge(getUserId()); @@ -312,7 +314,7 @@ public class AutoCredentialViewModel extends AndroidViewModel { * Get Credential intent extra which will be used to launch next activity. */ @NonNull - public Bundle getCredentialIntentExtra() { + public Bundle createCredentialIntentExtra() { final Bundle retBundle = new Bundle(); final long gkPwHandle = mCredentialModel.getGkPwHandle(); if (CredentialModel.isValidGkPwHandle(gkPwHandle)) { @@ -332,10 +334,10 @@ public class AutoCredentialViewModel extends AndroidViewModel { } /** - * Get Intent for choosing lock + * Create Intent for choosing lock */ @NonNull - public Intent getChooseLockIntent(@NonNull Context context, boolean isSuw, + public Intent createChooseLockIntent(@NonNull Context context, boolean isSuw, @NonNull Bundle suwExtras) { final Intent intent = BiometricUtils.getChooseLockIntent(context, isSuw, suwExtras); @@ -352,10 +354,10 @@ public class AutoCredentialViewModel extends AndroidViewModel { } /** - * Get ConfirmLockLauncher + * Create ConfirmLockLauncher */ @NonNull - public ChooseLockSettingsHelper getConfirmLockLauncher(@NonNull Activity activity, + public ChooseLockSettingsHelper createConfirmLockLauncher(@NonNull Activity activity, int requestCode, @NonNull String title) { final ChooseLockSettingsHelper.Builder builder = new ChooseLockSettingsHelper.Builder(activity); diff --git a/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollIntroViewModel.java b/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollIntroViewModel.java index 3274eb29565..72611a7c791 100644 --- a/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollIntroViewModel.java +++ b/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollIntroViewModel.java @@ -145,7 +145,7 @@ public class FingerprintEnrollIntroViewModel extends AndroidViewModel } /** - * Clear user's action live data (like clicking Agree, Skip, or Done) + * Clear user's action live data */ public void clearActionLiveData() { mActionLiveData.setValue(null); @@ -168,8 +168,8 @@ public class FingerprintEnrollIntroViewModel extends AndroidViewModel /** * Update onboarding intro page has scrolled to bottom */ - public void setHasScrolledToBottom() { - mHasScrolledToBottomLiveData.postValue(true); + public void setHasScrolledToBottom(boolean value) { + mHasScrolledToBottomLiveData.postValue(value); } /** diff --git a/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/AutoCredentialViewModelTest.java b/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/AutoCredentialViewModelTest.java index a11650ebe84..3abbca6cb68 100644 --- a/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/AutoCredentialViewModelTest.java +++ b/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/AutoCredentialViewModelTest.java @@ -26,6 +26,8 @@ import static com.android.settings.biometrics.BiometricEnrollBase.EXTRA_KEY_SENS import static com.android.settings.biometrics2.ui.model.CredentialModel.INVALID_CHALLENGE; import static com.android.settings.biometrics2.ui.model.CredentialModel.INVALID_GK_PW_HANDLE; import static com.android.settings.biometrics2.ui.model.CredentialModel.INVALID_SENSOR_ID; +import static com.android.settings.biometrics2.ui.model.CredentialModel.isValidGkPwHandle; +import static com.android.settings.biometrics2.ui.model.CredentialModel.isValidToken; import static com.android.settings.biometrics2.ui.model.CredentialModelTest.newCredentialModelIntentExtras; import static com.android.settings.biometrics2.ui.model.CredentialModelTest.newGkPwHandleCredentialIntentExtras; import static com.android.settings.biometrics2.ui.model.CredentialModelTest.newInvalidChallengeCredentialIntentExtras; @@ -58,9 +60,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4; import com.android.internal.widget.LockPatternUtils; import com.android.internal.widget.VerifyCredentialResponse; -import com.android.settings.biometrics2.ui.model.CredentialModel; import com.android.settings.password.ChooseLockPattern; -import com.android.settings.password.ChooseLockSettingsHelper; import com.android.settings.testutils.InstantTaskExecutorRule; import org.junit.Before; @@ -79,12 +79,12 @@ public class AutoCredentialViewModelTest { @Mock private LockPatternUtils mLockPatternUtils; private TestChallengeGenerator mChallengeGenerator = null; - private AutoCredentialViewModel mAutoCredentialViewModel; + private AutoCredentialViewModel mViewModel; @Before public void setUp() { mChallengeGenerator = new TestChallengeGenerator(); - mAutoCredentialViewModel = new AutoCredentialViewModel( + mViewModel = new AutoCredentialViewModel( ApplicationProvider.getApplicationContext(), mLockPatternUtils, mChallengeGenerator); @@ -99,22 +99,21 @@ public class AutoCredentialViewModelTest { } @Test - public void testGetCredentialIntentExtra_sameResultFromSavedInstanceOrIntent() { + public void testSetCredentialModel_sameResultFromSavedInstanceOrIntent() { final Bundle extras = newCredentialModelIntentExtras(12, 33, 1, new byte[] { 2, 3 }, 3L); - AutoCredentialViewModel autoCredentialViewModel2 = new AutoCredentialViewModel( + AutoCredentialViewModel viewModel2 = new AutoCredentialViewModel( ApplicationProvider.getApplicationContext(), mLockPatternUtils, mChallengeGenerator); - mAutoCredentialViewModel.setCredentialModel(null, - new Intent().putExtras(extras)); + mViewModel.setCredentialModel(null, new Intent().putExtras(extras)); final Bundle savedInstance = new Bundle(); savedInstance.putBundle(KEY_CREDENTIAL_MODEL, extras); - autoCredentialViewModel2.setCredentialModel(savedInstance, new Intent()); + viewModel2.setCredentialModel(savedInstance, new Intent()); - final Bundle bundle1 = mAutoCredentialViewModel.getCredentialIntentExtra(); - final Bundle bundle2 = autoCredentialViewModel2.getCredentialIntentExtra(); + final Bundle bundle1 = mViewModel.createCredentialIntentExtra(); + final Bundle bundle2 = viewModel2.createCredentialIntentExtra(); assertThat(bundle1.getLong(EXTRA_KEY_GK_PW_HANDLE)) .isEqualTo(bundle2.getLong(EXTRA_KEY_GK_PW_HANDLE)); assertThat(bundle1.getLong(Intent.EXTRA_USER_ID)) @@ -134,23 +133,22 @@ public class AutoCredentialViewModelTest { } @Test - public void testGetCredentialIntentExtra_sameResultFromSavedInstanceOrIntent_invalidValues() { + public void testSetCredentialModel_sameResultFromSavedInstanceOrIntent_invalidValues() { final Bundle extras = newCredentialModelIntentExtras(UserHandle.USER_NULL, INVALID_CHALLENGE, INVALID_SENSOR_ID, null, INVALID_GK_PW_HANDLE); - AutoCredentialViewModel autoCredentialViewModel2 = new AutoCredentialViewModel( + AutoCredentialViewModel viewModel2 = new AutoCredentialViewModel( ApplicationProvider.getApplicationContext(), mLockPatternUtils, mChallengeGenerator); - mAutoCredentialViewModel.setCredentialModel(null, - new Intent().putExtras(extras)); + mViewModel.setCredentialModel(null, new Intent().putExtras(extras)); final Bundle savedInstance = new Bundle(); savedInstance.putBundle(KEY_CREDENTIAL_MODEL, extras); - autoCredentialViewModel2.setCredentialModel(savedInstance, new Intent()); + viewModel2.setCredentialModel(savedInstance, new Intent()); - final Bundle bundle1 = mAutoCredentialViewModel.getCredentialIntentExtra(); - final Bundle bundle2 = autoCredentialViewModel2.getCredentialIntentExtra(); + final Bundle bundle1 = mViewModel.createCredentialIntentExtra(); + final Bundle bundle2 = viewModel2.createCredentialIntentExtra(); assertThat(bundle1.containsKey(EXTRA_KEY_GK_PW_HANDLE)).isFalse(); assertThat(bundle2.containsKey(EXTRA_KEY_GK_PW_HANDLE)).isFalse(); assertThat(bundle1.containsKey(EXTRA_KEY_CHALLENGE_TOKEN)).isFalse(); @@ -164,83 +162,83 @@ public class AutoCredentialViewModelTest { @Test public void testCheckCredential_validCredentialCase() { final int userId = 99; - mAutoCredentialViewModel.setCredentialModel(null, + mViewModel.setCredentialModel(null, new Intent().putExtras(newValidTokenCredentialIntentExtras(userId))); when(mLockPatternUtils.getActivePasswordQuality(userId)).thenReturn( PASSWORD_QUALITY_SOMETHING); // Run credential check - @CredentialAction final int action = mAutoCredentialViewModel.checkCredential(); + @CredentialAction final int action = mViewModel.checkCredential(); assertThat(action).isEqualTo(CREDENTIAL_VALID); - assertThat(mAutoCredentialViewModel.getGenerateChallengeFailLiveData().getValue()).isNull(); + assertThat(mViewModel.getGenerateChallengeFailedLiveData().getValue()).isNull(); } @Test public void testCheckCredential_needToChooseLock() { final int userId = 100; - mAutoCredentialViewModel.setCredentialModel(null, + mViewModel.setCredentialModel(null, new Intent().putExtras(newInvalidChallengeCredentialIntentExtras(userId))); when(mLockPatternUtils.getActivePasswordQuality(userId)).thenReturn( PASSWORD_QUALITY_UNSPECIFIED); // Run credential check - @CredentialAction final int action = mAutoCredentialViewModel.checkCredential(); + @CredentialAction final int action = mViewModel.checkCredential(); assertThat(action).isEqualTo(CREDENTIAL_FAIL_NEED_TO_CHOOSE_LOCK); - assertThat(mAutoCredentialViewModel.getGenerateChallengeFailLiveData().getValue()).isNull(); + assertThat(mViewModel.getGenerateChallengeFailedLiveData().getValue()).isNull(); } @Test public void testCheckCredential_needToConfirmLockFoSomething() { final int userId = 101; - mAutoCredentialViewModel.setCredentialModel(null, + mViewModel.setCredentialModel(null, new Intent().putExtras(newInvalidChallengeCredentialIntentExtras(userId))); when(mLockPatternUtils.getActivePasswordQuality(userId)).thenReturn( PASSWORD_QUALITY_SOMETHING); // Run credential check - @CredentialAction final int action = mAutoCredentialViewModel.checkCredential(); + @CredentialAction final int action = mViewModel.checkCredential(); assertThat(action).isEqualTo(CREDENTIAL_FAIL_NEED_TO_CONFIRM_LOCK); - assertThat(mAutoCredentialViewModel.getGenerateChallengeFailLiveData().getValue()).isNull(); + assertThat(mViewModel.getGenerateChallengeFailedLiveData().getValue()).isNull(); } @Test public void testCheckCredential_needToConfirmLockForNumeric() { final int userId = 102; - mAutoCredentialViewModel.setCredentialModel(null, + mViewModel.setCredentialModel(null, new Intent().putExtras(newInvalidChallengeCredentialIntentExtras(userId))); when(mLockPatternUtils.getActivePasswordQuality(userId)).thenReturn( PASSWORD_QUALITY_NUMERIC); // Run credential check - @CredentialAction final int action = mAutoCredentialViewModel.checkCredential(); + @CredentialAction final int action = mViewModel.checkCredential(); assertThat(action).isEqualTo(CREDENTIAL_FAIL_NEED_TO_CONFIRM_LOCK); - assertThat(mAutoCredentialViewModel.getGenerateChallengeFailLiveData().getValue()).isNull(); + assertThat(mViewModel.getGenerateChallengeFailedLiveData().getValue()).isNull(); } @Test public void testCheckCredential_needToConfirmLockForAlphabetic() { final int userId = 103; - mAutoCredentialViewModel.setCredentialModel(null, + mViewModel.setCredentialModel(null, new Intent().putExtras(newInvalidChallengeCredentialIntentExtras(userId))); when(mLockPatternUtils.getActivePasswordQuality(userId)).thenReturn( PASSWORD_QUALITY_ALPHABETIC); // Run credential check - @CredentialAction final int action = mAutoCredentialViewModel.checkCredential(); + @CredentialAction final int action = mViewModel.checkCredential(); assertThat(action).isEqualTo(CREDENTIAL_FAIL_NEED_TO_CONFIRM_LOCK); - assertThat(mAutoCredentialViewModel.getGenerateChallengeFailLiveData().getValue()).isNull(); + assertThat(mViewModel.getGenerateChallengeFailedLiveData().getValue()).isNull(); } @Test public void testCheckCredential_generateChallenge() { final int userId = 104; final long gkPwHandle = 1111L; - mAutoCredentialViewModel.setCredentialModel(null, + mViewModel.setCredentialModel(null, new Intent().putExtras(newGkPwHandleCredentialIntentExtras(userId, gkPwHandle))); when(mLockPatternUtils.getActivePasswordQuality(userId)).thenReturn( PASSWORD_QUALITY_SOMETHING); @@ -252,17 +250,15 @@ public class AutoCredentialViewModelTest { .thenReturn(newGoodCredential(gkPwHandle, new byte[] { 1 })); // Run credential check - @CredentialAction final int action = mAutoCredentialViewModel.checkCredential(); + @CredentialAction final int action = mViewModel.checkCredential(); assertThat(action).isEqualTo(CREDENTIAL_IS_GENERATING_CHALLENGE); - assertThat(mAutoCredentialViewModel.getGenerateChallengeFailLiveData().getValue()).isNull(); - final Bundle extras = mAutoCredentialViewModel.getCredentialIntentExtra(); + assertThat(mViewModel.getGenerateChallengeFailedLiveData().getValue()).isNull(); + final Bundle extras = mViewModel.createCredentialIntentExtra(); assertThat(extras.getInt(EXTRA_KEY_SENSOR_ID)).isEqualTo(newSensorId); assertThat(extras.getLong(EXTRA_KEY_CHALLENGE)).isEqualTo(newChallenge); - assertThat(CredentialModel.isValidToken(extras.getByteArray(EXTRA_KEY_CHALLENGE_TOKEN))) - .isTrue(); - assertThat(CredentialModel.isValidGkPwHandle(extras.getLong(EXTRA_KEY_GK_PW_HANDLE))) - .isFalse(); + assertThat(isValidToken(extras.getByteArray(EXTRA_KEY_CHALLENGE_TOKEN))).isTrue(); + assertThat(isValidGkPwHandle(extras.getLong(EXTRA_KEY_GK_PW_HANDLE))).isFalse(); assertThat(mChallengeGenerator.mCallbackRunCount).isEqualTo(1); } @@ -270,7 +266,7 @@ public class AutoCredentialViewModelTest { public void testCheckCredential_generateChallengeFail() { final int userId = 104; final long gkPwHandle = 1111L; - mAutoCredentialViewModel.setCredentialModel(null, + mViewModel.setCredentialModel(null, new Intent().putExtras(newGkPwHandleCredentialIntentExtras(userId, gkPwHandle))); when(mLockPatternUtils.getActivePasswordQuality(userId)).thenReturn( PASSWORD_QUALITY_SOMETHING); @@ -282,21 +278,21 @@ public class AutoCredentialViewModelTest { .thenReturn(newBadCredential(0)); // Run credential check - @CredentialAction final int action = mAutoCredentialViewModel.checkCredential(); + @CredentialAction final int action = mViewModel.checkCredential(); assertThat(action).isEqualTo(CREDENTIAL_IS_GENERATING_CHALLENGE); - assertThat(mAutoCredentialViewModel.getGenerateChallengeFailLiveData().getValue()).isTrue(); + assertThat(mViewModel.getGenerateChallengeFailedLiveData().getValue()).isTrue(); assertThat(mChallengeGenerator.mCallbackRunCount).isEqualTo(1); } @Test public void testGetUserId_fromIntent() { final int userId = 106; - mAutoCredentialViewModel.setCredentialModel(null, + mViewModel.setCredentialModel(null, new Intent().putExtras(newInvalidChallengeCredentialIntentExtras(userId))); // Get userId - assertThat(mAutoCredentialViewModel.getUserId()).isEqualTo(userId); + assertThat(mViewModel.getUserId()).isEqualTo(userId); } @Test @@ -305,79 +301,79 @@ public class AutoCredentialViewModelTest { final Bundle savedInstance = new Bundle(); savedInstance.putBundle(KEY_CREDENTIAL_MODEL, newInvalidChallengeCredentialIntentExtras(userId)); - mAutoCredentialViewModel.setCredentialModel(savedInstance, new Intent()); + mViewModel.setCredentialModel(savedInstance, new Intent()); // Get userId - assertThat(mAutoCredentialViewModel.getUserId()).isEqualTo(userId); + assertThat(mViewModel.getUserId()).isEqualTo(userId); } @Test public void testCheckNewCredentialFromActivityResult_invalidChooseLock() { final int userId = 107; final long gkPwHandle = 3333L; - mAutoCredentialViewModel.setCredentialModel(null, + mViewModel.setCredentialModel(null, new Intent().putExtras(newGkPwHandleCredentialIntentExtras(userId, gkPwHandle))); final Intent intent = new Intent(); - intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, gkPwHandle); + intent.putExtra(EXTRA_KEY_GK_PW_HANDLE, gkPwHandle); // run checkNewCredentialFromActivityResult() - final boolean ret = mAutoCredentialViewModel.checkNewCredentialFromActivityResult(true, + final boolean ret = mViewModel.checkNewCredentialFromActivityResult(true, new ActivityResult(ChooseLockPattern.RESULT_FINISHED + 1, intent)); assertThat(ret).isFalse(); - assertThat(mAutoCredentialViewModel.getGenerateChallengeFailLiveData().getValue()).isNull(); + assertThat(mViewModel.getGenerateChallengeFailedLiveData().getValue()).isNull(); } @Test public void testCheckNewCredentialFromActivityResult_invalidConfirmLock() { final int userId = 107; final long gkPwHandle = 3333L; - mAutoCredentialViewModel.setCredentialModel(null, + mViewModel.setCredentialModel(null, new Intent().putExtras(newGkPwHandleCredentialIntentExtras(userId, gkPwHandle))); final Intent intent = new Intent(); - intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, gkPwHandle); + intent.putExtra(EXTRA_KEY_GK_PW_HANDLE, gkPwHandle); // run checkNewCredentialFromActivityResult() - final boolean ret = mAutoCredentialViewModel.checkNewCredentialFromActivityResult(false, + final boolean ret = mViewModel.checkNewCredentialFromActivityResult(false, new ActivityResult(Activity.RESULT_OK + 1, intent)); assertThat(ret).isFalse(); - assertThat(mAutoCredentialViewModel.getGenerateChallengeFailLiveData().getValue()).isNull(); + assertThat(mViewModel.getGenerateChallengeFailedLiveData().getValue()).isNull(); } @Test public void testCheckNewCredentialFromActivityResult_nullDataChooseLock() { final int userId = 108; final long gkPwHandle = 4444L; - mAutoCredentialViewModel.setCredentialModel(null, + mViewModel.setCredentialModel(null, new Intent().putExtras(newGkPwHandleCredentialIntentExtras(userId, gkPwHandle))); // run checkNewCredentialFromActivityResult() - final boolean ret = mAutoCredentialViewModel.checkNewCredentialFromActivityResult(true, + final boolean ret = mViewModel.checkNewCredentialFromActivityResult(true, new ActivityResult(ChooseLockPattern.RESULT_FINISHED, null)); assertThat(ret).isFalse(); - assertThat(mAutoCredentialViewModel.getGenerateChallengeFailLiveData().getValue()).isNull(); + assertThat(mViewModel.getGenerateChallengeFailedLiveData().getValue()).isNull(); } @Test public void testCheckNewCredentialFromActivityResult_nullDataConfirmLock() { final int userId = 109; - mAutoCredentialViewModel.setCredentialModel(null, + mViewModel.setCredentialModel(null, new Intent().putExtras(newInvalidChallengeCredentialIntentExtras(userId))); // run checkNewCredentialFromActivityResult() - final boolean ret = mAutoCredentialViewModel.checkNewCredentialFromActivityResult(false, + final boolean ret = mViewModel.checkNewCredentialFromActivityResult(false, new ActivityResult(Activity.RESULT_OK, null)); assertThat(ret).isFalse(); - assertThat(mAutoCredentialViewModel.getGenerateChallengeFailLiveData().getValue()).isNull(); + assertThat(mViewModel.getGenerateChallengeFailedLiveData().getValue()).isNull(); } @Test public void testCheckNewCredentialFromActivityResult_validChooseLock() { final int userId = 108; - mAutoCredentialViewModel.setCredentialModel(null, + mViewModel.setCredentialModel(null, new Intent().putExtras(newInvalidChallengeCredentialIntentExtras(userId))); when(mLockPatternUtils.getActivePasswordQuality(userId)).thenReturn( PASSWORD_QUALITY_SOMETHING); @@ -390,20 +386,17 @@ public class AutoCredentialViewModelTest { .thenReturn(newGoodCredential(gkPwHandle, new byte[] { 1 })); // Run checkNewCredentialFromActivityResult() - final Intent intent = new Intent().putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, - gkPwHandle); - final boolean ret = mAutoCredentialViewModel.checkNewCredentialFromActivityResult(true, + final Intent intent = new Intent().putExtra(EXTRA_KEY_GK_PW_HANDLE, gkPwHandle); + final boolean ret = mViewModel.checkNewCredentialFromActivityResult(true, new ActivityResult(ChooseLockPattern.RESULT_FINISHED, intent)); assertThat(ret).isTrue(); - assertThat(mAutoCredentialViewModel.getGenerateChallengeFailLiveData().getValue()).isNull(); - final Bundle extras = mAutoCredentialViewModel.getCredentialIntentExtra(); + assertThat(mViewModel.getGenerateChallengeFailedLiveData().getValue()).isNull(); + final Bundle extras = mViewModel.createCredentialIntentExtra(); assertThat(extras.getInt(EXTRA_KEY_SENSOR_ID)).isEqualTo(newSensorId); assertThat(extras.getLong(EXTRA_KEY_CHALLENGE)).isEqualTo(newChallenge); - assertThat(CredentialModel.isValidToken(extras.getByteArray(EXTRA_KEY_CHALLENGE_TOKEN))) - .isTrue(); - assertThat(CredentialModel.isValidGkPwHandle(extras.getLong(EXTRA_KEY_GK_PW_HANDLE))) - .isFalse(); + assertThat(isValidToken(extras.getByteArray(EXTRA_KEY_CHALLENGE_TOKEN))).isTrue(); + assertThat(isValidGkPwHandle(extras.getLong(EXTRA_KEY_GK_PW_HANDLE))).isFalse(); assertThat(mChallengeGenerator.mCallbackRunCount).isEqualTo(1); } @@ -411,7 +404,7 @@ public class AutoCredentialViewModelTest { @Test public void testCheckNewCredentialFromActivityResult_validConfirmLock() { final int userId = 109; - mAutoCredentialViewModel.setCredentialModel(null, + mViewModel.setCredentialModel(null, new Intent().putExtras(newInvalidChallengeCredentialIntentExtras(userId))); when(mLockPatternUtils.getActivePasswordQuality(userId)).thenReturn( PASSWORD_QUALITY_SOMETHING); @@ -424,20 +417,17 @@ public class AutoCredentialViewModelTest { .thenReturn(newGoodCredential(gkPwHandle, new byte[] { 1 })); // Run checkNewCredentialFromActivityResult() - final Intent intent = new Intent().putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, - gkPwHandle); - final boolean ret = mAutoCredentialViewModel.checkNewCredentialFromActivityResult(false, + final Intent intent = new Intent().putExtra(EXTRA_KEY_GK_PW_HANDLE, gkPwHandle); + final boolean ret = mViewModel.checkNewCredentialFromActivityResult(false, new ActivityResult(Activity.RESULT_OK, intent)); assertThat(ret).isTrue(); - assertThat(mAutoCredentialViewModel.getGenerateChallengeFailLiveData().getValue()).isNull(); - final Bundle extras = mAutoCredentialViewModel.getCredentialIntentExtra(); + assertThat(mViewModel.getGenerateChallengeFailedLiveData().getValue()).isNull(); + final Bundle extras = mViewModel.createCredentialIntentExtra(); assertThat(extras.getInt(EXTRA_KEY_SENSOR_ID)).isEqualTo(newSensorId); assertThat(extras.getLong(EXTRA_KEY_CHALLENGE)).isEqualTo(newChallenge); - assertThat(CredentialModel.isValidToken(extras.getByteArray(EXTRA_KEY_CHALLENGE_TOKEN))) - .isTrue(); - assertThat(CredentialModel.isValidGkPwHandle(extras.getLong(EXTRA_KEY_GK_PW_HANDLE))) - .isFalse(); + assertThat(isValidToken(extras.getByteArray(EXTRA_KEY_CHALLENGE_TOKEN))).isTrue(); + assertThat(isValidGkPwHandle(extras.getLong(EXTRA_KEY_GK_PW_HANDLE))).isFalse(); assertThat(mChallengeGenerator.mCallbackRunCount).isEqualTo(1); } diff --git a/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollIntroViewModelTest.java b/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollIntroViewModelTest.java index 921f1822809..a9536cffcbf 100644 --- a/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollIntroViewModelTest.java +++ b/tests/unit/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollIntroViewModelTest.java @@ -215,11 +215,13 @@ public class FingerprintEnrollIntroViewModelTest { @Test public void testSetHasScrolledToBottom() { - mViewModel.setHasScrolledToBottom(); - + mViewModel.setHasScrolledToBottom(true); FingerprintEnrollIntroStatus status = mViewModel.getPageStatusLiveData().getValue(); - assertThat(status.hasScrollToBottom()).isEqualTo(true); + + mViewModel.setHasScrolledToBottom(false); + status = mViewModel.getPageStatusLiveData().getValue(); + assertThat(status.hasScrollToBottom()).isEqualTo(false); } @Test From c2776e0e67d0caac16b138f0db6be528e7de7075 Mon Sep 17 00:00:00 2001 From: Bonian Chen Date: Wed, 23 Nov 2022 12:36:17 +0000 Subject: [PATCH 16/16] [Settings] Add some log Add log to support debugging. Bug: 259611847 Test: auto test Change-Id: Ic7ea410604794e3b9caa8ab955e1406578a25425 --- .../network/ResetNetworkOperationBuilder.java | 39 ++++++++++++++++--- 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/src/com/android/settings/network/ResetNetworkOperationBuilder.java b/src/com/android/settings/network/ResetNetworkOperationBuilder.java index 3b5c9bce646..3583d06b2b4 100644 --- a/src/com/android/settings/network/ResetNetworkOperationBuilder.java +++ b/src/com/android/settings/network/ResetNetworkOperationBuilder.java @@ -28,8 +28,10 @@ import android.net.wifi.WifiManager; import android.net.wifi.p2p.WifiP2pManager; import android.os.Looper; import android.os.RecoverySystem; +import android.os.SystemClock; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; +import android.util.Log; import com.android.settings.network.apn.ApnSettings; @@ -43,6 +45,10 @@ import java.util.function.Consumer; */ public class ResetNetworkOperationBuilder { + private static final String TAG = "ResetNetworkOpBuilder"; + + private static final boolean DRY_RUN = false; + private Context mContext; private List mResetSequence = new ArrayList(); @@ -127,10 +133,17 @@ public class ResetNetworkOperationBuilder { public ResetNetworkOperationBuilder resetEsim(String callerPackage, Consumer resultCallback) { Runnable runnable = () -> { - Boolean wipped = RecoverySystem.wipeEuiccData(mContext, callerPackage); - if (resultCallback != null) { - resultCallback.accept(wipped); + long startTime = SystemClock.elapsedRealtime(); + + if (!DRY_RUN) { + Boolean wipped = RecoverySystem.wipeEuiccData(mContext, callerPackage); + if (resultCallback != null) { + resultCallback.accept(wipped); + } } + + long endTime = SystemClock.elapsedRealtime(); + Log.i(TAG, "Reset eSIM, takes " + (endTime - startTime) + " ms"); }; mResetSequence.add(runnable); return this; @@ -179,14 +192,21 @@ public class ResetNetworkOperationBuilder { */ public ResetNetworkOperationBuilder resetApn(int subscriptionId) { Runnable runnable = () -> { + long startTime = SystemClock.elapsedRealtime(); + Uri uri = Uri.parse(ApnSettings.RESTORE_CARRIERS_URI); if (SubscriptionManager.isUsableSubscriptionId(subscriptionId)) { uri = Uri.withAppendedPath(uri, "subId/" + String.valueOf(subscriptionId)); } - ContentResolver resolver = mContext.getContentResolver(); - resolver.delete(uri, null, null); + if (!DRY_RUN) { + ContentResolver resolver = mContext.getContentResolver(); + resolver.delete(uri, null, null); + } + + long endTime = SystemClock.elapsedRealtime(); + Log.i(TAG, "Reset " + uri + ", takes " + (endTime - startTime) + " ms"); }; mResetSequence.add(runnable); return this; @@ -205,7 +225,14 @@ public class ResetNetworkOperationBuilder { if (service == null) { return; } - Runnable runnable = () -> serviceAccess.accept(service); + Runnable runnable = () -> { + long startTime = SystemClock.elapsedRealtime(); + if (!DRY_RUN) { + serviceAccess.accept(service); + } + long endTime = SystemClock.elapsedRealtime(); + Log.i(TAG, "Reset " + serviceName + ", takes " + (endTime - startTime) + " ms"); + }; mResetSequence.add(runnable); } }