diff options
710 files changed, 7520 insertions, 6089 deletions
diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java index 95728081bdb9..c9b33aa4dafc 100644 --- a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java +++ b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java @@ -4534,13 +4534,15 @@ public class AlarmManagerService extends SystemService { filter.addAction(Intent.ACTION_PACKAGE_RESTARTED); filter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART); filter.addDataScheme(IntentFilter.SCHEME_PACKAGE); - getContext().registerReceiver(this, filter); + getContext().registerReceiverForAllUsers(this, filter, + /* broadcastPermission */ null, /* scheduler */ null); // Register for events related to sdcard installation. IntentFilter sdFilter = new IntentFilter(); sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE); sdFilter.addAction(Intent.ACTION_USER_STOPPED); sdFilter.addAction(Intent.ACTION_UID_REMOVED); - getContext().registerReceiver(this, sdFilter); + getContext().registerReceiverForAllUsers(this, sdFilter, + /* broadcastPermission */ null, /* scheduler */ null); } @Override diff --git a/core/api/test-current.txt b/core/api/test-current.txt index d7c7bb174e45..bfbb9105dbb8 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -451,6 +451,7 @@ package android.app.admin { method @NonNull @RequiresPermission("android.permission.MANAGE_DEVICE_ADMINS") public java.util.Set<java.lang.String> getPolicyExemptApps(); method public boolean isCurrentInputMethodSetByOwner(); method public boolean isFactoryResetProtectionPolicySupported(); + method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}) public boolean isNewUserDisclaimerAcknowledged(); method @RequiresPermission(anyOf={"android.permission.MARK_DEVICE_ORGANIZATION_OWNED", "android.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS"}, conditional=true) public void markProfileOwnerOnOrganizationOwnedDevice(@NonNull android.content.ComponentName); method @NonNull public static String operationSafetyReasonToString(int); method @NonNull public static String operationToString(int); diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java index f453ba16043c..750e3d6f6fed 100644 --- a/core/java/android/app/Activity.java +++ b/core/java/android/app/Activity.java @@ -1537,7 +1537,10 @@ public class Activity extends ContextThemeWrapper } private void dispatchActivityConfigurationChanged() { - getApplication().dispatchActivityConfigurationChanged(this); + // In case the new config comes before mApplication is assigned. + if (getApplication() != null) { + getApplication().dispatchActivityConfigurationChanged(this); + } Object[] callbacks = collectActivityLifecycleCallbacks(); if (callbacks != null) { for (int i = 0; i < callbacks.length; i++) { diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl index 8f2417b1955f..df95f8f43bad 100644 --- a/core/java/android/app/IActivityManager.aidl +++ b/core/java/android/app/IActivityManager.aidl @@ -445,7 +445,7 @@ interface IActivityManager { void requestInteractiveBugReport(); void requestFullBugReport(); - void requestRemoteBugReport(); + void requestRemoteBugReport(long nonce); boolean launchBugReportHandlerApp(); List<String> getBugreportWhitelistedPackages(); diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl index 2be78033ddf7..cfda7e284c6b 100644 --- a/core/java/android/app/IActivityTaskManager.aidl +++ b/core/java/android/app/IActivityTaskManager.aidl @@ -293,7 +293,7 @@ interface IActivityTaskManager { * a short predefined amount of time. */ void registerRemoteAnimationForNextActivityStart(in String packageName, - in RemoteAnimationAdapter adapter); + in RemoteAnimationAdapter adapter, in IBinder launchCookie); /** * Registers remote animations for a display. diff --git a/core/java/android/app/TEST_MAPPING b/core/java/android/app/TEST_MAPPING index 23fc6f3bc72a..31c81bef7357 100644 --- a/core/java/android/app/TEST_MAPPING +++ b/core/java/android/app/TEST_MAPPING @@ -115,40 +115,42 @@ "file_patterns": ["(/|^)VoiceInteract[^/]*"] }, { - "name": "CtsContentTestCases", + "name": "CtsOsTestCases", "options": [ { + "include-annotation": "android.platform.test.annotations.Presubmit" + }, + { "exclude-annotation": "androidx.test.filters.FlakyTest" }, { "exclude-annotation": "org.junit.Ignore" }, { - "include-filter": "android.content.wm.cts" + "include-filter": "android.os.cts.StrictModeTest" } ], "file_patterns": ["(/|^)ContextImpl.java"] }, { - "name": "CtsOsTestCases", + "name": "FrameworksCoreTests", "options": [ { - "include-annotation": "android.platform.test.annotations.Presubmit" - }, - { "exclude-annotation": "androidx.test.filters.FlakyTest" }, { "exclude-annotation": "org.junit.Ignore" }, { - "include-filter": "android.os.cts.StrictModeTest" + "include-filter": "android.content.ContextTest" } ], "file_patterns": ["(/|^)ContextImpl.java"] - }, + } + ], + "presubmit-large": [ { - "name": "FrameworksCoreTests", + "name": "CtsContentTestCases", "options": [ { "exclude-annotation": "androidx.test.filters.FlakyTest" @@ -157,7 +159,7 @@ "exclude-annotation": "org.junit.Ignore" }, { - "include-filter": "android.content.ContextTest" + "include-filter": "android.content.wm.cts" } ], "file_patterns": ["(/|^)ContextImpl.java"] diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 067c135ca3aa..3ad33ae10446 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -21,6 +21,7 @@ import static android.net.NetworkCapabilities.NET_ENTERPRISE_ID_1; import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage; import android.Manifest.permission; +import android.accounts.Account; import android.annotation.CallbackExecutor; import android.annotation.ColorInt; import android.annotation.IntDef; @@ -167,6 +168,27 @@ public class DevicePolicyManager { this(context, service, false); } + /** + * Called when a managed profile has been provisioned. + * + * @throws SecurityException if the caller does not hold + * {@link android.Manifest.permission#MANAGE_PROFILE_AND_DEVICE_OWNERS}. + * @hide + */ + @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) + public void finalizeWorkProfileProvisioning( + @NonNull UserHandle managedProfileUser, @Nullable Account migratedAccount) { + Objects.requireNonNull(managedProfileUser, "managedProfileUser can't be null"); + if (mService == null) { + throw new IllegalStateException("Could not find DevicePolicyManagerService"); + } + try { + mService.finalizeWorkProfileProvisioning(managedProfileUser, migratedAccount); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + /** @hide */ @VisibleForTesting protected DevicePolicyManager(Context context, IDevicePolicyManager service, @@ -499,6 +521,14 @@ public class DevicePolicyManager { "android.intent.extra.REMOTE_BUGREPORT_HASH"; /** + * Extra for shared bugreport's nonce in long integer type. + * + * @hide + */ + public static final String EXTRA_REMOTE_BUGREPORT_NONCE = + "android.intent.extra.REMOTE_BUGREPORT_NONCE"; + + /** * Extra for remote bugreport notification shown type. * * @hide @@ -3105,11 +3135,19 @@ public class DevicePolicyManager { } } - /** @hide */ - public void resetNewUserDisclaimer() { + /** + * Acknoledges that the new managed user disclaimer was viewed by the (human) user + * so that {@link #ACTION_SHOW_NEW_USER_DISCLAIMER broadcast} is not sent again the next time + * this user is switched to. + * + * @hide + */ + @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS, + android.Manifest.permission.INTERACT_ACROSS_USERS}) + public void acknowledgeNewUserDisclaimer() { if (mService != null) { try { - mService.resetNewUserDisclaimer(); + mService.acknowledgeNewUserDisclaimer(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -3117,6 +3155,25 @@ public class DevicePolicyManager { } /** + * Checks whether the new managed user disclaimer was viewed by the current user. + * + * @hide + */ + @RequiresPermission(anyOf = {android.Manifest.permission.MANAGE_USERS, + android.Manifest.permission.INTERACT_ACROSS_USERS}) + @TestApi + public boolean isNewUserDisclaimerAcknowledged() { + if (mService != null) { + try { + return mService.isNewUserDisclaimerAcknowledged(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + return false; + } + + /** * Return true if the given administrator component is currently active (enabled) in the system. * * @param admin The administrator component to check for. @@ -5675,7 +5732,7 @@ public class DevicePolicyManager { */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_SHOW_NEW_USER_DISCLAIMER = - "android.app.action.ACTION_SHOW_NEW_USER_DISCLAIMER"; + "android.app.action.SHOW_NEW_USER_DISCLAIMER"; /** * Widgets are enabled in keyguard @@ -6363,10 +6420,10 @@ public class DevicePolicyManager { * management app can use {@link #ID_TYPE_BASE_INFO} to request inclusion of the general device * information including manufacturer, model, brand, device and product in the attestation * record. - * Only device owner, profile owner on an organization-owned device and their delegated - * certificate installers can use {@link #ID_TYPE_SERIAL}, {@link #ID_TYPE_IMEI} and - * {@link #ID_TYPE_MEID} to request unique device identifiers to be attested (the serial number, - * IMEI and MEID correspondingly), if supported by the device + * Only device owner, profile owner on an organization-owned device or affiliated user, and + * their delegated certificate installers can use {@link #ID_TYPE_SERIAL}, {@link #ID_TYPE_IMEI} + * and {@link #ID_TYPE_MEID} to request unique device identifiers to be attested (the serial + * number, IMEI and MEID correspondingly), if supported by the device * (see {@link #isDeviceIdAttestationSupported()}). * Additionally, device owner, profile owner on an organization-owned device and their delegated * certificate installers can also request the attestation record to be signed using an diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl index 765c8cbfc627..cc149cb50fa4 100644 --- a/core/java/android/app/admin/IDevicePolicyManager.aidl +++ b/core/java/android/app/admin/IDevicePolicyManager.aidl @@ -17,6 +17,7 @@ package android.app.admin; +import android.accounts.Account; import android.app.admin.NetworkEvent; import android.app.IApplicationThread; import android.app.IServiceConnection; @@ -98,6 +99,8 @@ interface IDevicePolicyManager { int getCurrentFailedPasswordAttempts(int userHandle, boolean parent); int getProfileWithMinimumFailedPasswordsForWipe(int userHandle, boolean parent); + void finalizeWorkProfileProvisioning(in UserHandle managedProfileUser, in Account migratedAccount); + void setMaximumFailedPasswordsForWipe(in ComponentName admin, int num, boolean parent); int getMaximumFailedPasswordsForWipe(in ComponentName admin, int userHandle, boolean parent); @@ -265,7 +268,8 @@ interface IDevicePolicyManager { int getLogoutUserId(); void clearLogoutUser(); List<UserHandle> getSecondaryUsers(in ComponentName who); - void resetNewUserDisclaimer(); + void acknowledgeNewUserDisclaimer(); + boolean isNewUserDisclaimerAcknowledged(); void enableSystemApp(in ComponentName admin, in String callerPackage, in String packageName); int enableSystemAppWithIntent(in ComponentName admin, in String callerPackage, in Intent intent); diff --git a/core/java/android/content/TEST_MAPPING b/core/java/android/content/TEST_MAPPING index 614143e7c04d..7f1d0d1d05cf 100644 --- a/core/java/android/content/TEST_MAPPING +++ b/core/java/android/content/TEST_MAPPING @@ -1,21 +1,6 @@ { "presubmit": [ { - "name": "CtsContentTestCases", - "options": [ - { - "exclude-annotation": "androidx.test.filters.FlakyTest" - }, - { - "exclude-annotation": "org.junit.Ignore" - }, - { - "include-filter": "android.content.wm.cts" - } - ], - "file_patterns": ["(/|^)Context.java", "(/|^)ContextWrapper.java"] - }, - { "name": "CtsOsTestCases", "options": [ { @@ -51,5 +36,22 @@ ], "file_patterns": ["(/|^)Context.java", "(/|^)ContextWrapper.java", "(/|^)ComponentCallbacksController.java"] } + ], + "presubmit-large": [ + { + "name": "CtsContentTestCases", + "options": [ + { + "exclude-annotation": "androidx.test.filters.FlakyTest" + }, + { + "exclude-annotation": "org.junit.Ignore" + }, + { + "include-filter": "android.content.wm.cts" + } + ], + "file_patterns": ["(/|^)Context.java", "(/|^)ContextWrapper.java"] + } ] }
\ No newline at end of file diff --git a/core/java/android/content/om/TEST_MAPPING b/core/java/android/content/om/TEST_MAPPING index d8f885439b34..6185cf64ad12 100644 --- a/core/java/android/content/om/TEST_MAPPING +++ b/core/java/android/content/om/TEST_MAPPING @@ -21,7 +21,9 @@ "include-filter": "android.appsecurity.cts.OverlayHostTest" } ] - }, + } + ], + "presubmit-large": [ { "name": "CtsContentTestCases", "options": [ diff --git a/core/java/android/content/pm/TEST_MAPPING b/core/java/android/content/pm/TEST_MAPPING index 8bc3734e060d..0a69413b36ea 100644 --- a/core/java/android/content/pm/TEST_MAPPING +++ b/core/java/android/content/pm/TEST_MAPPING @@ -19,6 +19,16 @@ "name": "CarrierAppIntegrationTestCases" }, { + "name": "CtsIncrementalInstallHostTestCases", + "options": [ + { + "include-filter": "android.incrementalinstall.cts.IncrementalFeatureTest" + } + ] + } + ], + "presubmit-large": [ + { "name": "CtsContentTestCases", "options": [ { @@ -31,14 +41,6 @@ "include-filter": "android.content.pm.cts" } ] - }, - { - "name": "CtsIncrementalInstallHostTestCases", - "options": [ - { - "include-filter": "android.incrementalinstall.cts.IncrementalFeatureTest" - } - ] } ], "postsubmit": [ diff --git a/core/java/android/content/res/TEST_MAPPING b/core/java/android/content/res/TEST_MAPPING index c02af59ab72e..535afd361f01 100644 --- a/core/java/android/content/res/TEST_MAPPING +++ b/core/java/android/content/res/TEST_MAPPING @@ -2,7 +2,9 @@ "presubmit": [ { "name": "CtsResourcesLoaderTests" - }, + } + ], + "presubmit-large": [ { "name": "CtsContentTestCases", "options": [ diff --git a/core/java/android/hardware/face/FaceManager.java b/core/java/android/hardware/face/FaceManager.java index 56f81423db4e..b97055976e3e 100644 --- a/core/java/android/hardware/face/FaceManager.java +++ b/core/java/android/hardware/face/FaceManager.java @@ -306,22 +306,21 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan throw new IllegalArgumentException("Must supply an enrollment callback"); } - if (cancel != null) { - if (cancel.isCanceled()) { - Slog.w(TAG, "enrollment already canceled"); - return; - } else { - cancel.setOnCancelListener(new OnEnrollCancelListener()); - } + if (cancel != null && cancel.isCanceled()) { + Slog.w(TAG, "enrollment already canceled"); + return; } if (mService != null) { try { mEnrollmentCallback = callback; Trace.beginSection("FaceManager#enroll"); - mService.enroll(userId, mToken, hardwareAuthToken, mServiceReceiver, - mContext.getOpPackageName(), disabledFeatures, previewSurface, - debugConsent); + final long enrollId = mService.enroll(userId, mToken, hardwareAuthToken, + mServiceReceiver, mContext.getOpPackageName(), disabledFeatures, + previewSurface, debugConsent); + if (cancel != null) { + cancel.setOnCancelListener(new OnEnrollCancelListener(enrollId)); + } } catch (RemoteException e) { Slog.w(TAG, "Remote exception in enroll: ", e); // Though this may not be a hardware issue, it will cause apps to give up or @@ -359,21 +358,20 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan throw new IllegalArgumentException("Must supply an enrollment callback"); } - if (cancel != null) { - if (cancel.isCanceled()) { - Slog.w(TAG, "enrollRemotely is already canceled."); - return; - } else { - cancel.setOnCancelListener(new OnEnrollCancelListener()); - } + if (cancel != null && cancel.isCanceled()) { + Slog.w(TAG, "enrollRemotely is already canceled."); + return; } if (mService != null) { try { mEnrollmentCallback = callback; Trace.beginSection("FaceManager#enrollRemotely"); - mService.enrollRemotely(userId, mToken, hardwareAuthToken, mServiceReceiver, - mContext.getOpPackageName(), disabledFeatures); + final long enrolId = mService.enrollRemotely(userId, mToken, hardwareAuthToken, + mServiceReceiver, mContext.getOpPackageName(), disabledFeatures); + if (cancel != null) { + cancel.setOnCancelListener(new OnEnrollCancelListener(enrolId)); + } } catch (RemoteException e) { Slog.w(TAG, "Remote exception in enrollRemotely: ", e); // Though this may not be a hardware issue, it will cause apps to give up or @@ -713,10 +711,10 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan } } - private void cancelEnrollment() { + private void cancelEnrollment(long requestId) { if (mService != null) { try { - mService.cancelEnrollment(mToken); + mService.cancelEnrollment(mToken, requestId); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1100,9 +1098,16 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan } private class OnEnrollCancelListener implements OnCancelListener { + private final long mAuthRequestId; + + private OnEnrollCancelListener(long id) { + mAuthRequestId = id; + } + @Override public void onCancel() { - cancelEnrollment(); + Slog.d(TAG, "Cancel face enrollment requested for: " + mAuthRequestId); + cancelEnrollment(mAuthRequestId); } } diff --git a/core/java/android/hardware/face/IFaceService.aidl b/core/java/android/hardware/face/IFaceService.aidl index e9198246dee3..989b001ca8bf 100644 --- a/core/java/android/hardware/face/IFaceService.aidl +++ b/core/java/android/hardware/face/IFaceService.aidl @@ -76,15 +76,16 @@ interface IFaceService { void cancelAuthenticationFromService(int sensorId, IBinder token, String opPackageName, long requestId); // Start face enrollment - void enroll(int userId, IBinder token, in byte [] hardwareAuthToken, IFaceServiceReceiver receiver, - String opPackageName, in int [] disabledFeatures, in Surface previewSurface, boolean debugConsent); + long enroll(int userId, IBinder token, in byte [] hardwareAuthToken, IFaceServiceReceiver receiver, + String opPackageName, in int [] disabledFeatures, + in Surface previewSurface, boolean debugConsent); // Start remote face enrollment - void enrollRemotely(int userId, IBinder token, in byte [] hardwareAuthToken, IFaceServiceReceiver receiver, + long enrollRemotely(int userId, IBinder token, in byte [] hardwareAuthToken, IFaceServiceReceiver receiver, String opPackageName, in int [] disabledFeatures); // Cancel enrollment in progress - void cancelEnrollment(IBinder token); + void cancelEnrollment(IBinder token, long requestId); // Removes the specified face enrollment for the specified userId. void remove(IBinder token, int faceId, int userId, IFaceServiceReceiver receiver, diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java index 3cee6100e4f8..7e070bc06056 100644 --- a/core/java/android/hardware/fingerprint/FingerprintManager.java +++ b/core/java/android/hardware/fingerprint/FingerprintManager.java @@ -184,9 +184,16 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing } private class OnEnrollCancelListener implements OnCancelListener { + private final long mAuthRequestId; + + private OnEnrollCancelListener(long id) { + mAuthRequestId = id; + } + @Override public void onCancel() { - cancelEnrollment(); + Slog.d(TAG, "Cancel fingerprint enrollment requested for: " + mAuthRequestId); + cancelEnrollment(mAuthRequestId); } } @@ -658,20 +665,19 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing throw new IllegalArgumentException("Must supply an enrollment callback"); } - if (cancel != null) { - if (cancel.isCanceled()) { - Slog.w(TAG, "enrollment already canceled"); - return; - } else { - cancel.setOnCancelListener(new OnEnrollCancelListener()); - } + if (cancel != null && cancel.isCanceled()) { + Slog.w(TAG, "enrollment already canceled"); + return; } if (mService != null) { try { mEnrollmentCallback = callback; - mService.enroll(mToken, hardwareAuthToken, userId, mServiceReceiver, - mContext.getOpPackageName(), enrollReason); + final long enrollId = mService.enroll(mToken, hardwareAuthToken, userId, + mServiceReceiver, mContext.getOpPackageName(), enrollReason); + if (cancel != null) { + cancel.setOnCancelListener(new OnEnrollCancelListener(enrollId)); + } } catch (RemoteException e) { Slog.w(TAG, "Remote exception in enroll: ", e); // Though this may not be a hardware issue, it will cause apps to give up or try @@ -1314,9 +1320,9 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing return allSensors.isEmpty() ? null : allSensors.get(0); } - private void cancelEnrollment() { + private void cancelEnrollment(long requestId) { if (mService != null) try { - mService.cancelEnrollment(mToken); + mService.cancelEnrollment(mToken, requestId); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/hardware/fingerprint/IFingerprintService.aidl b/core/java/android/hardware/fingerprint/IFingerprintService.aidl index ba1dc6da62a6..cbff8b11a72a 100644 --- a/core/java/android/hardware/fingerprint/IFingerprintService.aidl +++ b/core/java/android/hardware/fingerprint/IFingerprintService.aidl @@ -84,11 +84,11 @@ interface IFingerprintService { void cancelAuthenticationFromService(int sensorId, IBinder token, String opPackageName, long requestId); // Start fingerprint enrollment - void enroll(IBinder token, in byte [] hardwareAuthToken, int userId, IFingerprintServiceReceiver receiver, + long enroll(IBinder token, in byte [] hardwareAuthToken, int userId, IFingerprintServiceReceiver receiver, String opPackageName, int enrollReason); // Cancel enrollment in progress - void cancelEnrollment(IBinder token); + void cancelEnrollment(IBinder token, long requestId); // Any errors resulting from this call will be returned to the listener void remove(IBinder token, int fingerId, int userId, IFingerprintServiceReceiver receiver, diff --git a/core/java/android/hardware/location/GeofenceHardwareRequestParcelable.java b/core/java/android/hardware/location/GeofenceHardwareRequestParcelable.java index df13ade2bf5e..bd25b8f2ad88 100644 --- a/core/java/android/hardware/location/GeofenceHardwareRequestParcelable.java +++ b/core/java/android/hardware/location/GeofenceHardwareRequestParcelable.java @@ -16,9 +16,9 @@ package android.hardware.location; +import android.os.BadParcelableException; import android.os.Parcel; import android.os.Parcelable; -import android.util.Log; /** * Geofence Hardware Request used for internal location services communication. @@ -139,11 +139,8 @@ public final class GeofenceHardwareRequestParcelable implements Parcelable { @Override public GeofenceHardwareRequestParcelable createFromParcel(Parcel parcel) { int geofenceType = parcel.readInt(); - if(geofenceType != GeofenceHardwareRequest.GEOFENCE_TYPE_CIRCLE) { - Log.e( - "GeofenceHardwareRequest", - String.format("Invalid Geofence type: %d", geofenceType)); - return null; + if (geofenceType != GeofenceHardwareRequest.GEOFENCE_TYPE_CIRCLE) { + throw new BadParcelableException("Invalid Geofence type: " + geofenceType); } GeofenceHardwareRequest request = GeofenceHardwareRequest.createCircularGeofence( diff --git a/core/java/android/nfc/INfcTag.aidl b/core/java/android/nfc/INfcTag.aidl index 539fd4adb0a0..e1ccc4fb740b 100644 --- a/core/java/android/nfc/INfcTag.aidl +++ b/core/java/android/nfc/INfcTag.aidl @@ -45,4 +45,7 @@ interface INfcTag boolean canMakeReadOnly(int ndefType); int getMaxTransceiveLength(int technology); boolean getExtendedLengthApdusSupported(); + + void setTagUpToDate(long cookie); + boolean isTagUpToDate(long cookie); } diff --git a/core/java/android/nfc/Tag.java b/core/java/android/nfc/Tag.java index 398ec63a931b..731d1ba78299 100644 --- a/core/java/android/nfc/Tag.java +++ b/core/java/android/nfc/Tag.java @@ -34,6 +34,7 @@ import android.os.Bundle; import android.os.Parcel; import android.os.Parcelable; import android.os.RemoteException; +import android.os.SystemClock; import java.io.IOException; import java.util.Arrays; @@ -121,6 +122,7 @@ public final class Tag implements Parcelable { final INfcTag mTagService; // interface to NFC service, will be null if mock tag int mConnectedTechnology; + long mCookie; /** * Hidden constructor to be used by NFC service and internal classes. @@ -140,6 +142,17 @@ public final class Tag implements Parcelable { mTagService = tagService; mConnectedTechnology = -1; + mCookie = SystemClock.elapsedRealtime(); + + if (tagService == null) { + return; + } + + try { + tagService.setTagUpToDate(mCookie); + } catch (RemoteException e) { + throw e.rethrowAsRuntimeException(); + } } /** @@ -361,6 +374,22 @@ public final class Tag implements Parcelable { /** @hide */ @UnsupportedAppUsage public INfcTag getTagService() { + if (mTagService == null) { + return null; + } + + try { + if (!mTagService.isTagUpToDate(mCookie)) { + String id_str = ""; + for (int i = 0; i < mId.length; i++) { + id_str = id_str + String.format("%02X ", mId[i]); + } + String msg = "Permission Denial: Tag ( ID: " + id_str + ") is out of date"; + throw new SecurityException(msg); + } + } catch (RemoteException e) { + throw e.rethrowAsRuntimeException(); + } return mTagService; } diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java index 6ed99824cd0c..6411f424e7e0 100644 --- a/core/java/android/os/Parcel.java +++ b/core/java/android/os/Parcel.java @@ -557,6 +557,7 @@ public final class Parcel { */ public final void recycle() { if (DEBUG_RECYCLE) mStack = null; + mClassCookies = null; freeBuffer(); if (mOwnsNativeParcelObject) { diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java index 71b5354e4d42..6c8602510bf4 100644 --- a/core/java/android/provider/DeviceConfig.java +++ b/core/java/android/provider/DeviceConfig.java @@ -545,6 +545,13 @@ public final class DeviceConfig { public static final String NAMESPACE_WINDOW_MANAGER_NATIVE_BOOT = "window_manager_native_boot"; /** + * Definitions for voice interaction related functions. + * + * @hide + */ + public static final String NAMESPACE_VOICE_INTERACTION = "voice_interaction"; + + /** * List of namespaces which can be read without READ_DEVICE_CONFIG permission * * @hide diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index b7fcc03ef374..134cca1bb367 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -9696,6 +9696,13 @@ public final class Settings { "lockscreen_use_double_line_clock"; /** + * Whether to show the vibrate icon in the Status Bar (default off) + * + * @hide + */ + public static final String STATUS_BAR_SHOW_VIBRATE_ICON = "status_bar_show_vibrate_icon"; + + /** * Specifies whether the web action API is enabled. * * @hide @@ -13787,6 +13794,16 @@ public final class Settings { public static final String EMERGENCY_AFFORDANCE_NEEDED = "emergency_affordance_needed"; /** + * The power button "cooldown" period in milliseconds after the Emergency gesture is + * triggered, during which single-key actions on the power button are suppressed. Cooldown + * period is disabled if set to zero. + * + * @hide + */ + public static final String EMERGENCY_GESTURE_POWER_BUTTON_COOLDOWN_PERIOD_MS = + "emergency_gesture_power_button_cooldown_period_ms"; + + /** * Whether to enable automatic system server heap dumps. This only works on userdebug or * eng builds, not on user builds. This is set by the user and overrides the config value. * 1 means enable, 0 means disable. diff --git a/core/java/android/service/gatekeeper/GateKeeperResponse.java b/core/java/android/service/gatekeeper/GateKeeperResponse.java index 7ed733cb4f4c..9d648a6995fb 100644 --- a/core/java/android/service/gatekeeper/GateKeeperResponse.java +++ b/core/java/android/service/gatekeeper/GateKeeperResponse.java @@ -105,7 +105,7 @@ public final class GateKeeperResponse implements Parcelable { dest.writeInt(mTimeout); } else if (mResponseCode == RESPONSE_OK) { dest.writeInt(mShouldReEnroll ? 1 : 0); - if (mPayload != null) { + if (mPayload != null && mPayload.length > 0) { dest.writeInt(mPayload.length); dest.writeByteArray(mPayload); } else { diff --git a/core/java/android/service/voice/AbstractHotwordDetector.java b/core/java/android/service/voice/AbstractHotwordDetector.java index dbe108974684..192260791a8b 100644 --- a/core/java/android/service/voice/AbstractHotwordDetector.java +++ b/core/java/android/service/voice/AbstractHotwordDetector.java @@ -44,14 +44,17 @@ abstract class AbstractHotwordDetector implements HotwordDetector { private final IVoiceInteractionManagerService mManagerService; private final Handler mHandler; private final HotwordDetector.Callback mCallback; + private final int mDetectorType; AbstractHotwordDetector( IVoiceInteractionManagerService managerService, - HotwordDetector.Callback callback) { + HotwordDetector.Callback callback, + int detectorType) { mManagerService = managerService; // TODO: this needs to be supplied from above mHandler = new Handler(Looper.getMainLooper()); mCallback = callback; + mDetectorType = detectorType; } /** @@ -104,19 +107,20 @@ abstract class AbstractHotwordDetector implements HotwordDetector { Slog.d(TAG, "updateState()"); } synchronized (mLock) { - updateStateLocked(options, sharedMemory, null /* callback */); + updateStateLocked(options, sharedMemory, null /* callback */, mDetectorType); } } protected void updateStateLocked(@Nullable PersistableBundle options, - @Nullable SharedMemory sharedMemory, IHotwordRecognitionStatusCallback callback) { + @Nullable SharedMemory sharedMemory, IHotwordRecognitionStatusCallback callback, + int detectorType) { if (DEBUG) { Slog.d(TAG, "updateStateLocked()"); } Identity identity = new Identity(); identity.packageName = ActivityThread.currentOpPackageName(); try { - mManagerService.updateState(identity, options, sharedMemory, callback); + mManagerService.updateState(identity, options, sharedMemory, callback, detectorType); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/service/voice/AlwaysOnHotwordDetector.java b/core/java/android/service/voice/AlwaysOnHotwordDetector.java index face870ca1b4..c9daf52b5685 100644 --- a/core/java/android/service/voice/AlwaysOnHotwordDetector.java +++ b/core/java/android/service/voice/AlwaysOnHotwordDetector.java @@ -578,7 +578,9 @@ public class AlwaysOnHotwordDetector extends AbstractHotwordDetector { IVoiceInteractionManagerService modelManagementService, int targetSdkVersion, boolean supportHotwordDetectionService, @Nullable PersistableBundle options, @Nullable SharedMemory sharedMemory) { - super(modelManagementService, callback); + super(modelManagementService, callback, + supportHotwordDetectionService ? DETECTOR_TYPE_TRUSTED_HOTWORD_DSP + : DETECTOR_TYPE_NORMAL); mHandler = new MyHandler(); mText = text; @@ -590,7 +592,8 @@ public class AlwaysOnHotwordDetector extends AbstractHotwordDetector { mTargetSdkVersion = targetSdkVersion; mSupportHotwordDetectionService = supportHotwordDetectionService; if (mSupportHotwordDetectionService) { - updateStateLocked(options, sharedMemory, mInternalCallback); + updateStateLocked(options, sharedMemory, mInternalCallback, + DETECTOR_TYPE_TRUSTED_HOTWORD_DSP); } try { Identity identity = new Identity(); diff --git a/core/java/android/service/voice/HotwordDetector.java b/core/java/android/service/voice/HotwordDetector.java index e2478195bdde..969ec22beb97 100644 --- a/core/java/android/service/voice/HotwordDetector.java +++ b/core/java/android/service/voice/HotwordDetector.java @@ -37,6 +37,27 @@ import android.os.SharedMemory; public interface HotwordDetector { /** + * Indicates that it is a non-trusted hotword detector. + * + * @hide + */ + int DETECTOR_TYPE_NORMAL = 0; + + /** + * Indicates that it is a DSP trusted hotword detector. + * + * @hide + */ + int DETECTOR_TYPE_TRUSTED_HOTWORD_DSP = 1; + + /** + * Indicates that it is a software trusted hotword detector. + * + * @hide + */ + int DETECTOR_TYPE_TRUSTED_HOTWORD_SOFTWARE = 2; + + /** * Starts hotword recognition. * <p> * On calling this, the system streams audio from the device microphone to this application's @@ -98,6 +119,22 @@ public interface HotwordDetector { void updateState(@Nullable PersistableBundle options, @Nullable SharedMemory sharedMemory); /** + * @hide + */ + static String detectorTypeToString(int detectorType) { + switch (detectorType) { + case DETECTOR_TYPE_NORMAL: + return "normal"; + case DETECTOR_TYPE_TRUSTED_HOTWORD_DSP: + return "trusted_hotword_dsp"; + case DETECTOR_TYPE_TRUSTED_HOTWORD_SOFTWARE: + return "trusted_hotword_software"; + default: + return Integer.toString(detectorType); + } + } + + /** * The callback to notify of detection events. */ interface Callback { diff --git a/core/java/android/service/voice/SoftwareHotwordDetector.java b/core/java/android/service/voice/SoftwareHotwordDetector.java index f7a3415259fd..512a654adbab 100644 --- a/core/java/android/service/voice/SoftwareHotwordDetector.java +++ b/core/java/android/service/voice/SoftwareHotwordDetector.java @@ -60,14 +60,15 @@ class SoftwareHotwordDetector extends AbstractHotwordDetector { PersistableBundle options, SharedMemory sharedMemory, HotwordDetector.Callback callback) { - super(managerService, callback); + super(managerService, callback, DETECTOR_TYPE_TRUSTED_HOTWORD_SOFTWARE); mManagerService = managerService; mAudioFormat = audioFormat; mCallback = callback; mHandler = new Handler(Looper.getMainLooper()); updateStateLocked(options, sharedMemory, - new InitializationStateListener(mHandler, mCallback)); + new InitializationStateListener(mHandler, mCallback), + DETECTOR_TYPE_TRUSTED_HOTWORD_SOFTWARE); } @RequiresPermission(RECORD_AUDIO) diff --git a/core/java/android/util/TimingsTraceLog.java b/core/java/android/util/TimingsTraceLog.java index 5370645d31bc..f3353f45d434 100644 --- a/core/java/android/util/TimingsTraceLog.java +++ b/core/java/android/util/TimingsTraceLog.java @@ -127,7 +127,7 @@ public class TimingsTraceLog { * Logs a duration so it can be parsed by external tools for performance reporting. */ public void logDuration(String name, long timeMs) { - Slog.d(mTag, name + " took to complete: " + timeMs + "ms"); + Slog.v(mTag, name + " took to complete: " + timeMs + "ms"); } /** diff --git a/core/java/android/util/apk/TEST_MAPPING b/core/java/android/util/apk/TEST_MAPPING index 4598b4ffe4f6..e1825210bfd9 100644 --- a/core/java/android/util/apk/TEST_MAPPING +++ b/core/java/android/util/apk/TEST_MAPPING @@ -1,21 +1,23 @@ { "presubmit": [ { - "name": "CtsContentTestCases", + "name": "FrameworksCoreTests", "options": [ { - "include-filter": "android.content.pm.cts.PackageManagerShellCommandIncrementalTest" - }, - { - "include-filter": "android.content.pm.cts.PackageManagerShellCommandTest" + "include-filter": "android.util.apk.SourceStampVerifierTest" } ] - }, + } + ], + "presubmit-large": [ { - "name": "FrameworksCoreTests", + "name": "CtsContentTestCases", "options": [ { - "include-filter": "android.util.apk.SourceStampVerifierTest" + "include-filter": "android.content.pm.cts.PackageManagerShellCommandIncrementalTest" + }, + { + "include-filter": "android.content.pm.cts.PackageManagerShellCommandTest" } ] } diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl index 9da50889e43f..46ee0f839fa9 100644 --- a/core/java/android/view/IWindowSession.aidl +++ b/core/java/android/view/IWindowSession.aidl @@ -306,7 +306,7 @@ interface IWindowSession { */ void grantInputChannel(int displayId, in SurfaceControl surface, in IWindow window, in IBinder hostInputToken, int flags, int privateFlags, int type, - out InputChannel outInputChannel); + in IBinder focusGrantToken, out InputChannel outInputChannel); /** * Update the flags on an input channel associated with a particular surface. diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index 960d23d7afb0..a686cbf257ef 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -245,6 +245,7 @@ public final class SurfaceControl implements Parcelable { @SurfaceControl.BufferTransform int transformHint); private static native int nativeGetTransformHint(long nativeObject); private static native int nativeGetLayerId(long nativeObject); + private static native void nativeSanitize(long transactionObject); /** * Transforms that can be applied to buffers as they are displayed to a window. @@ -3544,6 +3545,13 @@ public final class SurfaceControl implements Parcelable { } /** + * @hide + */ + public void sanitize() { + nativeSanitize(mNativeObject); + } + + /** * Merge the other transaction into this transaction, clearing the * other transaction as if it had been applied. * diff --git a/core/java/android/view/SurfaceControlViewHost.java b/core/java/android/view/SurfaceControlViewHost.java index a6c5042db275..a312939e6522 100644 --- a/core/java/android/view/SurfaceControlViewHost.java +++ b/core/java/android/view/SurfaceControlViewHost.java @@ -231,7 +231,7 @@ public class SurfaceControlViewHost { public @Nullable SurfacePackage getSurfacePackage() { if (mSurfaceControl != null && mAccessibilityEmbeddedConnection != null) { return new SurfacePackage(mSurfaceControl, mAccessibilityEmbeddedConnection, - mViewRoot.getInputToken()); + mWm.getFocusGrantToken()); } else { return null; } diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index d779b4965d4e..ed6cd18941e3 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -3392,6 +3392,12 @@ public final class ViewRootImpl implements ViewParent, mReportNextDraw = false; pendingDrawFinished(); } + + // Make sure the consumer is not waiting if the view root was just made invisible. + if (mBLASTDrawConsumer != null) { + mBLASTDrawConsumer.accept(null); + mBLASTDrawConsumer = null; + } } } diff --git a/core/java/android/view/ViewRootInsetsControllerHost.java b/core/java/android/view/ViewRootInsetsControllerHost.java index efffa2b05a1e..aba79d5b87c3 100644 --- a/core/java/android/view/ViewRootInsetsControllerHost.java +++ b/core/java/android/view/ViewRootInsetsControllerHost.java @@ -171,8 +171,9 @@ public class ViewRootInsetsControllerHost implements InsetsController.Host { public void setSystemBarsAppearance(int appearance, int mask) { mViewRoot.mWindowAttributes.privateFlags |= PRIVATE_FLAG_APPEARANCE_CONTROLLED; final InsetsFlags insetsFlags = mViewRoot.mWindowAttributes.insetsFlags; - if (insetsFlags.appearance != appearance) { - insetsFlags.appearance = (insetsFlags.appearance & ~mask) | (appearance & mask); + final int newAppearance = (insetsFlags.appearance & ~mask) | (appearance & mask); + if (insetsFlags.appearance != newAppearance) { + insetsFlags.appearance = newAppearance; mViewRoot.mWindowAttributesChanged = true; mViewRoot.scheduleTraversals(); } diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java index ffb7efa67243..d5cf1a360b0f 100644 --- a/core/java/android/view/WindowlessWindowManager.java +++ b/core/java/android/view/WindowlessWindowManager.java @@ -22,6 +22,7 @@ import android.graphics.PixelFormat; import android.graphics.Point; import android.graphics.Rect; import android.graphics.Region; +import android.os.Binder; import android.os.IBinder; import android.os.RemoteCallback; import android.os.RemoteException; @@ -75,6 +76,7 @@ public class WindowlessWindowManager implements IWindowSession { private final Configuration mConfiguration; private final IWindowSession mRealWm; private final IBinder mHostInputToken; + private final IBinder mFocusGrantToken = new Binder(); private int mForceHeight = -1; private int mForceWidth = -1; @@ -91,6 +93,10 @@ public class WindowlessWindowManager implements IWindowSession { mConfiguration.setTo(configuration); } + IBinder getFocusGrantToken() { + return mFocusGrantToken; + } + /** * Utility API. */ @@ -153,10 +159,10 @@ public class WindowlessWindowManager implements IWindowSession { mRealWm.grantInputChannel(displayId, new SurfaceControl(sc, "WindowlessWindowManager.addToDisplay"), window, mHostInputToken, attrs.flags, attrs.privateFlags, attrs.type, - outInputChannel); + mFocusGrantToken, outInputChannel); } else { mRealWm.grantInputChannel(displayId, sc, window, mHostInputToken, attrs.flags, - attrs.privateFlags, attrs.type, outInputChannel); + attrs.privateFlags, attrs.type, mFocusGrantToken, outInputChannel); } } catch (RemoteException e) { Log.e(TAG, "Failed to grant input to surface: ", e); @@ -464,7 +470,7 @@ public class WindowlessWindowManager implements IWindowSession { @Override public void grantInputChannel(int displayId, SurfaceControl surface, IWindow window, - IBinder hostInputToken, int flags, int privateFlags, int type, + IBinder hostInputToken, int flags, int privateFlags, int type, IBinder focusGrantToken, InputChannel outInputChannel) { } diff --git a/core/java/android/view/contentcapture/ContentCaptureSession.java b/core/java/android/view/contentcapture/ContentCaptureSession.java index cc47f09d4e8d..a4db84055142 100644 --- a/core/java/android/view/contentcapture/ContentCaptureSession.java +++ b/core/java/android/view/contentcapture/ContentCaptureSession.java @@ -290,6 +290,8 @@ public abstract class ContentCaptureSession implements AutoCloseable { * <p>Typically used to change the context associated with the default session from an activity. */ public final void setContentCaptureContext(@Nullable ContentCaptureContext context) { + if (!isContentCaptureEnabled()) return; + mClientContext = context; updateContentCaptureContext(context); } diff --git a/core/java/android/view/translation/UiTranslationManager.java b/core/java/android/view/translation/UiTranslationManager.java index 3012e9344a1b..b57134b3ec44 100644 --- a/core/java/android/view/translation/UiTranslationManager.java +++ b/core/java/android/view/translation/UiTranslationManager.java @@ -101,26 +101,26 @@ public final class UiTranslationManager { public static final String LOG_TAG = "UiTranslation"; /** - * The state caller request to disable utranslation,, it is no longer need to ui translation. + * The state the caller requests to enable UI translation. * * @hide */ public static final int STATE_UI_TRANSLATION_STARTED = 0; /** - * The state caller request to pause ui translation, it will switch back to the original text. + * The state caller requests to pause UI translation. It will switch back to the original text. * * @hide */ public static final int STATE_UI_TRANSLATION_PAUSED = 1; /** - * The state caller request to resume the paused ui translation, it will show the translated + * The state caller requests to resume the paused UI translation. It will show the translated * text again if the text had been translated. * * @hide */ public static final int STATE_UI_TRANSLATION_RESUMED = 2; /** - * The state the caller request to enable ui translation. + * The state the caller requests to disable UI translation when it no longer needs translation. * * @hide */ diff --git a/core/java/android/widget/TextViewTranslationCallback.java b/core/java/android/widget/TextViewTranslationCallback.java index 942be21b1ade..1713d842560b 100644 --- a/core/java/android/widget/TextViewTranslationCallback.java +++ b/core/java/android/widget/TextViewTranslationCallback.java @@ -89,7 +89,7 @@ public class TextViewTranslationCallback implements ViewTranslationCallback { originalTranslationMethod); } final TransformationMethod transformation = mTranslationTransformation; - runWithAnimation( + runChangeTextWithAnimationIfNeeded( (TextView) view, () -> { mIsShowingTranslation = true; @@ -122,7 +122,7 @@ public class TextViewTranslationCallback implements ViewTranslationCallback { if (mTranslationTransformation != null) { final TransformationMethod transformation = mTranslationTransformation.getOriginalTransformationMethod(); - runWithAnimation( + runChangeTextWithAnimationIfNeeded( (TextView) view, () -> { mIsShowingTranslation = false; @@ -232,10 +232,16 @@ public class TextViewTranslationCallback implements ViewTranslationCallback { * Applies a simple text alpha animation when toggling between original and translated text. The * text is fully faded out, then swapped to the new text, then the fading is reversed. * - * @param runnable the operation to run on the view after the text is faded out, to change to - * displaying the original or translated text. + * @param changeTextRunnable the operation to run on the view after the text is faded out, to + * change to displaying the original or translated text. */ - private void runWithAnimation(TextView view, Runnable runnable) { + private void runChangeTextWithAnimationIfNeeded(TextView view, Runnable changeTextRunnable) { + boolean areAnimatorsEnabled = ValueAnimator.areAnimatorsEnabled(); + if (!areAnimatorsEnabled) { + // The animation is disabled, just change display text + changeTextRunnable.run(); + return; + } if (mAnimator != null) { mAnimator.end(); // Note: mAnimator is now null; do not use again here. @@ -269,7 +275,7 @@ public class TextViewTranslationCallback implements ViewTranslationCallback { @Override public void onAnimationRepeat(Animator animation) { - runnable.run(); + changeTextRunnable.run(); } }); mAnimator.start(); diff --git a/core/java/android/window/SplashScreen.java b/core/java/android/window/SplashScreen.java index 090dbff488e9..251e0acb97e6 100644 --- a/core/java/android/window/SplashScreen.java +++ b/core/java/android/window/SplashScreen.java @@ -99,8 +99,12 @@ public interface SplashScreen { * <p> * To reset to the default theme, set this the themeId to {@link Resources#ID_NULL}. * <p> - * <b>Note:</b> The theme name must be stable across versions, otherwise it won't be found - * after your application is updated. + * <b>Note:</b> Internally, the theme name is resolved and persisted. This means that the theme + * name must be stable across versions, otherwise it won't be found after your application is + * updated. + * + * @param themeId The ID of the splashscreen theme to be used in place of the one defined in + * the manifest. */ void setSplashScreenTheme(@StyleRes int themeId); diff --git a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl index 998526209c72..61c9128e499e 100644 --- a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl +++ b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl @@ -242,12 +242,14 @@ interface IVoiceInteractionManagerService { * {@link HotwordDetectionService}. Use this to provide the hotword models data or other * such data to the trusted process. * @param callback Use this to report {@link HotwordDetectionService} status. + * @param detectorType Indicate which detector is used. */ void updateState( in Identity originatorIdentity, in PersistableBundle options, in SharedMemory sharedMemory, - in IHotwordRecognitionStatusCallback callback); + in IHotwordRecognitionStatusCallback callback, + int detectorType); /** * Requests to shutdown hotword detection service. diff --git a/core/java/com/android/internal/infra/ServiceConnector.java b/core/java/com/android/internal/infra/ServiceConnector.java index 9ced6097804d..c379385429b5 100644 --- a/core/java/com/android/internal/infra/ServiceConnector.java +++ b/core/java/com/android/internal/infra/ServiceConnector.java @@ -507,10 +507,21 @@ public interface ServiceConnector<I extends IInterface> { void unbindJobThread() { cancelTimeout(); I service = mService; + // TODO(b/224695239): This is actually checking wasConnected. Rename and/or fix + // implementation based on what this should actually be checking. At least the first + // check for calling unbind is the correct behavior, though. boolean wasBound = service != null; + if (wasBound || mBinding) { + try { + mContext.unbindService(mServiceConnection); + } catch (IllegalArgumentException e) { // TODO(b/224697137): Fix the race condition + // that requires catching this (crashes if + // service isn't currently bound). + Log.e(LOG_TAG, "Failed to unbind: " + e); + } + } if (wasBound) { onServiceConnectionStatusChanged(service, false); - mContext.unbindService(mServiceConnection); service.asBinder().unlinkToDeath(this, 0); mService = null; } diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index c9b652ca1142..ce212e28e884 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -4672,7 +4672,6 @@ public class BatteryStatsImpl extends BatteryStats { public void noteLongPartialWakelockStart(String name, String historyName, int uid, long elapsedRealtimeMs, long uptimeMs) { - uid = mapUid(uid); noteLongPartialWakeLockStartInternal(name, historyName, uid, elapsedRealtimeMs, uptimeMs); } @@ -4704,15 +4703,21 @@ public class BatteryStatsImpl extends BatteryStats { private void noteLongPartialWakeLockStartInternal(String name, String historyName, int uid, long elapsedRealtimeMs, long uptimeMs) { + final int mappedUid = mapUid(uid); if (historyName == null) { historyName = name; } - if (!mActiveEvents.updateState(HistoryItem.EVENT_LONG_WAKE_LOCK_START, historyName, uid, - 0)) { + if (!mActiveEvents.updateState(HistoryItem.EVENT_LONG_WAKE_LOCK_START, historyName, + mappedUid, 0)) { return; } addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_LONG_WAKE_LOCK_START, - historyName, uid); + historyName, mappedUid); + if (mappedUid != uid) { + // Prevent the isolated uid mapping from being removed while the wakelock is + // being held. + incrementIsolatedUidRefCount(uid); + } } public void noteLongPartialWakelockFinish(String name, String historyName, int uid) { @@ -4722,7 +4727,6 @@ public class BatteryStatsImpl extends BatteryStats { public void noteLongPartialWakelockFinish(String name, String historyName, int uid, long elapsedRealtimeMs, long uptimeMs) { - uid = mapUid(uid); noteLongPartialWakeLockFinishInternal(name, historyName, uid, elapsedRealtimeMs, uptimeMs); } @@ -4754,15 +4758,20 @@ public class BatteryStatsImpl extends BatteryStats { private void noteLongPartialWakeLockFinishInternal(String name, String historyName, int uid, long elapsedRealtimeMs, long uptimeMs) { + final int mappedUid = mapUid(uid); if (historyName == null) { historyName = name; } - if (!mActiveEvents.updateState(HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH, historyName, uid, - 0)) { + if (!mActiveEvents.updateState(HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH, historyName, + mappedUid, 0)) { return; } addHistoryEventLocked(elapsedRealtimeMs, uptimeMs, HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH, - historyName, uid); + historyName, mappedUid); + if (mappedUid != uid) { + // Decrement the ref count for the isolated uid and delete the mapping if uneeded. + maybeRemoveIsolatedUidLocked(uid, elapsedRealtimeMs, uptimeMs); + } } void aggregateLastWakeupUptimeLocked(long elapsedRealtimeMs, long uptimeMs) { diff --git a/core/java/com/android/internal/os/MobileRadioPowerCalculator.java b/core/java/com/android/internal/os/MobileRadioPowerCalculator.java index eb5993dc2d61..31b807201bb6 100644 --- a/core/java/com/android/internal/os/MobileRadioPowerCalculator.java +++ b/core/java/com/android/internal/os/MobileRadioPowerCalculator.java @@ -99,9 +99,9 @@ public class MobileRadioPowerCalculator extends PowerCalculator { calculateApp(app, uid, powerPerPacketMah, total, query); } - final long consumptionUC = batteryStats.getMobileRadioMeasuredBatteryConsumptionUC(); - final int powerModel = getPowerModel(consumptionUC, query); - calculateRemaining(total, powerModel, batteryStats, rawRealtimeUs, consumptionUC); + final long totalConsumptionUC = batteryStats.getMobileRadioMeasuredBatteryConsumptionUC(); + final int powerModel = getPowerModel(totalConsumptionUC, query); + calculateRemaining(total, powerModel, batteryStats, rawRealtimeUs, totalConsumptionUC); if (total.remainingPowerMah != 0 || total.totalAppPowerMah != 0) { builder.getAggregateBatteryConsumerBuilder( @@ -229,12 +229,13 @@ public class MobileRadioPowerCalculator extends PowerCalculator { private void calculateRemaining(PowerAndDuration total, @BatteryConsumer.PowerModel int powerModel, BatteryStats batteryStats, - long rawRealtimeUs, long consumptionUC) { + long rawRealtimeUs, long totalConsumptionUC) { long signalTimeMs = 0; double powerMah = 0; if (powerModel == BatteryConsumer.POWER_MODEL_MEASURED_ENERGY) { - powerMah = uCtoMah(consumptionUC); + powerMah = uCtoMah(totalConsumptionUC) - total.totalAppPowerMah; + if (powerMah < 0) powerMah = 0; } for (int i = 0; i < NUM_SIGNAL_STRENGTH_LEVELS; i++) { diff --git a/core/java/com/android/internal/policy/IKeyguardStateCallback.aidl b/core/java/com/android/internal/policy/IKeyguardStateCallback.aidl index d69a240b140b..419b1f8feac7 100644 --- a/core/java/com/android/internal/policy/IKeyguardStateCallback.aidl +++ b/core/java/com/android/internal/policy/IKeyguardStateCallback.aidl @@ -16,7 +16,7 @@ package com.android.internal.policy; interface IKeyguardStateCallback { - void onShowingStateChanged(boolean showing, int userId); + void onShowingStateChanged(boolean showing); void onSimSecureStateChanged(boolean simSecure); void onInputRestrictedStateChanged(boolean inputRestricted); void onTrustedChanged(boolean trusted); diff --git a/core/java/com/android/internal/policy/SystemBarUtils.java b/core/java/com/android/internal/policy/SystemBarUtils.java index 6bf1333097f7..5358b96a0f97 100644 --- a/core/java/com/android/internal/policy/SystemBarUtils.java +++ b/core/java/com/android/internal/policy/SystemBarUtils.java @@ -43,7 +43,7 @@ public final class SystemBarUtils { * Gets the status bar height with a specific display cutout. */ public static int getStatusBarHeight(Resources res, DisplayCutout cutout) { - final int defaultSize = res.getDimensionPixelSize(R.dimen.status_bar_height); + final int defaultSize = res.getDimensionPixelSize(R.dimen.status_bar_height_default); final int safeInsetTop = cutout == null ? 0 : cutout.getSafeInsetTop(); final int waterfallInsetTop = cutout == null ? 0 : cutout.getWaterfallInsets().top; // The status bar height should be: diff --git a/core/java/com/android/internal/widget/ConversationLayout.java b/core/java/com/android/internal/widget/ConversationLayout.java index e6deada45fc1..a7d78eb02ed1 100644 --- a/core/java/com/android/internal/widget/ConversationLayout.java +++ b/core/java/com/android/internal/widget/ConversationLayout.java @@ -66,7 +66,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.function.Consumer; /** * A custom-built layout for the Notification.MessagingStyle allows dynamic addition and removal @@ -76,8 +75,6 @@ import java.util.function.Consumer; public class ConversationLayout extends FrameLayout implements ImageMessageConsumer, IMessagingLayout { - private static final Consumer<MessagingMessage> REMOVE_MESSAGE - = MessagingMessage::removeMessage; public static final Interpolator LINEAR_OUT_SLOW_IN = new PathInterpolator(0f, 0f, 0.2f, 1f); public static final Interpolator FAST_OUT_LINEAR_IN = new PathInterpolator(0.4f, 0f, 1f, 1f); public static final Interpolator FAST_OUT_SLOW_IN = new PathInterpolator(0.4f, 0f, 0.2f, 1f); @@ -150,6 +147,7 @@ public class ConversationLayout extends FrameLayout private Icon mShortcutIcon; private View mAppNameDivider; private TouchDelegateComposite mTouchDelegate = new TouchDelegateComposite(this); + private ArrayList<MessagingLinearLayout.MessagingChild> mToRecycle = new ArrayList<>(); public ConversationLayout(@NonNull Context context) { super(context); @@ -462,8 +460,12 @@ public class ConversationLayout extends FrameLayout removeGroups(oldGroups); // Let's remove the remaining messages - mMessages.forEach(REMOVE_MESSAGE); - mHistoricMessages.forEach(REMOVE_MESSAGE); + for (MessagingMessage message : mMessages) { + message.removeMessage(mToRecycle); + } + for (MessagingMessage historicMessage : mHistoricMessages) { + historicMessage.removeMessage(mToRecycle); + } mMessages = messages; mHistoricMessages = historicMessages; @@ -472,6 +474,12 @@ public class ConversationLayout extends FrameLayout updateTitleAndNamesDisplay(); updateConversationLayout(); + + // Recycle everything at the end of the update, now that we know it's no longer needed. + for (MessagingLinearLayout.MessagingChild child : mToRecycle) { + child.recycle(); + } + mToRecycle.clear(); } /** @@ -745,18 +753,18 @@ public class ConversationLayout extends FrameLayout MessagingGroup group = oldGroups.get(i); if (!mGroups.contains(group)) { List<MessagingMessage> messages = group.getMessages(); - Runnable endRunnable = () -> { - mMessagingLinearLayout.removeTransientView(group); - group.recycle(); - }; - boolean wasShown = group.isShown(); mMessagingLinearLayout.removeView(group); if (wasShown && !MessagingLinearLayout.isGone(group)) { mMessagingLinearLayout.addTransientView(group, 0); - group.removeGroupAnimated(endRunnable); + group.removeGroupAnimated(() -> { + mMessagingLinearLayout.removeTransientView(group); + group.recycle(); + }); } else { - endRunnable.run(); + // Defer recycling until after the update is done, since we may still need the + // old group around to perform other updates. + mToRecycle.add(group); } mMessages.removeAll(messages); mHistoricMessages.removeAll(messages); diff --git a/core/java/com/android/internal/widget/MessagingGroup.java b/core/java/com/android/internal/widget/MessagingGroup.java index f30b8442dc35..eaa9bcd72b84 100644 --- a/core/java/com/android/internal/widget/MessagingGroup.java +++ b/core/java/com/android/internal/widget/MessagingGroup.java @@ -263,7 +263,8 @@ public class MessagingGroup extends LinearLayout implements MessagingLinearLayou return createdGroup; } - public void removeMessage(MessagingMessage messagingMessage) { + public void removeMessage(MessagingMessage messagingMessage, + ArrayList<MessagingLinearLayout.MessagingChild> toRecycle) { View view = messagingMessage.getView(); boolean wasShown = view.isShown(); ViewGroup messageParent = (ViewGroup) view.getParent(); @@ -271,15 +272,14 @@ public class MessagingGroup extends LinearLayout implements MessagingLinearLayou return; } messageParent.removeView(view); - Runnable recycleRunnable = () -> { - messageParent.removeTransientView(view); - messagingMessage.recycle(); - }; if (wasShown && !MessagingLinearLayout.isGone(view)) { messageParent.addTransientView(view, 0); - performRemoveAnimation(view, recycleRunnable); + performRemoveAnimation(view, () -> { + messageParent.removeTransientView(view); + messagingMessage.recycle(); + }); } else { - recycleRunnable.run(); + toRecycle.add(messagingMessage); } } diff --git a/core/java/com/android/internal/widget/MessagingLayout.java b/core/java/com/android/internal/widget/MessagingLayout.java index e1602a981920..914de9e5e643 100644 --- a/core/java/com/android/internal/widget/MessagingLayout.java +++ b/core/java/com/android/internal/widget/MessagingLayout.java @@ -51,7 +51,6 @@ import com.android.internal.util.ContrastColorUtil; import java.util.ArrayList; import java.util.List; import java.util.Map; -import java.util.function.Consumer; /** * A custom-built layout for the Notification.MessagingStyle allows dynamic addition and removal @@ -62,8 +61,6 @@ public class MessagingLayout extends FrameLayout implements ImageMessageConsumer, IMessagingLayout { private static final float COLOR_SHIFT_AMOUNT = 60; - private static final Consumer<MessagingMessage> REMOVE_MESSAGE - = MessagingMessage::removeMessage; public static final Interpolator LINEAR_OUT_SLOW_IN = new PathInterpolator(0f, 0f, 0.2f, 1f); public static final Interpolator FAST_OUT_LINEAR_IN = new PathInterpolator(0.4f, 0f, 1f, 1f); public static final Interpolator FAST_OUT_SLOW_IN = new PathInterpolator(0.4f, 0f, 0.2f, 1f); @@ -89,6 +86,7 @@ public class MessagingLayout extends FrameLayout private boolean mIsCollapsed; private ImageResolver mImageResolver; private CharSequence mConversationTitle; + private ArrayList<MessagingLinearLayout.MessagingChild> mToRecycle = new ArrayList<>(); public MessagingLayout(@NonNull Context context) { super(context); @@ -212,8 +210,12 @@ public class MessagingLayout extends FrameLayout removeGroups(oldGroups); // Let's remove the remaining messages - mMessages.forEach(REMOVE_MESSAGE); - mHistoricMessages.forEach(REMOVE_MESSAGE); + for (MessagingMessage message : mMessages) { + message.removeMessage(mToRecycle); + } + for (MessagingMessage historicMessage : mHistoricMessages) { + historicMessage.removeMessage(mToRecycle); + } mMessages = messages; mHistoricMessages = historicMessages; @@ -223,6 +225,12 @@ public class MessagingLayout extends FrameLayout // after groups are finalized, hide the first sender name if it's showing as the title mPeopleHelper.maybeHideFirstSenderName(mGroups, mIsOneToOne, mConversationTitle); updateImageMessages(); + + // Recycle everything at the end of the update, now that we know it's no longer needed. + for (MessagingLinearLayout.MessagingChild child : mToRecycle) { + child.recycle(); + } + mToRecycle.clear(); } private void updateImageMessages() { @@ -263,18 +271,17 @@ public class MessagingLayout extends FrameLayout MessagingGroup group = oldGroups.get(i); if (!mGroups.contains(group)) { List<MessagingMessage> messages = group.getMessages(); - Runnable endRunnable = () -> { - mMessagingLinearLayout.removeTransientView(group); - group.recycle(); - }; boolean wasShown = group.isShown(); mMessagingLinearLayout.removeView(group); if (wasShown && !MessagingLinearLayout.isGone(group)) { mMessagingLinearLayout.addTransientView(group, 0); - group.removeGroupAnimated(endRunnable); + group.removeGroupAnimated(() -> { + mMessagingLinearLayout.removeTransientView(group); + group.recycle(); + }); } else { - endRunnable.run(); + mToRecycle.add(group); } mMessages.removeAll(messages); mHistoricMessages.removeAll(messages); diff --git a/core/java/com/android/internal/widget/MessagingLinearLayout.java b/core/java/com/android/internal/widget/MessagingLinearLayout.java index cb1d387dbd07..c06f5f75514f 100644 --- a/core/java/com/android/internal/widget/MessagingLinearLayout.java +++ b/core/java/com/android/internal/widget/MessagingLinearLayout.java @@ -365,6 +365,7 @@ public class MessagingLinearLayout extends ViewGroup { default int getExtraSpacing() { return 0; } + void recycle(); } public static class LayoutParams extends MarginLayoutParams { diff --git a/core/java/com/android/internal/widget/MessagingMessage.java b/core/java/com/android/internal/widget/MessagingMessage.java index 8c8437951402..2cc0d2305a78 100644 --- a/core/java/com/android/internal/widget/MessagingMessage.java +++ b/core/java/com/android/internal/widget/MessagingMessage.java @@ -20,6 +20,7 @@ import android.app.ActivityManager; import android.app.Notification; import android.view.View; +import java.util.ArrayList; import java.util.Objects; /** @@ -96,8 +97,8 @@ public interface MessagingMessage extends MessagingLinearLayout.MessagingChild { return sameAs(message.getMessage()); } - default void removeMessage() { - getGroup().removeMessage(this); + default void removeMessage(ArrayList<MessagingLinearLayout.MessagingChild> toRecycle) { + getGroup().removeMessage(this, toRecycle); } default void setMessagingGroup(MessagingGroup group) { diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp index 1452c67ae3c6..33fc92d60d62 100644 --- a/core/jni/android_view_SurfaceControl.cpp +++ b/core/jni/android_view_SurfaceControl.cpp @@ -877,6 +877,11 @@ static void nativeSetDropInputMode(JNIEnv* env, jclass clazz, jlong transactionO transaction->setDropInputMode(ctrl, static_cast<gui::DropInputMode>(mode)); } +static void nativeSanitize(JNIEnv* env, jclass clazz, jlong transactionObj) { + auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj); + transaction->sanitize(); +} + static jlongArray nativeGetPhysicalDisplayIds(JNIEnv* env, jclass clazz) { const auto displayIds = SurfaceComposerClient::getPhysicalDisplayIds(); jlongArray array = env->NewLongArray(displayIds.size()); @@ -2030,6 +2035,8 @@ static const JNINativeMethod sSurfaceControlMethods[] = { (void*)nativeSetDropInputMode }, {"nativeGetLayerId", "(J)I", (void*)nativeGetLayerId }, + {"nativeSanitize", "(J)V", + (void*) nativeSanitize } // clang-format on }; diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml index f81ac3dd6dd8..d2c4b644975e 100644 --- a/core/res/AndroidManifest.xml +++ b/core/res/AndroidManifest.xml @@ -100,6 +100,7 @@ <protected-broadcast android:name="android.intent.action.OVERLAY_PRIORITY_CHANGED" /> <protected-broadcast android:name="android.intent.action.MY_PACKAGE_SUSPENDED" /> <protected-broadcast android:name="android.intent.action.MY_PACKAGE_UNSUSPENDED" /> + <protected-broadcast android:name="android.app.action.MANAGED_PROFILE_PROVISIONED" /> <protected-broadcast android:name="android.os.action.POWER_SAVE_MODE_CHANGED" /> <protected-broadcast android:name="android.os.action.DEVICE_IDLE_MODE_CHANGED" /> @@ -711,7 +712,7 @@ <protected-broadcast android:name="android.scheduling.action.REBOOT_READY" /> <protected-broadcast android:name="android.app.action.DEVICE_POLICY_CONSTANTS_CHANGED" /> <protected-broadcast android:name="android.app.action.SCHEDULE_EXACT_ALARM_PERMISSION_STATE_CHANGED" /> - <protected-broadcast android:name="android.app.action.ACTION_SHOW_NEW_USER_DISCLAIMER" /> + <protected-broadcast android:name="android.app.action.SHOW_NEW_USER_DISCLAIMER" /> <!-- ====================================================================== --> <!-- RUNTIME PERMISSIONS --> diff --git a/core/res/res/values-land/dimens.xml b/core/res/res/values-land/dimens.xml index f1e5888d61b9..ca549aeba1f5 100644 --- a/core/res/res/values-land/dimens.xml +++ b/core/res/res/values-land/dimens.xml @@ -27,6 +27,8 @@ <dimen name="password_keyboard_spacebar_vertical_correction">2dip</dimen> <dimen name="preference_widget_width">72dp</dimen> + <!-- Height of the status bar --> + <dimen name="status_bar_height">@dimen/status_bar_height_landscape</dimen> <!-- Height of area above QQS where battery/time go --> <dimen name="quick_qs_offset_height">48dp</dimen> <!-- Default height of an action bar. --> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index a8ab1a88e4c7..160376ca2685 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -4578,6 +4578,8 @@ <item>0.75</item> </string-array> + <bool name="config_udfpsSupportsNewUi" translatable="false">false</bool> + <!-- Messages that should not be shown to the user during face auth enrollment. This should be used to hide messages that may be too chatty or messages that the user can't do much about. Entries are defined in android.hardware.biometrics.face@1.0 types.hal --> diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml index f331f1ab720f..cafebcec454e 100644 --- a/core/res/res/values/dimens.xml +++ b/core/res/res/values/dimens.xml @@ -39,14 +39,17 @@ <!-- Elevation of toast view --> <dimen name="toast_elevation">2dp</dimen> + <!-- The default height of the status bar used in {@link SystemBarUtils#getStatusBarHeight} to + calculate the status bar height. --> + <dimen name="status_bar_height_default">24dp</dimen> <!-- Height of the status bar. Do not read this dimen directly. Use {@link SystemBarUtils#getStatusBarHeight} instead. --> - <dimen name="status_bar_height">24dp</dimen> + <dimen name="status_bar_height">@dimen/status_bar_height_portrait</dimen> <!-- Height of the status bar in portrait. Do not read this dimen directly. Use {@link SystemBarUtils#getStatusBarHeight} instead. --> - <dimen name="status_bar_height_portrait">@dimen/status_bar_height</dimen> + <dimen name="status_bar_height_portrait">24dp</dimen> <!-- Height of the status bar in landscape. Do not read this dimen directly. Use {@link SystemBarUtils#getStatusBarHeight} instead. --> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 00639562918b..5894bdc389dc 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -2598,6 +2598,7 @@ <java-symbol type="integer" name="config_udfps_illumination_transition_ms" /> <java-symbol type="bool" name="config_is_powerbutton_fps" /> <java-symbol type="array" name="config_udfps_enroll_stage_thresholds" /> + <java-symbol type="bool" name="config_udfpsSupportsNewUi" /> <java-symbol type="array" name="config_face_acquire_enroll_ignorelist" /> <java-symbol type="array" name="config_face_acquire_vendor_enroll_ignorelist" /> @@ -4465,6 +4466,8 @@ <java-symbol type="array" name="config_roundedCornerBottomRadiusAdjustmentArray" /> <java-symbol type="bool" name="config_secondaryBuiltInDisplayIsRound" /> <java-symbol type="array" name="config_builtInDisplayIsRoundArray" /> + <java-symbol type="bool" name="config_disableTaskSnapshots" /> + <java-symbol type="dimen" name="status_bar_height_default" /> </resources> diff --git a/core/tests/coretests/src/android/content/AbstractCrossUserContentResolverTest.java b/core/tests/coretests/src/android/content/AbstractCrossUserContentResolverTest.java index 328429c6f96e..e690da2d0377 100644 --- a/core/tests/coretests/src/android/content/AbstractCrossUserContentResolverTest.java +++ b/core/tests/coretests/src/android/content/AbstractCrossUserContentResolverTest.java @@ -17,6 +17,7 @@ package android.content; import static org.junit.Assert.fail; +import static org.junit.Assume.assumeTrue; import android.app.ActivityManager; import android.app.activity.LocalProvider; @@ -58,10 +59,12 @@ abstract class AbstractCrossUserContentResolverTest { @Before public void setUp() throws Exception { mContext = InstrumentationRegistry.getContext(); + final PackageManager pm = mContext.getPackageManager(); + assumeTrue("device doesn't have the " + PackageManager.FEATURE_MANAGED_USERS + " feature", + pm.hasSystemFeature(PackageManager.FEATURE_MANAGED_USERS)); mUm = UserManager.get(mContext); final UserInfo userInfo = createUser(); mCrossUserId = userInfo.id; - final PackageManager pm = mContext.getPackageManager(); pm.installExistingPackageAsUser(mContext.getPackageName(), mCrossUserId); unlockUser(); diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java index 3e2885a74287..a6bc456cbe6d 100644 --- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java +++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java @@ -23,6 +23,8 @@ import static android.os.BatteryStats.WAKE_TYPE_PARTIAL; import static com.android.internal.os.BatteryStatsImpl.ExternalStatsSync.UPDATE_CPU; import static com.android.internal.os.BatteryStatsImpl.ExternalStatsSync.UPDATE_DISPLAY; +import static com.google.common.truth.Truth.assertThat; + import android.app.ActivityManager; import android.os.BatteryStats; import android.os.BatteryStats.HistoryItem; @@ -206,6 +208,116 @@ public class BatteryStatsNoteTest extends TestCase { assertEquals(120_000, bgTime); } + /** + * Test BatteryStatsImpl.Uid.noteLongPartialWakelockStart for an isolated uid. + */ + @SmallTest + public void testNoteLongPartialWakelockStart_isolatedUid() throws Exception { + final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms + MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks); + + + bi.setRecordAllHistoryLocked(true); + bi.forceRecordAllHistory(); + + int pid = 10; + String name = "name"; + String historyName = "historyName"; + + WorkSource.WorkChain isolatedWorkChain = new WorkSource.WorkChain(); + isolatedWorkChain.addNode(ISOLATED_UID, name); + + // Map ISOLATED_UID to UID. + bi.addIsolatedUidLocked(ISOLATED_UID, UID); + + bi.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0); + bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_TOP); + bi.noteLongPartialWakelockStart(name, historyName, ISOLATED_UID); + + clocks.realtime = clocks.uptime = 100; + bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND); + + clocks.realtime = clocks.uptime = 220; + bi.noteLongPartialWakelockFinish(name, historyName, ISOLATED_UID); + + final BatteryStatsHistoryIterator iterator = + bi.createBatteryStatsHistoryIterator(); + + BatteryStats.HistoryItem item = new BatteryStats.HistoryItem(); + + while (iterator.next(item)) { + if (item.eventCode == HistoryItem.EVENT_LONG_WAKE_LOCK_START) break; + } + assertThat(item.eventCode).isEqualTo(HistoryItem.EVENT_LONG_WAKE_LOCK_START); + assertThat(item.eventTag).isNotNull(); + assertThat(item.eventTag.string).isEqualTo(historyName); + assertThat(item.eventTag.uid).isEqualTo(UID); + + while (iterator.next(item)) { + if (item.eventCode == HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH) break; + } + assertThat(item.eventCode).isEqualTo(HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH); + assertThat(item.eventTag).isNotNull(); + assertThat(item.eventTag.string).isEqualTo(historyName); + assertThat(item.eventTag.uid).isEqualTo(UID); + } + + /** + * Test BatteryStatsImpl.Uid.noteLongPartialWakelockStart for an isolated uid. + */ + @SmallTest + public void testNoteLongPartialWakelockStart_isolatedUidRace() throws Exception { + final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms + MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks); + + + bi.setRecordAllHistoryLocked(true); + bi.forceRecordAllHistory(); + + int pid = 10; + String name = "name"; + String historyName = "historyName"; + + WorkSource.WorkChain isolatedWorkChain = new WorkSource.WorkChain(); + isolatedWorkChain.addNode(ISOLATED_UID, name); + + // Map ISOLATED_UID to UID. + bi.addIsolatedUidLocked(ISOLATED_UID, UID); + + bi.updateTimeBasesLocked(true, Display.STATE_OFF, 0, 0); + bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_TOP); + bi.noteLongPartialWakelockStart(name, historyName, ISOLATED_UID); + + clocks.realtime = clocks.uptime = 100; + bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND); + + clocks.realtime = clocks.uptime = 150; + bi.maybeRemoveIsolatedUidLocked(ISOLATED_UID, clocks.realtime, clocks.uptime); + + clocks.realtime = clocks.uptime = 220; + bi.noteLongPartialWakelockFinish(name, historyName, ISOLATED_UID); + + final BatteryStatsHistoryIterator iterator = + bi.createBatteryStatsHistoryIterator(); + + BatteryStats.HistoryItem item = new BatteryStats.HistoryItem(); + + while (iterator.next(item)) { + if (item.eventCode == HistoryItem.EVENT_LONG_WAKE_LOCK_START) break; + } + assertThat(item.eventCode).isEqualTo(HistoryItem.EVENT_LONG_WAKE_LOCK_START); + assertThat(item.eventTag).isNotNull(); + assertThat(item.eventTag.string).isEqualTo(historyName); + assertThat(item.eventTag.uid).isEqualTo(UID); + + while (iterator.next(item)) { + if (item.eventCode == HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH) break; + } + assertThat(item.eventCode).isEqualTo(HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH); + assertThat(item.eventTag).isNotNull(); + assertThat(item.eventTag.string).isEqualTo(historyName); + assertThat(item.eventTag.uid).isEqualTo(UID); + } /** * Test BatteryStatsImpl.noteUidProcessStateLocked. diff --git a/core/tests/coretests/src/com/android/internal/os/MobileRadioPowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/MobileRadioPowerCalculatorTest.java index a48a8822f4c0..19ccd642ba25 100644 --- a/core/tests/coretests/src/com/android/internal/os/MobileRadioPowerCalculatorTest.java +++ b/core/tests/coretests/src/com/android/internal/os/MobileRadioPowerCalculatorTest.java @@ -176,8 +176,9 @@ public class MobileRadioPowerCalculatorTest { .isEqualTo(BatteryConsumer.POWER_MODEL_MEASURED_ENERGY); BatteryConsumer deviceConsumer = mStatsRule.getDeviceBatteryConsumer(); + // 10_000_000 micro-Coulomb * 1/1000 milli/micro * 1/3600 hour/second = 2.77778 mAh assertThat(deviceConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO)) - .isWithin(PRECISION).of(4.31711); + .isWithin(PRECISION).of(2.77778); assertThat(deviceConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO)) .isEqualTo(BatteryConsumer.POWER_MODEL_MEASURED_ENERGY); diff --git a/core/tests/mockingcoretests/src/android/util/TimingsTraceLogTest.java b/core/tests/mockingcoretests/src/android/util/TimingsTraceLogTest.java index 5dc44d21c6b7..8de919681006 100644 --- a/core/tests/mockingcoretests/src/android/util/TimingsTraceLogTest.java +++ b/core/tests/mockingcoretests/src/android/util/TimingsTraceLogTest.java @@ -123,7 +123,7 @@ public class TimingsTraceLogTest { public void testLogDuration() throws Exception { TimingsTraceLog log = new TimingsTraceLog(TAG, TRACE_TAG_APP, 10); log.logDuration("logro", 42); - verify((MockedVoidMethod) () -> Slog.d(eq(TAG), contains("logro took to complete: 42ms"))); + verify((MockedVoidMethod) () -> Slog.v(eq(TAG), contains("logro took to complete: 42ms"))); } @Test @@ -134,7 +134,7 @@ public class TimingsTraceLogTest { verify((MockedVoidMethod) () -> Trace.traceBegin(TRACE_TAG_APP, "test")); verify((MockedVoidMethod) () -> Trace.traceEnd(TRACE_TAG_APP)); - verify((MockedVoidMethod) () -> Slog.d(eq(TAG), matches("test took to complete: \\dms"))); + verify((MockedVoidMethod) () -> Slog.v(eq(TAG), matches("test took to complete: \\dms"))); } @Test @@ -149,8 +149,8 @@ public class TimingsTraceLogTest { verify((MockedVoidMethod) () -> Trace.traceBegin(TRACE_TAG_APP, "L2")); verify((MockedVoidMethod) () -> Trace.traceEnd(TRACE_TAG_APP), times(2)); // L1 and L2 - verify((MockedVoidMethod) () -> Slog.d(eq(TAG), matches("L2 took to complete: \\d+ms"))); - verify((MockedVoidMethod) () -> Slog.d(eq(TAG), matches("L1 took to complete: \\d+ms"))); + verify((MockedVoidMethod) () -> Slog.v(eq(TAG), matches("L2 took to complete: \\d+ms"))); + verify((MockedVoidMethod) () -> Slog.v(eq(TAG), matches("L1 took to complete: \\d+ms"))); } @Test @@ -170,9 +170,9 @@ public class TimingsTraceLogTest { verify((MockedVoidMethod) () -> Trace.traceBegin(TRACE_TAG_APP, "L3")); verify((MockedVoidMethod) () -> Trace.traceEnd(TRACE_TAG_APP), times(3)); - verify((MockedVoidMethod) () -> Slog.d(eq(TAG), matches("L2 took to complete: \\d+ms"))); - verify((MockedVoidMethod) () -> Slog.d(eq(TAG), matches("L1 took to complete: \\d+ms"))); - verify((MockedVoidMethod) () -> Slog.d(eq(TAG), matches("L3 took to complete: \\d+ms")), + verify((MockedVoidMethod) () -> Slog.v(eq(TAG), matches("L2 took to complete: \\d+ms"))); + verify((MockedVoidMethod) () -> Slog.v(eq(TAG), matches("L1 took to complete: \\d+ms"))); + verify((MockedVoidMethod) () -> Slog.v(eq(TAG), matches("L3 took to complete: \\d+ms")), never()); verify((MockedVoidMethod) () -> Slog.w(TAG, "not tracing duration of 'L3' " diff --git a/data/etc/car/com.android.car.shell.xml b/data/etc/car/com.android.car.shell.xml index 992840db1a27..f29f6ee07af0 100644 --- a/data/etc/car/com.android.car.shell.xml +++ b/data/etc/car/com.android.car.shell.xml @@ -37,5 +37,6 @@ <permission name="android.car.permission.USE_CAR_WATCHDOG" /> <permission name="android.car.permission.COLLECT_CAR_WATCHDOG_METRICS" /> <permission name="android.car.permission.CONTROL_CAR_WATCHDOG_CONFIG" /> + <permission name="com.android.car.permission.USE_CAR_TELEMETRY_SERVICE"/> </privapp-permissions> </permissions> diff --git a/data/etc/car/com.android.carsystemui.xml b/data/etc/car/com.android.carsystemui.xml index a267d5650782..6c9103cb0f4f 100644 --- a/data/etc/car/com.android.carsystemui.xml +++ b/data/etc/car/com.android.carsystemui.xml @@ -24,5 +24,6 @@ <permission name="android.car.permission.CONTROL_CAR_CLIMATE"/> <permission name="android.car.permission.CONTROL_CAR_EVS_ACTIVITY"/> <permission name="android.car.permission.MONITOR_CAR_EVS_STATUS"/> + <permission name="android.car.permission.CONTROL_CAR_APP_LAUNCH"/> </privapp-permissions> </permissions> diff --git a/data/etc/car/com.google.android.car.kitchensink.xml b/data/etc/car/com.google.android.car.kitchensink.xml index 2c59c7390ebf..313fa308801a 100644 --- a/data/etc/car/com.google.android.car.kitchensink.xml +++ b/data/etc/car/com.google.android.car.kitchensink.xml @@ -95,6 +95,6 @@ <permission name="android.car.permission.CONTROL_CAR_EVS_ACTIVITY" /> <permission name="android.car.permission.USE_CAR_EVS_CAMERA" /> <permission name="android.car.permission.MONITOR_CAR_EVS_STATUS" /> - <permission name="android.car.permission.USE_CAR_TELEMETRY_SERVICE" /> + <permission name="com.android.car.permission.USE_CAR_TELEMETRY_SERVICE" /> </privapp-permissions> </permissions> diff --git a/libs/WindowManager/Jetpack/src/androidx/window/common/CommonDisplayFeature.java b/libs/WindowManager/Jetpack/src/androidx/window/common/CommonFoldingFeature.java index eb9429747b66..8733c152dca9 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/common/CommonDisplayFeature.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/common/CommonFoldingFeature.java @@ -18,17 +18,73 @@ package androidx.window.common; import static androidx.window.util.ExtensionHelper.isZero; +import android.annotation.IntDef; import android.annotation.Nullable; import android.graphics.Rect; +import android.util.Log; import androidx.annotation.NonNull; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.ArrayList; +import java.util.List; import java.util.Objects; import java.util.regex.Matcher; import java.util.regex.Pattern; -/** Wrapper for both Extension and Sidecar versions of DisplayFeature. */ -final class CommonDisplayFeature implements DisplayFeature { +/** A representation of a folding feature for both Extension and Sidecar. + * For Sidecar this is the same as combining {@link androidx.window.sidecar.SidecarDeviceState} and + * {@link androidx.window.sidecar.SidecarDisplayFeature}. For Extensions this is the mirror of + * {@link androidx.window.extensions.layout.FoldingFeature}. + */ +public final class CommonFoldingFeature { + + private static final boolean DEBUG = false; + + public static final String TAG = CommonFoldingFeature.class.getSimpleName(); + + /** + * A common type to represent a hinge where the screen is continuous. + */ + public static final int COMMON_TYPE_FOLD = 1; + + /** + * A common type to represent a hinge where there is a physical gap separating multiple + * displays. + */ + public static final int COMMON_TYPE_HINGE = 2; + + @IntDef({COMMON_TYPE_FOLD, COMMON_TYPE_HINGE}) + @Retention(RetentionPolicy.SOURCE) + public @interface Type { + } + + /** + * A common state to represent when the state is not known. One example is if the device is + * closed. We do not emit this value for developers but is useful for implementation reasons. + */ + public static final int COMMON_STATE_UNKNOWN = -1; + + /** + * A common state to represent a FLAT hinge. This is needed because the definitions in Sidecar + * and Extensions do not match exactly. + */ + public static final int COMMON_STATE_FLAT = 3; + /** + * A common state to represent a HALF_OPENED hinge. This is needed because the definitions in + * Sidecar and Extensions do not match exactly. + */ + public static final int COMMON_STATE_HALF_OPENED = 2; + + /** + * The possible states for a folding hinge. + */ + @IntDef({COMMON_STATE_UNKNOWN, COMMON_STATE_FLAT, COMMON_STATE_HALF_OPENED}) + @Retention(RetentionPolicy.SOURCE) + public @interface State { + } + private static final Pattern FEATURE_PATTERN = Pattern.compile("([a-z]+)-\\[(\\d+),(\\d+),(\\d+),(\\d+)]-?(flat|half-opened)?"); @@ -38,17 +94,49 @@ final class CommonDisplayFeature implements DisplayFeature { private static final String PATTERN_STATE_FLAT = "flat"; private static final String PATTERN_STATE_HALF_OPENED = "half-opened"; - // TODO(b/183049815): Support feature strings that include the state of the feature. + /** + * Parse a {@link List} of {@link CommonFoldingFeature} from a {@link String}. + * @param value a {@link String} representation of multiple {@link CommonFoldingFeature} + * separated by a ":". + * @param hingeState a global fallback value for a {@link CommonFoldingFeature} if one is not + * specified in the input. + * @throws IllegalArgumentException if the provided string is improperly formatted or could not + * otherwise be parsed. + * @see #FEATURE_PATTERN + * @return {@link List} of {@link CommonFoldingFeature}. + */ + static List<CommonFoldingFeature> parseListFromString(@NonNull String value, + @State int hingeState) { + List<CommonFoldingFeature> features = new ArrayList<>(); + String[] featureStrings = value.split(";"); + for (String featureString : featureStrings) { + CommonFoldingFeature feature; + try { + feature = CommonFoldingFeature.parseFromString(featureString, hingeState); + } catch (IllegalArgumentException e) { + if (DEBUG) { + Log.w(TAG, "Failed to parse display feature: " + featureString, e); + } + continue; + } + features.add(feature); + } + return features; + } /** * Parses a display feature from a string. * + * @param string A {@link String} representation of a {@link CommonFoldingFeature}. + * @param hingeState A fallback value for the {@link State} if it is not specified in the input. * @throws IllegalArgumentException if the provided string is improperly formatted or could not * otherwise be parsed. + * @return {@link CommonFoldingFeature} represented by the {@link String} value. * @see #FEATURE_PATTERN */ @NonNull - static CommonDisplayFeature parseFromString(@NonNull String string) { + private static CommonFoldingFeature parseFromString(@NonNull String string, + @State int hingeState) { Matcher featureMatcher = FEATURE_PATTERN.matcher(string); if (!featureMatcher.matches()) { throw new IllegalArgumentException("Malformed feature description format: " + string); @@ -59,10 +147,10 @@ final class CommonDisplayFeature implements DisplayFeature { int type; switch (featureType) { case FEATURE_TYPE_FOLD: - type = 1 /* TYPE_FOLD */; + type = COMMON_TYPE_FOLD; break; case FEATURE_TYPE_HINGE: - type = 2 /* TYPE_HINGE */; + type = COMMON_TYPE_HINGE; break; default: { throw new IllegalArgumentException("Malformed feature type: " + featureType); @@ -79,7 +167,7 @@ final class CommonDisplayFeature implements DisplayFeature { } String stateString = featureMatcher.group(6); stateString = stateString == null ? "" : stateString; - Integer state; + final int state; switch (stateString) { case PATTERN_STATE_FLAT: state = COMMON_STATE_FLAT; @@ -88,10 +176,10 @@ final class CommonDisplayFeature implements DisplayFeature { state = COMMON_STATE_HALF_OPENED; break; default: - state = null; + state = hingeState; break; } - return new CommonDisplayFeature(type, state, featureRect); + return new CommonFoldingFeature(type, state, featureRect); } catch (NumberFormatException e) { throw new IllegalArgumentException("Malformed feature description: " + string, e); } @@ -99,11 +187,11 @@ final class CommonDisplayFeature implements DisplayFeature { private final int mType; @Nullable - private final Integer mState; + private final int mState; @NonNull private final Rect mRect; - CommonDisplayFeature(int type, @Nullable Integer state, @NonNull Rect rect) { + CommonFoldingFeature(int type, int state, @NonNull Rect rect) { assertValidState(state); this.mType = type; this.mState = state; @@ -114,16 +202,19 @@ final class CommonDisplayFeature implements DisplayFeature { this.mRect = rect; } + /** Returns the type of the feature. */ + @Type public int getType() { return mType; } /** Returns the state of the feature, or {@code null} if the feature has no state. */ - @Nullable - public Integer getState() { + @State + public int getState() { return mState; } + /** Returns the bounds of the feature. */ @NonNull public Rect getRect() { return mRect; @@ -133,7 +224,7 @@ final class CommonDisplayFeature implements DisplayFeature { public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; - CommonDisplayFeature that = (CommonDisplayFeature) o; + CommonFoldingFeature that = (CommonFoldingFeature) o; return mType == that.mType && Objects.equals(mState, that.mState) && mRect.equals(that.mRect); @@ -145,7 +236,8 @@ final class CommonDisplayFeature implements DisplayFeature { } private static void assertValidState(@Nullable Integer state) { - if (state != null && state != COMMON_STATE_FLAT && state != COMMON_STATE_HALF_OPENED) { + if (state != null && state != COMMON_STATE_FLAT + && state != COMMON_STATE_HALF_OPENED && state != COMMON_STATE_UNKNOWN) { throw new IllegalArgumentException("Invalid state: " + state + "must be either COMMON_STATE_FLAT or COMMON_STATE_HALF_OPENED"); } diff --git a/libs/WindowManager/Jetpack/src/androidx/window/common/DeviceStateManagerPostureProducer.java b/libs/WindowManager/Jetpack/src/androidx/window/common/DeviceStateManagerFoldingFeatureProducer.java index fa9a5a8b7a1b..6987401525b4 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/common/DeviceStateManagerPostureProducer.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/common/DeviceStateManagerFoldingFeatureProducer.java @@ -18,11 +18,15 @@ package androidx.window.common; import static android.hardware.devicestate.DeviceStateManager.INVALID_DEVICE_STATE; +import static androidx.window.common.CommonFoldingFeature.COMMON_STATE_UNKNOWN; +import static androidx.window.common.CommonFoldingFeature.parseListFromString; + import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; import android.hardware.devicestate.DeviceStateManager; import android.hardware.devicestate.DeviceStateManager.DeviceStateCallback; +import android.text.TextUtils; import android.util.Log; import android.util.SparseIntArray; @@ -30,6 +34,7 @@ import androidx.window.util.BaseDataProducer; import com.android.internal.R; +import java.util.List; import java.util.Optional; /** @@ -37,10 +42,13 @@ import java.util.Optional; * by mapping the state returned from {@link DeviceStateManager} to values provided in the resources * config at {@link R.array#config_device_state_postures}. */ -public final class DeviceStateManagerPostureProducer extends BaseDataProducer<Integer> { - private static final String TAG = "ConfigDevicePostureProducer"; +public final class DeviceStateManagerFoldingFeatureProducer extends + BaseDataProducer<List<CommonFoldingFeature>> { + private static final String TAG = + DeviceStateManagerFoldingFeatureProducer.class.getSimpleName(); private static final boolean DEBUG = false; + private final Context mContext; private final SparseIntArray mDeviceStateToPostureMap = new SparseIntArray(); private int mCurrentDeviceState = INVALID_DEVICE_STATE; @@ -50,7 +58,8 @@ public final class DeviceStateManagerPostureProducer extends BaseDataProducer<In notifyDataChanged(); }; - public DeviceStateManagerPostureProducer(@NonNull Context context) { + public DeviceStateManagerFoldingFeatureProducer(@NonNull Context context) { + mContext = context; String[] deviceStatePosturePairs = context.getResources() .getStringArray(R.array.config_device_state_postures); for (String deviceStatePosturePair : deviceStatePosturePairs) { @@ -86,8 +95,17 @@ public final class DeviceStateManagerPostureProducer extends BaseDataProducer<In @Override @Nullable - public Optional<Integer> getData() { - final int posture = mDeviceStateToPostureMap.get(mCurrentDeviceState, -1); - return posture != -1 ? Optional.of(posture) : Optional.empty(); + public Optional<List<CommonFoldingFeature>> getData() { + final int globalHingeState = globalHingeState(); + String displayFeaturesString = mContext.getResources().getString( + R.string.config_display_features); + if (TextUtils.isEmpty(displayFeaturesString)) { + return Optional.empty(); + } + return Optional.of(parseListFromString(displayFeaturesString, globalHingeState)); + } + + private int globalHingeState() { + return mDeviceStateToPostureMap.get(mCurrentDeviceState, COMMON_STATE_UNKNOWN); } } diff --git a/libs/WindowManager/Jetpack/src/androidx/window/common/DisplayFeature.java b/libs/WindowManager/Jetpack/src/androidx/window/common/DisplayFeature.java deleted file mode 100644 index 573641857b99..000000000000 --- a/libs/WindowManager/Jetpack/src/androidx/window/common/DisplayFeature.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2021 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 androidx.window.common; - -import android.annotation.IntDef; -import android.annotation.Nullable; -import android.graphics.Rect; - -import androidx.annotation.NonNull; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -/** Wrapper for both Extension and Sidecar versions of DisplayFeature. */ -public interface DisplayFeature { - /** Returns the type of the feature. */ - int getType(); - - /** Returns the state of the feature, or {@code null} if the feature has no state. */ - @Nullable - @State - Integer getState(); - - /** Returns the bounds of the feature. */ - @NonNull - Rect getRect(); - - /** - * A common state to represent a FLAT hinge. This is needed because the definitions in Sidecar - * and Extensions do not match exactly. - */ - int COMMON_STATE_FLAT = 3; - /** - * A common state to represent a HALF_OPENED hinge. This is needed because the definitions in - * Sidecar and Extensions do not match exactly. - */ - int COMMON_STATE_HALF_OPENED = 2; - - /** - * The possible states for a folding hinge. - */ - @IntDef({COMMON_STATE_FLAT, COMMON_STATE_HALF_OPENED}) - @Retention(RetentionPolicy.SOURCE) - @interface State {} - -} diff --git a/libs/WindowManager/Jetpack/src/androidx/window/common/EmptyLifecycleCallbacksAdapter.java b/libs/WindowManager/Jetpack/src/androidx/window/common/EmptyLifecycleCallbacksAdapter.java new file mode 100644 index 000000000000..f2e403b4f792 --- /dev/null +++ b/libs/WindowManager/Jetpack/src/androidx/window/common/EmptyLifecycleCallbacksAdapter.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2021 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 androidx.window.common; + +import android.app.Activity; +import android.app.Application; +import android.os.Bundle; + +/** + * An empty implementation of {@link Application.ActivityLifecycleCallbacks} derived classes can + * implement the methods necessary. + */ +public class EmptyLifecycleCallbacksAdapter implements Application.ActivityLifecycleCallbacks { + @Override + public void onActivityCreated(Activity activity, Bundle savedInstanceState) { + } + + @Override + public void onActivityStarted(Activity activity) { + } + + @Override + public void onActivityResumed(Activity activity) { + } + + @Override + public void onActivityPaused(Activity activity) { + } + + @Override + public void onActivityStopped(Activity activity) { + } + + @Override + public void onActivitySaveInstanceState(Activity activity, Bundle outState) { + } + + @Override + public void onActivityDestroyed(Activity activity) { + } +} diff --git a/libs/WindowManager/Jetpack/src/androidx/window/common/ResourceConfigDisplayFeatureProducer.java b/libs/WindowManager/Jetpack/src/androidx/window/common/ResourceConfigDisplayFeatureProducer.java deleted file mode 100644 index cd2cadc082e1..000000000000 --- a/libs/WindowManager/Jetpack/src/androidx/window/common/ResourceConfigDisplayFeatureProducer.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2021 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 androidx.window.common; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.content.Context; -import android.text.TextUtils; -import android.util.Log; - -import androidx.window.util.BaseDataProducer; - -import com.android.internal.R; - -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; - -/** - * Implementation of {@link androidx.window.util.DataProducer} that produces - * {@link CommonDisplayFeature} parsed from a string stored in the resources config at - * {@link R.string#config_display_features}. - */ -public final class ResourceConfigDisplayFeatureProducer extends - BaseDataProducer<List<DisplayFeature>> { - private static final boolean DEBUG = false; - private static final String TAG = "ResourceConfigDisplayFeatureProducer"; - - private final Context mContext; - - public ResourceConfigDisplayFeatureProducer(@NonNull Context context) { - mContext = context; - } - - @Override - @Nullable - public Optional<List<DisplayFeature>> getData() { - String displayFeaturesString = mContext.getResources().getString( - R.string.config_display_features); - if (TextUtils.isEmpty(displayFeaturesString)) { - return Optional.empty(); - } - - List<DisplayFeature> features = new ArrayList<>(); - String[] featureStrings = displayFeaturesString.split(";"); - for (String featureString : featureStrings) { - CommonDisplayFeature feature; - try { - feature = CommonDisplayFeature.parseFromString(featureString); - } catch (IllegalArgumentException e) { - if (DEBUG) { - Log.w(TAG, "Failed to parse display feature: " + featureString, e); - } - continue; - } - features.add(feature); - } - return Optional.of(features); - } -} diff --git a/libs/WindowManager/Jetpack/src/androidx/window/common/SettingsDevicePostureProducer.java b/libs/WindowManager/Jetpack/src/androidx/window/common/SettingsDevicePostureProducer.java deleted file mode 100644 index 2026df3fa979..000000000000 --- a/libs/WindowManager/Jetpack/src/androidx/window/common/SettingsDevicePostureProducer.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2021 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 androidx.window.common; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.content.ContentResolver; -import android.content.Context; -import android.database.ContentObserver; -import android.net.Uri; -import android.os.Handler; -import android.os.Looper; -import android.provider.Settings; - -import androidx.window.util.BaseDataProducer; - -import java.util.Optional; - -/** - * Implementation of {@link androidx.window.util.DataProducer} that provides the device posture - * as an {@link Integer} from a value stored in {@link Settings}. - */ -public final class SettingsDevicePostureProducer extends BaseDataProducer<Integer> { - private static final String DEVICE_POSTURE = "device_posture"; - - private final Uri mDevicePostureUri = - Settings.Global.getUriFor(DEVICE_POSTURE); - - private final ContentResolver mResolver; - private final ContentObserver mObserver; - private boolean mRegisteredObservers; - - public SettingsDevicePostureProducer(@NonNull Context context) { - mResolver = context.getContentResolver(); - mObserver = new SettingsObserver(); - } - - @Override - @Nullable - public Optional<Integer> getData() { - int posture = Settings.Global.getInt(mResolver, DEVICE_POSTURE, -1); - return posture == -1 ? Optional.empty() : Optional.of(posture); - } - - /** - * Registers settings observers, if needed. When settings observers are registered for this - * producer callbacks for changes in data will be triggered. - */ - public void registerObserversIfNeeded() { - if (mRegisteredObservers) { - return; - } - mRegisteredObservers = true; - mResolver.registerContentObserver(mDevicePostureUri, false /* notifyForDescendants */, - mObserver /* ContentObserver */); - } - - /** - * Unregisters settings observers, if needed. When settings observers are unregistered for this - * producer callbacks for changes in data will not be triggered. - */ - public void unregisterObserversIfNeeded() { - if (!mRegisteredObservers) { - return; - } - mRegisteredObservers = false; - mResolver.unregisterContentObserver(mObserver); - } - - private final class SettingsObserver extends ContentObserver { - SettingsObserver() { - super(new Handler(Looper.getMainLooper())); - } - - @Override - public void onChange(boolean selfChange, Uri uri) { - if (mDevicePostureUri.equals(uri)) { - notifyDataChanged(); - } - } - } -} diff --git a/libs/WindowManager/Jetpack/src/androidx/window/common/SettingsDisplayFeatureProducer.java b/libs/WindowManager/Jetpack/src/androidx/window/common/SettingsDisplayFeatureProducer.java index 040662657a74..0e696eb8efb7 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/common/SettingsDisplayFeatureProducer.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/common/SettingsDisplayFeatureProducer.java @@ -16,8 +16,12 @@ package androidx.window.common; +import static androidx.window.common.CommonFoldingFeature.COMMON_STATE_FLAT; +import static androidx.window.common.CommonFoldingFeature.COMMON_STATE_HALF_OPENED; +import static androidx.window.common.CommonFoldingFeature.COMMON_STATE_UNKNOWN; +import static androidx.window.common.CommonFoldingFeature.parseListFromString; + import android.annotation.NonNull; -import android.annotation.Nullable; import android.content.ContentResolver; import android.content.Context; import android.database.ContentObserver; @@ -26,24 +30,24 @@ import android.os.Handler; import android.os.Looper; import android.provider.Settings; import android.text.TextUtils; -import android.util.Log; import androidx.window.util.BaseDataProducer; -import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Optional; /** * Implementation of {@link androidx.window.util.DataProducer} that produces - * {@link CommonDisplayFeature} parsed from a string stored in {@link Settings}. + * {@link CommonFoldingFeature} parsed from a string stored in {@link Settings}. */ public final class SettingsDisplayFeatureProducer - extends BaseDataProducer<List<DisplayFeature>> { - private static final boolean DEBUG = false; - private static final String TAG = "SettingsDisplayFeatureProducer"; + extends BaseDataProducer<List<CommonFoldingFeature>> { private static final String DISPLAY_FEATURES = "display_features"; + private static final String DEVICE_POSTURE = "device_posture"; + private final Uri mDevicePostureUri = + Settings.Global.getUriFor(DEVICE_POSTURE); private final Uri mDisplayFeaturesUri = Settings.Global.getUriFor(DISPLAY_FEATURES); @@ -56,33 +60,27 @@ public final class SettingsDisplayFeatureProducer mObserver = new SettingsObserver(); } + private int getPosture() { + int posture = Settings.Global.getInt(mResolver, DEVICE_POSTURE, COMMON_STATE_UNKNOWN); + if (posture == COMMON_STATE_HALF_OPENED || posture == COMMON_STATE_FLAT) { + return posture; + } else { + return COMMON_STATE_UNKNOWN; + } + } + @Override - @Nullable - public Optional<List<DisplayFeature>> getData() { + @NonNull + public Optional<List<CommonFoldingFeature>> getData() { String displayFeaturesString = Settings.Global.getString(mResolver, DISPLAY_FEATURES); if (displayFeaturesString == null) { return Optional.empty(); } - List<DisplayFeature> features = new ArrayList<>(); if (TextUtils.isEmpty(displayFeaturesString)) { - return Optional.of(features); - } - String[] featureStrings = displayFeaturesString.split(";"); - - for (String featureString : featureStrings) { - CommonDisplayFeature feature; - try { - feature = CommonDisplayFeature.parseFromString(featureString); - } catch (IllegalArgumentException e) { - if (DEBUG) { - Log.w(TAG, "Failed to parse display feature: " + featureString, e); - } - continue; - } - features.add(feature); + return Optional.of(Collections.emptyList()); } - return Optional.of(features); + return Optional.of(parseListFromString(displayFeaturesString, getPosture())); } /** @@ -96,6 +94,7 @@ public final class SettingsDisplayFeatureProducer mRegisteredObservers = true; mResolver.registerContentObserver(mDisplayFeaturesUri, false /* notifyForDescendants */, mObserver /* ContentObserver */); + mResolver.registerContentObserver(mDevicePostureUri, false, mObserver); } /** @@ -117,7 +116,7 @@ public final class SettingsDisplayFeatureProducer @Override public void onChange(boolean selfChange, Uri uri) { - if (mDisplayFeaturesUri.equals(uri)) { + if (mDisplayFeaturesUri.equals(uri) || mDevicePostureUri.equals(uri)) { notifyDataChanged(); } } diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java index 8f368c2bee22..fc955927f3ed 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java @@ -28,7 +28,6 @@ import android.app.Activity; import android.app.ActivityClient; import android.app.ActivityOptions; import android.app.ActivityThread; -import android.app.Application.ActivityLifecycleCallbacks; import android.app.Instrumentation; import android.content.Context; import android.content.Intent; @@ -41,6 +40,8 @@ import android.os.Looper; import android.window.TaskFragmentInfo; import android.window.WindowContainerTransaction; +import androidx.window.common.EmptyLifecycleCallbacksAdapter; + import java.util.ArrayList; import java.util.List; import java.util.Set; @@ -759,11 +760,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen return shouldRetainAssociatedContainer(finishingContainer, associatedContainer); } - private final class LifecycleCallbacks implements ActivityLifecycleCallbacks { - - @Override - public void onActivityCreated(Activity activity, Bundle savedInstanceState) { - } + private final class LifecycleCallbacks extends EmptyLifecycleCallbacksAdapter { @Override public void onActivityPostCreated(Activity activity, Bundle savedInstanceState) { @@ -775,30 +772,6 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen } @Override - public void onActivityStarted(Activity activity) { - } - - @Override - public void onActivityResumed(Activity activity) { - } - - @Override - public void onActivityPaused(Activity activity) { - } - - @Override - public void onActivityStopped(Activity activity) { - } - - @Override - public void onActivitySaveInstanceState(Activity activity, Bundle outState) { - } - - @Override - public void onActivityDestroyed(Activity activity) { - } - - @Override public void onActivityConfigurationChanged(Activity activity) { SplitController.this.onActivityConfigurationChanged(activity); } @@ -833,8 +806,8 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen if (shouldExpand(null, intent, getSplitRules())) { setLaunchingInExpandedContainer(launchingActivity, options); - } else if (!setLaunchingToSideContainer(launchingActivity, intent, options)) { - setLaunchingInSameContainer(launchingActivity, intent, options); + } else if (!splitWithLaunchingActivity(launchingActivity, intent, options)) { + setLaunchingInSameSideContainer(launchingActivity, intent, options); } return super.onStartActivity(who, intent, options); @@ -853,9 +826,9 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen /** * Returns {@code true} if the activity that is going to be started via the * {@code intent} should be paired with the {@code launchingActivity} and is set to be - * launched in an empty side container. + * launched in the side container. */ - private boolean setLaunchingToSideContainer(Activity launchingActivity, Intent intent, + private boolean splitWithLaunchingActivity(Activity launchingActivity, Intent intent, Bundle options) { final SplitPairRule splitPairRule = getSplitRule(launchingActivity, intent, getSplitRules()); @@ -863,9 +836,14 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen return false; } - // Create a new split with an empty side container - final TaskFragmentContainer secondaryContainer = mPresenter - .createNewSplitWithEmptySideContainer(launchingActivity, splitPairRule); + // Check if there is any existing side container to launch into. + TaskFragmentContainer secondaryContainer = findSideContainerForNewLaunch( + launchingActivity, splitPairRule); + if (secondaryContainer == null) { + // Create a new split with an empty side container. + secondaryContainer = mPresenter + .createNewSplitWithEmptySideContainer(launchingActivity, splitPairRule); + } // Amend the request to let the WM know that the activity should be placed in the // dedicated container. @@ -875,12 +853,39 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen } /** + * Finds if there is an existing split side {@link TaskFragmentContainer} that can be used + * for the new rule. + */ + @Nullable + private TaskFragmentContainer findSideContainerForNewLaunch(Activity launchingActivity, + SplitPairRule splitPairRule) { + final TaskFragmentContainer launchingContainer = getContainerWithActivity( + launchingActivity.getActivityToken()); + if (launchingContainer == null) { + return null; + } + + // We only check if the launching activity is the primary of the split. We will check + // if the launching activity is the secondary in #setLaunchingInSameSideContainer. + final SplitContainer splitContainer = getActiveSplitForContainer(launchingContainer); + if (splitContainer == null + || splitContainer.getPrimaryContainer() != launchingContainer) { + return null; + } + + if (canReuseContainer(splitPairRule, splitContainer.getSplitRule())) { + return splitContainer.getSecondaryContainer(); + } + return null; + } + + /** * Checks if the activity that is going to be started via the {@code intent} should be * paired with the existing top activity which is currently paired with the - * {@code launchingActivity}. If so, set the activity to be launched in the same + * {@code launchingActivity}. If so, set the activity to be launched in the same side * container of the {@code launchingActivity}. */ - private void setLaunchingInSameContainer(Activity launchingActivity, Intent intent, + private void setLaunchingInSameSideContainer(Activity launchingActivity, Intent intent, Bundle options) { final TaskFragmentContainer launchingContainer = getContainerWithActivity( launchingActivity.getActivityToken()); @@ -911,6 +916,11 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen return; } + // Can only launch in the same container if the rules share the same presentation. + if (!canReuseContainer(splitPairRule, splitContainer.getSplitRule())) { + return; + } + // Amend the request to let the WM know that the activity should be placed in the // dedicated container. This is necessary for the case that the activity is started // into a new Task, or new Task will be escaped from the current host Task and be @@ -927,4 +937,31 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen public boolean isActivityEmbedded(@NonNull Activity activity) { return mPresenter.isActivityEmbedded(activity.getActivityToken()); } + + /** + * If the two rules have the same presentation, we can reuse the same {@link SplitContainer} if + * there is any. + */ + private static boolean canReuseContainer(SplitRule rule1, SplitRule rule2) { + if (!isContainerReusableRule(rule1) || !isContainerReusableRule(rule2)) { + return false; + } + return rule1.getSplitRatio() == rule2.getSplitRatio() + && rule1.getLayoutDirection() == rule2.getLayoutDirection(); + } + + /** + * Whether it is ok for other rule to reuse the {@link TaskFragmentContainer} of the given + * rule. + */ + private static boolean isContainerReusableRule(SplitRule rule) { + // We don't expect to reuse the placeholder rule. + if (!(rule instanceof SplitPairRule)) { + return false; + } + final SplitPairRule pairRule = (SplitPairRule) rule; + + // Not reuse if it needs to destroy the existing. + return !pairRule.shouldClearTop(); + } } diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationAdapter.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationAdapter.java index 89d7a407e459..b3becad3dc5a 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationAdapter.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationAdapter.java @@ -33,6 +33,12 @@ import androidx.annotation.NonNull; * The base adapter can be used for {@link RemoteAnimationTarget} that is simple open/close. */ class TaskFragmentAnimationAdapter { + + /** + * If {@link #mOverrideLayer} is set to this value, we don't want to override the surface layer. + */ + private static final int LAYER_NO_OVERRIDE = -1; + final Animation mAnimation; final RemoteAnimationTarget mTarget; final SurfaceControl mLeash; @@ -42,6 +48,7 @@ class TaskFragmentAnimationAdapter { final float[] mVecs = new float[4]; final Rect mRect = new Rect(); private boolean mIsFirstFrame = true; + private int mOverrideLayer = LAYER_NO_OVERRIDE; TaskFragmentAnimationAdapter(@NonNull Animation animation, @NonNull RemoteAnimationTarget target) { @@ -58,10 +65,21 @@ class TaskFragmentAnimationAdapter { mLeash = leash; } + /** + * Surface layer to be set at the first frame of the animation. We will not set the layer if it + * is set to {@link #LAYER_NO_OVERRIDE}. + */ + final void overrideLayer(int layer) { + mOverrideLayer = layer; + } + /** Called on frame update. */ final void onAnimationUpdate(@NonNull SurfaceControl.Transaction t, long currentPlayTime) { if (mIsFirstFrame) { t.show(mLeash); + if (mOverrideLayer != LAYER_NO_OVERRIDE) { + t.setLayer(mLeash, mOverrideLayer); + } mIsFirstFrame = false; } diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationRunner.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationRunner.java index 46bdf6d0e689..1ac33173668b 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationRunner.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationRunner.java @@ -25,6 +25,7 @@ import static android.view.WindowManager.TRANSIT_OLD_TASK_FRAGMENT_CHANGE; import static android.view.WindowManager.TRANSIT_OLD_TASK_FRAGMENT_CLOSE; import static android.view.WindowManager.TRANSIT_OLD_TASK_FRAGMENT_OPEN; import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN; +import static android.view.WindowManagerPolicyConstants.TYPE_LAYER_OFFSET; import android.animation.Animator; import android.animation.ValueAnimator; @@ -181,18 +182,22 @@ class TaskFragmentAnimationRunner extends IRemoteAnimationRunner.Stub { private List<TaskFragmentAnimationAdapter> createOpenAnimationAdapters( @NonNull RemoteAnimationTarget[] targets) { - return createOpenCloseAnimationAdapters(targets, + return createOpenCloseAnimationAdapters(targets, true /* isOpening */, mAnimationSpec::loadOpenAnimation); } private List<TaskFragmentAnimationAdapter> createCloseAnimationAdapters( @NonNull RemoteAnimationTarget[] targets) { - return createOpenCloseAnimationAdapters(targets, + return createOpenCloseAnimationAdapters(targets, false /* isOpening */, mAnimationSpec::loadCloseAnimation); } + /** + * Creates {@link TaskFragmentAnimationAdapter} for OPEN and CLOSE types of transition. + * @param isOpening {@code true} for OPEN type, {@code false} for CLOSE type. + */ private List<TaskFragmentAnimationAdapter> createOpenCloseAnimationAdapters( - @NonNull RemoteAnimationTarget[] targets, + @NonNull RemoteAnimationTarget[] targets, boolean isOpening, @NonNull BiFunction<RemoteAnimationTarget, Rect, Animation> animationProvider) { // We need to know if the target window is only a partial of the whole animation screen. // If so, we will need to adjust it to make the whole animation screen looks like one. @@ -210,14 +215,25 @@ class TaskFragmentAnimationRunner extends IRemoteAnimationRunner.Stub { } } + // For OPEN transition, open windows should be above close windows. + // For CLOSE transition, open windows should be below close windows. + int offsetLayer = TYPE_LAYER_OFFSET; final List<TaskFragmentAnimationAdapter> adapters = new ArrayList<>(); for (RemoteAnimationTarget target : openingTargets) { - adapters.add(createOpenCloseAnimationAdapter(target, animationProvider, - openingWholeScreenBounds)); + final TaskFragmentAnimationAdapter adapter = createOpenCloseAnimationAdapter(target, + animationProvider, openingWholeScreenBounds); + if (isOpening) { + adapter.overrideLayer(offsetLayer++); + } + adapters.add(adapter); } for (RemoteAnimationTarget target : closingTargets) { - adapters.add(createOpenCloseAnimationAdapter(target, animationProvider, - closingWholeScreenBounds)); + final TaskFragmentAnimationAdapter adapter = createOpenCloseAnimationAdapter(target, + animationProvider, closingWholeScreenBounds); + if (!isOpening) { + adapter.overrideLayer(offsetLayer++); + } + adapters.add(adapter); } return adapters; } diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java index fe9ce971d4d9..ee8cb48e3c4c 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/layout/WindowLayoutComponentImpl.java @@ -18,22 +18,24 @@ package androidx.window.extensions.layout; import static android.view.Display.DEFAULT_DISPLAY; -import static androidx.window.common.DisplayFeature.COMMON_STATE_FLAT; -import static androidx.window.common.DisplayFeature.COMMON_STATE_HALF_OPENED; +import static androidx.window.common.CommonFoldingFeature.COMMON_STATE_FLAT; +import static androidx.window.common.CommonFoldingFeature.COMMON_STATE_HALF_OPENED; import static androidx.window.util.ExtensionHelper.rotateRectToDisplayRotation; import static androidx.window.util.ExtensionHelper.transformToWindowSpaceRect; import android.annotation.Nullable; import android.app.Activity; +import android.app.Application; import android.content.Context; import android.graphics.Rect; +import android.os.Bundle; +import android.os.IBinder; import android.util.Log; import androidx.annotation.NonNull; -import androidx.window.common.DeviceStateManagerPostureProducer; -import androidx.window.common.DisplayFeature; -import androidx.window.common.ResourceConfigDisplayFeatureProducer; -import androidx.window.common.SettingsDevicePostureProducer; +import androidx.window.common.CommonFoldingFeature; +import androidx.window.common.DeviceStateManagerFoldingFeatureProducer; +import androidx.window.common.EmptyLifecycleCallbacksAdapter; import androidx.window.common.SettingsDisplayFeatureProducer; import androidx.window.util.DataProducer; import androidx.window.util.PriorityDataProducer; @@ -56,36 +58,27 @@ import java.util.function.Consumer; */ public class WindowLayoutComponentImpl implements WindowLayoutComponent { private static final String TAG = "SampleExtension"; - private static WindowLayoutComponent sInstance; private final Map<Activity, Consumer<WindowLayoutInfo>> mWindowLayoutChangeListeners = new HashMap<>(); - private final SettingsDevicePostureProducer mSettingsDevicePostureProducer; - private final DataProducer<Integer> mDevicePostureProducer; - private final SettingsDisplayFeatureProducer mSettingsDisplayFeatureProducer; - private final DataProducer<List<DisplayFeature>> mDisplayFeatureProducer; + private final DataProducer<List<CommonFoldingFeature>> mFoldingFeatureProducer; public WindowLayoutComponentImpl(Context context) { - mSettingsDevicePostureProducer = new SettingsDevicePostureProducer(context); - mDevicePostureProducer = new PriorityDataProducer<>(List.of( - mSettingsDevicePostureProducer, - new DeviceStateManagerPostureProducer(context) - )); - + ((Application) context.getApplicationContext()) + .registerActivityLifecycleCallbacks(new NotifyOnConfigurationChanged()); mSettingsDisplayFeatureProducer = new SettingsDisplayFeatureProducer(context); - mDisplayFeatureProducer = new PriorityDataProducer<>(List.of( + mFoldingFeatureProducer = new PriorityDataProducer<>(List.of( mSettingsDisplayFeatureProducer, - new ResourceConfigDisplayFeatureProducer(context) + new DeviceStateManagerFoldingFeatureProducer(context) )); - - mDevicePostureProducer.addDataChangedCallback(this::onDisplayFeaturesChanged); - mDisplayFeatureProducer.addDataChangedCallback(this::onDisplayFeaturesChanged); + mFoldingFeatureProducer.addDataChangedCallback(this::onDisplayFeaturesChanged); } /** * Adds a listener interested in receiving updates to {@link WindowLayoutInfo} + * * @param activity hosting a {@link android.view.Window} * @param consumer interested in receiving updates to {@link WindowLayoutInfo} */ @@ -97,6 +90,7 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent { /** * Removes a listener no longer interested in receiving updates. + * * @param consumer no longer interested in receiving updates to {@link WindowLayoutInfo} */ public void removeWindowLayoutInfoListener( @@ -118,43 +112,34 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent { return mWindowLayoutChangeListeners.keySet(); } - protected boolean hasListeners() { - return !mWindowLayoutChangeListeners.isEmpty(); + @NonNull + private Boolean isListeningForLayoutChanges(IBinder token) { + for (Activity activity: getActivitiesListeningForLayoutChanges()) { + if (token.equals(activity.getWindow().getAttributes().token)) { + return true; + } + } + return false; } - /** - * Calculate the {@link DisplayFeature.State} from the feature or the device posture producer. - * If the given {@link DisplayFeature.State} is not valid then {@code null} will be returned. - * The {@link FoldingFeature} should be ignored in the case of an invalid - * {@link DisplayFeature.State}. - * - * @param feature a {@link DisplayFeature} to provide the feature state if present. - * @return {@link DisplayFeature.State} of the hinge if present or the state from the posture - * produce if present. - */ - @Nullable - private Integer getFeatureState(DisplayFeature feature) { - Integer featureState = feature.getState(); - Optional<Integer> posture = mDevicePostureProducer.getData(); - Integer state = featureState == null ? posture.orElse(null) : featureState; - return convertToExtensionState(state); + protected boolean hasListeners() { + return !mWindowLayoutChangeListeners.isEmpty(); } /** * A convenience method to translate from the common feature state to the extensions feature - * state. More specifically, translates from {@link DisplayFeature.State} to + * state. More specifically, translates from {@link CommonFoldingFeature.State} to * {@link FoldingFeature.STATE_FLAT} or {@link FoldingFeature.STATE_HALF_OPENED}. If it is not * possible to translate, then we will return a {@code null} value. * - * @param state if it matches a value in {@link DisplayFeature.State}, {@code null} otherwise. - * @return a {@link FoldingFeature.STATE_FLAT} or {@link FoldingFeature.STATE_HALF_OPENED} if - * the given state matches a value in {@link DisplayFeature.State} and {@code null} otherwise. + * @param state if it matches a value in {@link CommonFoldingFeature.State}, {@code null} + * otherwise. @return a {@link FoldingFeature.STATE_FLAT} or + * {@link FoldingFeature.STATE_HALF_OPENED} if the given state matches a value in + * {@link CommonFoldingFeature.State} and {@code null} otherwise. */ @Nullable - private Integer convertToExtensionState(@Nullable Integer state) { - if (state == null) { // The null check avoids a NullPointerException. - return null; - } else if (state == COMMON_STATE_FLAT) { + private Integer convertToExtensionState(int state) { + if (state == COMMON_STATE_FLAT) { return FoldingFeature.STATE_FLAT; } else if (state == COMMON_STATE_HALF_OPENED) { return FoldingFeature.STATE_HALF_OPENED; @@ -172,33 +157,30 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent { @NonNull private WindowLayoutInfo getWindowLayoutInfo(@NonNull Activity activity) { - List<androidx.window.extensions.layout.DisplayFeature> displayFeatures = - getDisplayFeatures(activity); + List<DisplayFeature> displayFeatures = getDisplayFeatures(activity); return new WindowLayoutInfo(displayFeatures); } /** - * Translate from the {@link DisplayFeature} to - * {@link androidx.window.extensions.layout.DisplayFeature} for a given {@link Activity}. If a - * {@link DisplayFeature} is not valid then it will be omitted. + * Translate from the {@link CommonFoldingFeature} to + * {@link DisplayFeature} for a given {@link Activity}. If a + * {@link CommonFoldingFeature} is not valid then it will be omitted. * * For a {@link FoldingFeature} the bounds are localized into the {@link Activity} window - * coordinate space and the state is calculated either from {@link DisplayFeature#getState()} or - * {@link #mDisplayFeatureProducer}. The state from {@link #mDisplayFeatureProducer} may not be - * valid since {@link #mDisplayFeatureProducer} is a general state controller. If the state is - * not valid, the {@link FoldingFeature} is omitted from the {@link List} of - * {@link androidx.window.extensions.layout.DisplayFeature}. If the bounds are not valid, - * constructing a {@link FoldingFeature} will throw an {@link IllegalArgumentException} since - * this can cause negative UI effects down stream. + * coordinate space and the state is calculated from {@link CommonFoldingFeature#getState()}. + * The state from {@link #mFoldingFeatureProducer} may not be valid since + * {@link #mFoldingFeatureProducer} is a general state controller. If the state is not valid, + * the {@link FoldingFeature} is omitted from the {@link List} of {@link DisplayFeature}. If + * the bounds are not valid, constructing a {@link FoldingFeature} will throw an + * {@link IllegalArgumentException} since this can cause negative UI effects down stream. * * @param activity a proxy for the {@link android.view.Window} that contains the - * {@link androidx.window.extensions.layout.DisplayFeature}. - * @return a {@link List} of valid {@link androidx.window.extensions.layout.DisplayFeature} that + * {@link DisplayFeature}. + * @return a {@link List} of valid {@link DisplayFeature} that * are within the {@link android.view.Window} of the {@link Activity} */ - private List<androidx.window.extensions.layout.DisplayFeature> getDisplayFeatures( - @NonNull Activity activity) { - List<androidx.window.extensions.layout.DisplayFeature> features = new ArrayList<>(); + private List<DisplayFeature> getDisplayFeatures(@NonNull Activity activity) { + List<DisplayFeature> features = new ArrayList<>(); int displayId = activity.getDisplay().getDisplayId(); if (displayId != DEFAULT_DISPLAY) { Log.w(TAG, "This sample doesn't support display features on secondary displays"); @@ -211,11 +193,10 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent { return features; } - Optional<List<DisplayFeature>> storedFeatures = mDisplayFeatureProducer.getData(); + Optional<List<CommonFoldingFeature>> storedFeatures = mFoldingFeatureProducer.getData(); if (storedFeatures.isPresent()) { - - for (DisplayFeature baseFeature : storedFeatures.get()) { - Integer state = getFeatureState(baseFeature); + for (CommonFoldingFeature baseFeature : storedFeatures.get()) { + Integer state = convertToExtensionState(baseFeature.getState()); if (state == null) { continue; } @@ -223,8 +204,7 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent { rotateRectToDisplayRotation(displayId, featureRect); transformToWindowSpaceRect(activity, featureRect); - features.add(new FoldingFeature(featureRect, baseFeature.getType(), - getFeatureState(baseFeature))); + features.add(new FoldingFeature(featureRect, baseFeature.getType(), state)); } } return features; @@ -232,13 +212,31 @@ public class WindowLayoutComponentImpl implements WindowLayoutComponent { private void updateRegistrations() { if (hasListeners()) { - mSettingsDevicePostureProducer.registerObserversIfNeeded(); mSettingsDisplayFeatureProducer.registerObserversIfNeeded(); } else { - mSettingsDevicePostureProducer.unregisterObserversIfNeeded(); mSettingsDisplayFeatureProducer.unregisterObserversIfNeeded(); } - onDisplayFeaturesChanged(); } + + private final class NotifyOnConfigurationChanged extends EmptyLifecycleCallbacksAdapter { + @Override + public void onActivityCreated(Activity activity, Bundle savedInstanceState) { + super.onActivityCreated(activity, savedInstanceState); + onDisplayFeaturesChangedIfListening(activity); + } + + @Override + public void onActivityConfigurationChanged(Activity activity) { + super.onActivityConfigurationChanged(activity); + onDisplayFeaturesChangedIfListening(activity); + } + + private void onDisplayFeaturesChangedIfListening(Activity activity) { + IBinder token = activity.getWindow().getAttributes().token; + if (token == null || isListeningForLayoutChanges(token)) { + onDisplayFeaturesChanged(); + } + } + } } diff --git a/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SampleSidecarImpl.java b/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SampleSidecarImpl.java index aa949f126154..c7b709347060 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SampleSidecarImpl.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/sidecar/SampleSidecarImpl.java @@ -23,16 +23,17 @@ import static androidx.window.util.ExtensionHelper.transformToWindowSpaceRect; import android.app.Activity; import android.app.ActivityThread; +import android.app.Application; import android.content.Context; import android.graphics.Rect; +import android.os.Bundle; import android.os.IBinder; import android.util.Log; import androidx.annotation.NonNull; -import androidx.window.common.DeviceStateManagerPostureProducer; -import androidx.window.common.DisplayFeature; -import androidx.window.common.ResourceConfigDisplayFeatureProducer; -import androidx.window.common.SettingsDevicePostureProducer; +import androidx.window.common.CommonFoldingFeature; +import androidx.window.common.DeviceStateManagerFoldingFeatureProducer; +import androidx.window.common.EmptyLifecycleCallbacksAdapter; import androidx.window.common.SettingsDisplayFeatureProducer; import androidx.window.util.DataProducer; import androidx.window.util.PriorityDataProducer; @@ -48,36 +49,25 @@ import java.util.Optional; */ class SampleSidecarImpl extends StubSidecar { private static final String TAG = "SampleSidecar"; - private static final boolean DEBUG = false; - private final SettingsDevicePostureProducer mSettingsDevicePostureProducer; - private final DataProducer<Integer> mDevicePostureProducer; + private final DataProducer<List<CommonFoldingFeature>> mFoldingFeatureProducer; - private final SettingsDisplayFeatureProducer mSettingsDisplayFeatureProducer; - private final DataProducer<List<DisplayFeature>> mDisplayFeatureProducer; + private final SettingsDisplayFeatureProducer mSettingsFoldingFeatureProducer; SampleSidecarImpl(Context context) { - mSettingsDevicePostureProducer = new SettingsDevicePostureProducer(context); - mDevicePostureProducer = new PriorityDataProducer<>(List.of( - mSettingsDevicePostureProducer, - new DeviceStateManagerPostureProducer(context) + ((Application) context.getApplicationContext()) + .registerActivityLifecycleCallbacks(new NotifyOnConfigurationChanged()); + mSettingsFoldingFeatureProducer = new SettingsDisplayFeatureProducer(context); + mFoldingFeatureProducer = new PriorityDataProducer<>(List.of( + mSettingsFoldingFeatureProducer, + new DeviceStateManagerFoldingFeatureProducer(context) )); - mSettingsDisplayFeatureProducer = new SettingsDisplayFeatureProducer(context); - mDisplayFeatureProducer = new PriorityDataProducer<>(List.of( - mSettingsDisplayFeatureProducer, - new ResourceConfigDisplayFeatureProducer(context) - )); - - mDevicePostureProducer.addDataChangedCallback(this::onDevicePostureChanged); - mDisplayFeatureProducer.addDataChangedCallback(this::onDisplayFeaturesChanged); - } - - private void onDevicePostureChanged() { - updateDeviceState(getDeviceState()); + mFoldingFeatureProducer.addDataChangedCallback(this::onDisplayFeaturesChanged); } private void onDisplayFeaturesChanged() { + updateDeviceState(getDeviceState()); for (IBinder windowToken : getWindowsListeningForLayoutChanges()) { SidecarWindowLayoutInfo newLayout = getWindowLayoutInfo(windowToken); updateWindowLayout(windowToken, newLayout); @@ -87,27 +77,21 @@ class SampleSidecarImpl extends StubSidecar { @NonNull @Override public SidecarDeviceState getDeviceState() { - Optional<Integer> posture = mDevicePostureProducer.getData(); - SidecarDeviceState deviceState = new SidecarDeviceState(); - deviceState.posture = posture.orElse(deviceStateFromFeature()); + deviceState.posture = deviceStateFromFeature(); return deviceState; } private int deviceStateFromFeature() { - List<DisplayFeature> storedFeatures = mDisplayFeatureProducer.getData() + List<CommonFoldingFeature> storedFeatures = mFoldingFeatureProducer.getData() .orElse(Collections.emptyList()); for (int i = 0; i < storedFeatures.size(); i++) { - DisplayFeature feature = storedFeatures.get(i); - final int state = feature.getState() == null ? -1 : feature.getState(); - if (DEBUG && feature.getState() == null) { - Log.d(TAG, "feature#getState was null for DisplayFeature: " + feature); - } - + CommonFoldingFeature feature = storedFeatures.get(i); + final int state = feature.getState(); switch (state) { - case DisplayFeature.COMMON_STATE_FLAT: + case CommonFoldingFeature.COMMON_STATE_FLAT: return SidecarDeviceState.POSTURE_OPENED; - case DisplayFeature.COMMON_STATE_HALF_OPENED: + case CommonFoldingFeature.COMMON_STATE_HALF_OPENED: return SidecarDeviceState.POSTURE_HALF_OPENED; } } @@ -127,22 +111,22 @@ class SampleSidecarImpl extends StubSidecar { } private List<SidecarDisplayFeature> getDisplayFeatures(@NonNull Activity activity) { - List<SidecarDisplayFeature> features = new ArrayList<SidecarDisplayFeature>(); int displayId = activity.getDisplay().getDisplayId(); if (displayId != DEFAULT_DISPLAY) { Log.w(TAG, "This sample doesn't support display features on secondary displays"); - return features; + return Collections.emptyList(); } if (activity.isInMultiWindowMode()) { // It is recommended not to report any display features in multi-window mode, since it // won't be possible to synchronize the display feature positions with window movement. - return features; + return Collections.emptyList(); } - Optional<List<DisplayFeature>> storedFeatures = mDisplayFeatureProducer.getData(); + Optional<List<CommonFoldingFeature>> storedFeatures = mFoldingFeatureProducer.getData(); + List<SidecarDisplayFeature> features = new ArrayList<>(); if (storedFeatures.isPresent()) { - for (DisplayFeature baseFeature : storedFeatures.get()) { + for (CommonFoldingFeature baseFeature : storedFeatures.get()) { SidecarDisplayFeature feature = new SidecarDisplayFeature(); Rect featureRect = baseFeature.getRect(); rotateRectToDisplayRotation(displayId, featureRect); @@ -152,17 +136,37 @@ class SampleSidecarImpl extends StubSidecar { features.add(feature); } } - return features; + return Collections.unmodifiableList(features); } @Override protected void onListenersChanged() { if (hasListeners()) { - mSettingsDevicePostureProducer.registerObserversIfNeeded(); - mSettingsDisplayFeatureProducer.registerObserversIfNeeded(); + mSettingsFoldingFeatureProducer.registerObserversIfNeeded(); + onDisplayFeaturesChanged(); } else { - mSettingsDevicePostureProducer.unregisterObserversIfNeeded(); - mSettingsDisplayFeatureProducer.unregisterObserversIfNeeded(); + mSettingsFoldingFeatureProducer.unregisterObserversIfNeeded(); + } + } + + private final class NotifyOnConfigurationChanged extends EmptyLifecycleCallbacksAdapter { + @Override + public void onActivityCreated(Activity activity, Bundle savedInstanceState) { + super.onActivityCreated(activity, savedInstanceState); + onDisplayFeaturesChangedForActivity(activity); + } + + @Override + public void onActivityConfigurationChanged(Activity activity) { + super.onActivityConfigurationChanged(activity); + onDisplayFeaturesChangedForActivity(activity); + } + + private void onDisplayFeaturesChangedForActivity(@NonNull Activity activity) { + IBinder token = activity.getWindow().getAttributes().token; + if (token == null || mWindowLayoutChangeListenerTokens.contains(token)) { + onDisplayFeaturesChanged(); + } } } } diff --git a/libs/WindowManager/Jetpack/src/androidx/window/sidecar/StubSidecar.java b/libs/WindowManager/Jetpack/src/androidx/window/sidecar/StubSidecar.java index 199c37315c07..b9c808a6569b 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/sidecar/StubSidecar.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/sidecar/StubSidecar.java @@ -30,7 +30,7 @@ import java.util.Set; abstract class StubSidecar implements SidecarInterface { private SidecarCallback mSidecarCallback; - private final Set<IBinder> mWindowLayoutChangeListenerTokens = new HashSet<>(); + final Set<IBinder> mWindowLayoutChangeListenerTokens = new HashSet<>(); private boolean mDeviceStateChangeListenerRegistered; StubSidecar() { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java index fd3be2b11c15..f98849260511 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java @@ -103,7 +103,7 @@ public class DragLayout extends LinearLayout { MATCH_PARENT)); ((LayoutParams) mDropZoneView1.getLayoutParams()).weight = 1; ((LayoutParams) mDropZoneView2.getLayoutParams()).weight = 1; - updateContainerMargins(); + updateContainerMargins(getResources().getConfiguration().orientation); } @Override @@ -128,20 +128,18 @@ public class DragLayout extends LinearLayout { } public void onConfigChanged(Configuration newConfig) { - final int orientation = getResources().getConfiguration().orientation; - if (orientation == Configuration.ORIENTATION_LANDSCAPE + if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE && getOrientation() != HORIZONTAL) { setOrientation(LinearLayout.HORIZONTAL); - updateContainerMargins(); - } else if (orientation == Configuration.ORIENTATION_PORTRAIT + updateContainerMargins(newConfig.orientation); + } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT && getOrientation() != VERTICAL) { setOrientation(LinearLayout.VERTICAL); - updateContainerMargins(); + updateContainerMargins(newConfig.orientation); } } - private void updateContainerMargins() { - final int orientation = getResources().getConfiguration().orientation; + private void updateContainerMargins(int orientation) { final float halfMargin = mDisplayMargin / 2f; if (orientation == Configuration.ORIENTATION_LANDSCAPE) { mDropZoneView1.setContainerMargin( diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java index 8b87df44c52c..4c77f6a7e00d 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java @@ -134,6 +134,9 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, private final Provider<Optional<StageTaskUnfoldController>> mUnfoldControllerProvider; private StageCoordinator mStageCoordinator; + // Only used for the legacy recents animation from splitscreen to allow the tasks to be animated + // outside the bounds of the roots by being reparented into a higher level fullscreen container + private SurfaceControl mSplitTasksContainerLayer; public SplitScreenController(ShellTaskOrganizer shellTaskOrganizer, SyncTransactionQueue syncQueue, Context context, @@ -364,20 +367,24 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, RemoteAnimationTarget[] onGoingToRecentsLegacy(boolean cancel, RemoteAnimationTarget[] apps) { if (apps.length < 2) return null; + SurfaceControl.Transaction transaction = new SurfaceControl.Transaction(); + if (mSplitTasksContainerLayer != null) { + // Remove the previous layer before recreating + transaction.remove(mSplitTasksContainerLayer); + } final SurfaceControl.Builder builder = new SurfaceControl.Builder(new SurfaceSession()) .setContainerLayer() .setName("RecentsAnimationSplitTasks") .setHidden(false) .setCallsite("SplitScreenController#onGoingtoRecentsLegacy"); mRootTDAOrganizer.attachToDisplayArea(DEFAULT_DISPLAY, builder); - SurfaceControl sc = builder.build(); - SurfaceControl.Transaction transaction = new SurfaceControl.Transaction(); + mSplitTasksContainerLayer = builder.build(); // Ensure that we order these in the parent in the right z-order as their previous order Arrays.sort(apps, (a1, a2) -> a1.prefixOrderIndex - a2.prefixOrderIndex); int layer = 1; for (RemoteAnimationTarget appTarget : apps) { - transaction.reparent(appTarget.leash, sc); + transaction.reparent(appTarget.leash, mSplitTasksContainerLayer); transaction.setPosition(appTarget.leash, appTarget.screenSpaceBounds.left, appTarget.screenSpaceBounds.top); transaction.setLayer(appTarget.leash, layer++); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java index 5d1d159e63e6..38c1aff0a62c 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java @@ -365,8 +365,10 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, void startTasksWithLegacyTransition(int mainTaskId, @Nullable Bundle mainOptions, int sideTaskId, @Nullable Bundle sideOptions, @SplitPosition int sidePosition, float splitRatio, RemoteAnimationAdapter adapter) { + // Ensure divider is invisible before transition. + setDividerVisibility(false /* visible */); // Init divider first to make divider leash for remote animation target. - setDividerVisibility(true /* visible */); + mSplitLayout.init(); // Set false to avoid record new bounds with old task still on top; mShouldUpdateRecents = false; final WindowContainerTransaction wct = new WindowContainerTransaction(); @@ -396,6 +398,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, public void onAnimationFinished() throws RemoteException { mIsDividerRemoteAnimating = false; mShouldUpdateRecents = true; + setDividerVisibility(true /* visible */); mSyncQueue.queue(evictWct); mSyncQueue.runInSync(t -> applyDividerVisibility(t)); finishedCallback.onAnimationFinished(); @@ -420,6 +423,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler, public void onAnimationCancelled() { mIsDividerRemoteAnimating = false; mShouldUpdateRecents = true; + setDividerVisibility(true /* visible */); mSyncQueue.queue(evictWct); mSyncQueue.runInSync(t -> applyDividerVisibility(t)); try { diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp index 0e4a1f945b85..99fd463b0660 100644 --- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp +++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp @@ -74,7 +74,15 @@ bool SkiaVulkanPipeline::draw(const Frame& frame, const SkRect& screenDirty, con if (backBuffer.get() == nullptr) { return false; } - LightingInfo::updateLighting(lightGeometry, lightInfo); + + // update the coordinates of the global light position based on surface rotation + SkPoint lightCenter = mVkSurface->getCurrentPreTransform().mapXY(lightGeometry.center.x, + lightGeometry.center.y); + LightGeometry localGeometry = lightGeometry; + localGeometry.center.x = lightCenter.fX; + localGeometry.center.y = lightCenter.fY; + + LightingInfo::updateLighting(localGeometry, lightInfo); renderFrame(*layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, backBuffer, mVkSurface->getCurrentPreTransform()); diff --git a/packages/BackupRestoreConfirmation/res/values-af/strings.xml b/packages/BackupRestoreConfirmation/res/values-af/strings.xml index 0bf54cf99418..06a1af86bdd3 100644 --- a/packages/BackupRestoreConfirmation/res/values-af/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-af/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"Voer jou toestelenkripsie-wagwoord hier onder in. Dit sal ook gebruik word om die rugsteunargief te enkripteer."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"Voer asb. \'n wagwoord in om te gebruik vir enkripsie van die volle rugsteundata. As dit leeg gelaat word, sal jou huidige rugsteunwagwoord gebruik word:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"As jy die volle rugsteundata wil enkripteer, voer \'n wagwoord hieronder in:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"Omdat jou toestel geënkripteer is, word daar van jou vereis om jou rugsteun te enkripteer. Voer \'n wagwoord hieronder in:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"As die hersteldata geïnkripteer word, voer asb. die wagwoord hieronder in:"</string> <string name="toast_backup_started" msgid="550354281452756121">"Rugsteun begin tans..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"Rugsteun klaar"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-am/strings.xml b/packages/BackupRestoreConfirmation/res/values-am/strings.xml index ec5b9631229c..7077b39f0d41 100644 --- a/packages/BackupRestoreConfirmation/res/values-am/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-am/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"እባክህ የመሳሪያህ ምስጠራ የይለፍ ቃል ከታች አስገባ፡፡ይሄ ለምትኬ መዝገብ ለመመስጠርም ይጠቅማል፡፡"</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"እባክዎ የሙሉ ውሂብ መጠበቂያ ማመስጠር ለመጠቅም የይለፍ ቃል ያስገቡ። ይህም ባዶ ከሆነ፣ የእርስዎ የአሁኑ የመጠበቂያ ይለፍ ቃል ይወሰዳል፡"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"ሙሉ የውሂብ መጠበቂያ ለማመስጠር ከፈለጉ ከታች የይለፍ ቃል ያስገቡ፡"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"መሣሪያዎ የተመሰጠረ እንደመሆኑ መጠን ምትኬዎን ማመስጠር አለብዎት። እባክዎ የይለፍ ቃል ከታች ያስገቡ፦"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"ውሂብ እነበረበት መልስ የተመሳጠረ ከሆነ፣ እባክዎ ከታች የይለፍ ቃል ያስገቡ"</string> <string name="toast_backup_started" msgid="550354281452756121">"መጠባበቂያ በመጀመር ላይ..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"መጠባበቂያ ጨርሷል"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-ar/strings.xml b/packages/BackupRestoreConfirmation/res/values-ar/strings.xml index 2a3ddb243a80..810b1e7a4754 100644 --- a/packages/BackupRestoreConfirmation/res/values-ar/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-ar/strings.xml @@ -25,11 +25,12 @@ <string name="allow_restore_button_label" msgid="3081286752277127827">"استرداد بياناتي"</string> <string name="deny_restore_button_label" msgid="1724367334453104378">"عدم الاسترداد"</string> <string name="current_password_text" msgid="8268189555578298067">"يُرجى إدخال كلمة مرور النسخ الاحتياطي أدناه:"</string> - <string name="device_encryption_restore_text" msgid="1570864916855208992">"يُرجى إدخال كلمة مرور ترميز جهازك أدناه."</string> - <string name="device_encryption_backup_text" msgid="5866590762672844664">"يُرجى إدخال كلمة مرور ترميز الجهاز. سيتم استخدام ذلك أيضًا لترميز أرشيف النسخ الاحتياطي."</string> + <string name="device_encryption_restore_text" msgid="1570864916855208992">"يُرجى إدخال كلمة مرور تشفير جهازك أدناه."</string> + <string name="device_encryption_backup_text" msgid="5866590762672844664">"يُرجى إدخال كلمة مرور تشفير الجهاز. سيتم استخدام ذلك أيضًا لتشفير أرشيف النسخ الاحتياطي."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"يُرجى إدخال كلمة المرور للاستخدام لتشفير بيانات النسخة الاحتياطية بالكامل. إذا تم ترك هذا فارغًا، فسيتم استخدام كلمة مرور النسخ الاحتياطي الحالية:"</string> - <string name="backup_enc_password_optional" msgid="1350137345907579306">"إذا كنت ترغب في ترميز بيانات النسخة الاحتياطية بالكامل، فأدخل كلمة المرور أدناه:"</string> - <string name="restore_enc_password_text" msgid="6140898525580710823">"إذا كانت بيانات الاسترداد مشفرة، يُرجى إدخال كلمة المرور أدناه:"</string> + <string name="backup_enc_password_optional" msgid="1350137345907579306">"إذا كنت ترغب في تشفير بيانات النسخة الاحتياطية بالكامل، فأدخل كلمة المرور أدناه:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"نظرًا لكون جهازك مشفرًا، أنت مطالب بتشفير النسخة الاحتياطية. يُرجى إدخال كلمة المرور أدناه:"</string> + <string name="restore_enc_password_text" msgid="6140898525580710823">"إذا كانت بيانات الاسترداد مشفرة، فالرجاء إدخال كلمة المرور أدناه:"</string> <string name="toast_backup_started" msgid="550354281452756121">"جارٍ بدء النسخ الاحتياطي..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"انتهت عملية النسخ الاحتياطي"</string> <string name="toast_restore_started" msgid="7881679218971277385">"جارٍ بدء الاستعادة..."</string> diff --git a/packages/BackupRestoreConfirmation/res/values-as/strings.xml b/packages/BackupRestoreConfirmation/res/values-as/strings.xml index e7c0db0b62e9..76ec60b166a8 100644 --- a/packages/BackupRestoreConfirmation/res/values-as/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-as/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"অনুগ্ৰহ কৰি তলত আপোনাৰ ডিভাইচৰ এনক্ৰিপশ্বন পাছৱৰ্ডটো দিয়ক৷ এই পাছৱৰ্ডটো বেকআপ কাৰ্যৰ আৰ্কাইভ কৰিবলৈও ব্যৱহাৰ কৰা হ\'ব৷"</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"সম্পূৰ্ণৰূপে বেকআপ লোৱা ডেটা এনক্ৰিপ্ট কৰিবলৈ অনুগ্ৰহ কৰি এটা পাছৱৰ্ড দিয়ক। এই ঠাইটো খালী ৰাখিলে আপোনাৰ বৰ্তমানৰ বেকআপ পাছৱৰ্ডটো ব্যৱহাৰ কৰা হ\'ব:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"যদি আপুনি সম্পূৰ্ণ বেকআপ ডেটা এনক্ৰিপ্ট কৰিব বিচাৰিছে, তেতিয়াহ\'লে তলত পাছৱৰ্ড এটা দিয়ক:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"যিহেতু আপোনাৰ ডিভাইচটো এনক্ৰিপ্ট কৰা হৈছে, আপুনি আপোনাৰ বেকআপ এনক্ৰিপ্ট কৰাৰ প্ৰয়োজন। অনুগ্ৰহ কৰি তলত এটা পাছৱৰ্ড দিয়ক:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"যদি পুনঃস্থাপন কৰিবলগীয়া ডেটা এনক্ৰিপ্ট কৰা আছে, তেন্তে তলত পাছৱৰ্ড দিয়ক:"</string> <string name="toast_backup_started" msgid="550354281452756121">"বেকআপ লোৱা কাৰ্য আৰম্ভ কৰি আছে..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"বেকআপ লোৱা সম্পূৰ্ণ হ’ল"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-az/strings.xml b/packages/BackupRestoreConfirmation/res/values-az/strings.xml index 1f9e6aae56ba..3194baefd4c6 100644 --- a/packages/BackupRestoreConfirmation/res/values-az/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-az/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"Lütfən, aşağıda cihaz şifrələmə parolunuzu daxil edin. Bu yedək arxivini şifrələmək üçün də istifadə olunacaq."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"Tam yedək data şifrələmədən istifadə üçün şifrə daxil edin. Əgər boş buraxılsa, cari yedək şifrə istifadə olunacaq:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"Bütün yedək datanı şifrələmək istəyirsinizsə, aşağıda parol daxil edin:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"Cihazınız şifrələndiyi üçün yedəyinizi şifrələmək tələb olunur. Aşağıda parolu daxil etməyiniz xahiş olunur:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"Bərpa məlumatları şifrələnibsə, şifrəni aşağıda daxil edin:"</string> <string name="toast_backup_started" msgid="550354281452756121">"Rezerv edilir ..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"Yedəkləmə sona çatdı"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-b+sr+Latn/strings.xml b/packages/BackupRestoreConfirmation/res/values-b+sr+Latn/strings.xml index ab551201771c..c46ff49aec4d 100644 --- a/packages/BackupRestoreConfirmation/res/values-b+sr+Latn/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-b+sr+Latn/strings.xml @@ -18,10 +18,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="backup_confirm_title" msgid="827563724209303345">"Rezervna kopije svih podataka"</string> <string name="restore_confirm_title" msgid="5469365809567486602">"Potpuno vraćanje"</string> - <string name="backup_confirm_text" msgid="1878021282758896593">"Zahtevana je potpuna rezervna kopija svih podataka na povezani računar. Da li želite da dozvolite to?\n\nAko niste lično zahtevali rezervnu kopiju, ne dozvoljavajte nastavak radnje."</string> + <string name="backup_confirm_text" msgid="1878021282758896593">"Zahtevana je potpuna rezervna kopija svih podataka na povezani stoni računar. Da li želite da dozvolite to?\n\nAko niste lično zahtevali rezervnu kopiju, ne dozvoljavajte nastavak radnje."</string> <string name="allow_backup_button_label" msgid="4217228747769644068">"Napravi rezervnu kopiju mojih podataka"</string> <string name="deny_backup_button_label" msgid="6009119115581097708">"Ne pravi rezervne kopije"</string> - <string name="restore_confirm_text" msgid="7499866728030461776">"Zahtevano je potpuno vraćanje svih podataka sa povezanog računara. Da li želite da dozvolite to?\n\nAko niste lično zahtevali vraćanje, ne dozvoljavajte nastavak radnje. Time ćete zameniti sve podatke koji su trenutno na uređaju!"</string> + <string name="restore_confirm_text" msgid="7499866728030461776">"Zahtevano je potpuno vraćanje svih podataka sa povezanog stonog računara. Da li želite da dozvolite to?\n\nAko niste lično zahtevali vraćanje, ne dozvoljavajte nastavak radnje. Time ćete zameniti sve podatke koji su trenutno na uređaju!"</string> <string name="allow_restore_button_label" msgid="3081286752277127827">"Vrati moje podatke"</string> <string name="deny_restore_button_label" msgid="1724367334453104378">"Ne vraćaj"</string> <string name="current_password_text" msgid="8268189555578298067">"Unesite trenutnu lozinku rezervne kopije u nastavku:"</string> @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"Unesite lozinku uređaja za šifrovanje. Ovo će se koristiti i za šifrovanje rezervne arhive."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"Unesite lozinku koju ćete koristiti za šifrovanje podataka potpune rezervne kopije. Ako to polje ostavite prazno, koristiće se trenutna lozinka rezervne kopije:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"Ako želite da šifrujete podatke potpune rezervne kopije, unesite lozinku u nastavku."</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"Pošto vam je uređaj šifrovan, morate da šifrujete rezervnu kopiju. Unesite lozinku u nastavku:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"Ako su podaci za vraćanje šifrovani, unesite lozinku u nastavku:"</string> <string name="toast_backup_started" msgid="550354281452756121">"Pokretanje pravljenja rezervne kopije..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"Rezervna kopija je napravljena"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-be/strings.xml b/packages/BackupRestoreConfirmation/res/values-be/strings.xml index 188041a08aa5..24662fe53467 100644 --- a/packages/BackupRestoreConfirmation/res/values-be/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-be/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"Увядзіце пароль для расшыфравання прылады. Ён таксама будзе выкарыстоўвацца для расшыфравання рэзервовай копіі."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"Увядзіце пароль, які выкарыстоўваецца для шыфравання ўсіх дадзеных рэзервовага капіявання. Калі гэтае поле пакінуць пустым, будзе выкарыстоўвацца бягучы пароль рэзервовага капіявання:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"Калі вы жадаеце зашыфраваць усе дадзеныя рэзервовага капіявання, увядзіце пароль ніжэй:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"Даныя на вашай прыладзе зашыфраваны, таму вы павінны зашыфраваць рэзервовую копію. Калі ласка, увядзіце пароль ніжэй:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"Калі дадзеныя для аднаўлення зашыфраваныя, увядзіце пароль ніжэй:"</string> <string name="toast_backup_started" msgid="550354281452756121">"Рэзервовае капіяванне..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"Рэзервовае капіяванне скончылася"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-bg/strings.xml b/packages/BackupRestoreConfirmation/res/values-bg/strings.xml index c332774520bb..f1b01e572332 100644 --- a/packages/BackupRestoreConfirmation/res/values-bg/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-bg/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"Моля, въведете паролата си за шифроване на устройството по-долу. Тя ще се използва и за шифроване на резервното копие на архива."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"Моля, въведете парола, която да използвате за шифроване на пълното резервно копие на данните. Ако не е попълнена, ще бъде използвана текущата ви парола за резервно копие:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"Ако искате да шифровате пълното резервно копие на данните, въведете парола по-долу:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"Тъй като устройството ви е шифровано, трябва да направите това и за резервното си копие. Моля, по-долу въведете парола:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"Ако възстановените данни са шифровани, моля, въведете паролата по-долу:"</string> <string name="toast_backup_started" msgid="550354281452756121">"Създаването на резервно копие се стартира..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"Създаването на резервно копие завърши"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-bn/strings.xml b/packages/BackupRestoreConfirmation/res/values-bn/strings.xml index 2f5aae41d7a5..afc8c3eb918f 100644 --- a/packages/BackupRestoreConfirmation/res/values-bn/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-bn/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"অনুগ্রহ করে নিচে আপানার ডিভাইসের এনক্রিপশান পাসওয়ার্ড লিখুন৷ এছাড়াও ব্যাক-আপ আর্কাইভ এনক্রিপ্ট করতে এটি ব্যবহার করা হবে৷"</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"সম্পূর্ণ ব্যাকআপ ডেটা এনক্রিপ্ট করতে দয়া করে একটি পাসওয়ার্ড লিখুন৷ যদি এটি খালি রেখে দেওয়া হয় তবে আপনার বর্তমান ব্যাকআপ পাসওয়ার্ডটি ব্যবহার করা হবে:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"আপনি যদি সম্পূর্ণ ব্যাকআপ ডেটা এনক্রিপ্ট করতে চান তাহলে নিচে একটি পাসওয়ার্ড লিখুন:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"আপনার ডিভাইস এনক্রিপ্ট হয়ে থাকার কারণে আপনার ব্যাকআপকে এনক্রিপ্ট করতে হবে। দয়া করে নিচে একটি পাসওয়ার্ড দিন:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"যদি পুনরুদ্ধার করা ডেটা এনক্রিপ্ট করা থাকে, তবে দয়া করে নিচে পাসওয়ার্ডটি লিখুন:"</string> <string name="toast_backup_started" msgid="550354281452756121">"ব্যাকআপ নেওয়া শুরু হয়েছে..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"ব্যাকআপ নেওয়া সম্পূর্ণ হয়েছে"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-bs/strings.xml b/packages/BackupRestoreConfirmation/res/values-bs/strings.xml index 9edcec0a5c28..bc52b06e3eb8 100644 --- a/packages/BackupRestoreConfirmation/res/values-bs/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-bs/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"Molimo vas unesite svoju lozinku za šifriranje uređaja ispod. Ona će se koristiti i za šifriranje arhive sigurnosnih kopija."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"Unesite lozinku za šifriranje potpune sigurnosne kopije podataka. Ukoliko ne unesete lozinku, primijenit će se vaša trenutna lozinka za sigurnosnu kopiju:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"Ukoliko želite šifrirati potpunu sigurnosnu kopiju podataka, unesite lozinku ispod:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"Pošto je vaš uređaj šifriran, potrebno je šifrirati sigurnosnu kopiju. Unesite šifru ispod:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"Ukoliko su podaci za vraćanje šifrirani, unesite lozinku ispod:"</string> <string name="toast_backup_started" msgid="550354281452756121">"Pravljenje rezervne kopije..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"Pravljenje rezervne kopije završeno"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-ca/strings.xml b/packages/BackupRestoreConfirmation/res/values-ca/strings.xml index 8cf11bc01247..c7c8346a3ede 100644 --- a/packages/BackupRestoreConfirmation/res/values-ca/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-ca/strings.xml @@ -20,7 +20,7 @@ <string name="restore_confirm_title" msgid="5469365809567486602">"Restaura completament"</string> <string name="backup_confirm_text" msgid="1878021282758896593">"S\'ha sol·licitat una còpia de seguretat completa de totes les dades a un equip de sobretaula connectat. Vols permetre que això passi?\n \nSi no has sol·licitat la còpia de seguretat tu mateix, no permetis que continuï l\'operació."</string> <string name="allow_backup_button_label" msgid="4217228747769644068">"Còpia de seguretat de les meves dades"</string> - <string name="deny_backup_button_label" msgid="6009119115581097708">"No facis una còpia de seguretat"</string> + <string name="deny_backup_button_label" msgid="6009119115581097708">"No en facis una còpia de seguretat"</string> <string name="restore_confirm_text" msgid="7499866728030461776">"S\'ha sol·licitat una restauració completa de totes les dades d\'un equip d\'escriptori connectat. Vols permetre que això passi?\n \nSi no has sol·licitat la restauració tu mateix, no permetis que continuï l\'operació. Això reemplaçarà les dades que hi hagi actualment a l\'equip."</string> <string name="allow_restore_button_label" msgid="3081286752277127827">"Restaura les meves dades"</string> <string name="deny_restore_button_label" msgid="1724367334453104378">"No ho restauris"</string> @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"Introdueix la contrasenya d\'encriptació del dispositiu a continuació. També es farà servir per encriptar l\'arxiu de seguretat."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"Introdueix una contrasenya que utilitzaràs per a l\'encriptació de les dades de còpia de la seguretat completa. Si es deixa en blanc, s\'utilitzarà la teva contrasenya de còpia de seguretat actual:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"Si vols xifrar les dades de la còpia de seguretat completa, introdueix una contrasenya a continuació:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"Com que el teu dispositiu està encriptat, has d\'encriptar el dispositiu secundari. Escriu una contrasenya a continuació:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"Si la recuperació de dades està xifrada, introdueix la contrasenya a continuació:"</string> <string name="toast_backup_started" msgid="550354281452756121">"S\'està iniciant la còpia de seguretat..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"Ha finalitzat la còpia de seguretat"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-cs/strings.xml b/packages/BackupRestoreConfirmation/res/values-cs/strings.xml index c46916b42e1f..697de32c5d82 100644 --- a/packages/BackupRestoreConfirmation/res/values-cs/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-cs/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"Sem prosím zadejte bezpečnostní gesto. Toto gesto se použije také při šifrování záložního archivu."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"Zadejte prosím heslo pro šifrování dat úplné zálohy. Pokud pole ponecháte prázdné, použije se aktuální heslo pro zálohy:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"Chcete-li data úplné zálohy zašifrovat, zadejte heslo:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"Protože je zařízení šifrováno, je třeba zálohu zašifrovat. Níže prosím zadejte heslo:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"Pokud jsou obnovená data šifrována, zadejte prosím heslo níže:"</string> <string name="toast_backup_started" msgid="550354281452756121">"Spouští se zálohování..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"Zálohování bylo dokončeno"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-da/strings.xml b/packages/BackupRestoreConfirmation/res/values-da/strings.xml index 01898d0b9644..8b7e21f94517 100644 --- a/packages/BackupRestoreConfirmation/res/values-da/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-da/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"Angiv adgangskoden til kryptering for din enhed nedenfor. Denne bliver også brugt til at kryptere sikkerhedskopien af arkivet."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"Angiv en adgangskode, som skal bruges til kryptering af alle dine sikkerhedsdata. Hvis dette felt er tomt, bruges din aktuelle adgangskode til backup:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"Hvis du ønsker at kryptere sikkerhedsdataene, skal du indtaste en adgangskode nedenfor:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"Eftersom din enhed er krypteret, skal du kryptere din backup. Angiv en adgangskode nedenfor:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"Hvis gendannelsesdataene er krypteret, skal du angive adgangskoden nedenfor:"</string> <string name="toast_backup_started" msgid="550354281452756121">"Backup begynder..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"Backup er færdig"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-de/strings.xml b/packages/BackupRestoreConfirmation/res/values-de/strings.xml index 838ce008a4f5..1913578b58e5 100644 --- a/packages/BackupRestoreConfirmation/res/values-de/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-de/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"Gib dein Passwort zur Geräteverschlüsselung unten ein. Damit wird auch das Sicherungsarchiv verschlüsselt."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"Gib ein Passwort für die Verschlüsselung der vollständigen Sicherungsdaten ein. Wenn du dieses Feld leer lässt, wird dein aktuelles Sicherungspasswort verwendet:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"Wenn du die gesamten Sicherungsdaten verschlüsseln möchtest, gib unten ein Passwort ein:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"Da dein Gerät verschlüsselt ist, muss auch die Sicherung verschlüsselt werden. Gib unten ein Passwort ein:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"Gib das Passwort unten ein, wenn die Daten für die Wiederherstellung verschlüsselt sind:"</string> <string name="toast_backup_started" msgid="550354281452756121">"Sicherung wird gestartet..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"Sicherung abgeschlossen"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-el/strings.xml b/packages/BackupRestoreConfirmation/res/values-el/strings.xml index cd325ef88aee..481ad3e16c63 100644 --- a/packages/BackupRestoreConfirmation/res/values-el/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-el/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"Εισαγάγετε τον κωδικό πρόσβασης για την κρυπτογράφηση συσκευής παρακάτω. Ο κωδικός αυτός θα χρησιμοποιηθεί και για την κρυπτογράφηση του αρχείου αντιγράφων ασφαλείας."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"Εισαγάγετε έναν κωδικό πρόσβασης για χρήση για την κωδικοποίηση του πλήρους αντιγράφου ασφαλείας δεδομένων. Αν μείνει κενό, θα χρησιμοποιηθεί ο τρέχων κωδικός σας πρόσβασης:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"Αν θέλετε να κρυπτογραφήσετε τα πλήρη δεδομένα αντιγράφων ασφαλείας, πληκτρολογήστε έναν κωδικό πρόσβασης παρακάτω:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"Δεδομένου ότι η συσκευή σας είναι κρυπτογραφημένη, θα πρέπει να κρυπτογραφήσετε τα αντίγραφα ασφαλείας σας. Εισαγάγετε τον κωδικό παρακάτω:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"Εάν η επαναφορά των δεδομένων είναι κρυπτογραφημένη, εισάγετε τον κωδικό πρόσβασης παρακάτω:"</string> <string name="toast_backup_started" msgid="550354281452756121">"Έναρξη διαδικασίας δημιουργίας αντιγράφου ασφαλείας..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"Ολοκληρώθηκε η διαδικασία δημιουργίας αντιγράφου ασφαλείας"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-en-rAU/strings.xml b/packages/BackupRestoreConfirmation/res/values-en-rAU/strings.xml index d096d98a1a51..badad601114e 100644 --- a/packages/BackupRestoreConfirmation/res/values-en-rAU/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-en-rAU/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"Please enter your device encryption password below. This will also be used to encrypt the backup archive."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"Please enter a password to use for encrypting the full backup data. If this is left blank, your current backup password will be used:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"If you wish to encrypt the full backup data, enter a password below:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"Since your device is encrypted, you are required to encrypt your backup. Please enter a password below:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"If the restore data is encrypted, please enter the password below:"</string> <string name="toast_backup_started" msgid="550354281452756121">"Backup starting..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"Backup finished"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-en-rCA/strings.xml b/packages/BackupRestoreConfirmation/res/values-en-rCA/strings.xml index d096d98a1a51..badad601114e 100644 --- a/packages/BackupRestoreConfirmation/res/values-en-rCA/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-en-rCA/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"Please enter your device encryption password below. This will also be used to encrypt the backup archive."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"Please enter a password to use for encrypting the full backup data. If this is left blank, your current backup password will be used:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"If you wish to encrypt the full backup data, enter a password below:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"Since your device is encrypted, you are required to encrypt your backup. Please enter a password below:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"If the restore data is encrypted, please enter the password below:"</string> <string name="toast_backup_started" msgid="550354281452756121">"Backup starting..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"Backup finished"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-en-rGB/strings.xml b/packages/BackupRestoreConfirmation/res/values-en-rGB/strings.xml index d096d98a1a51..badad601114e 100644 --- a/packages/BackupRestoreConfirmation/res/values-en-rGB/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-en-rGB/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"Please enter your device encryption password below. This will also be used to encrypt the backup archive."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"Please enter a password to use for encrypting the full backup data. If this is left blank, your current backup password will be used:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"If you wish to encrypt the full backup data, enter a password below:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"Since your device is encrypted, you are required to encrypt your backup. Please enter a password below:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"If the restore data is encrypted, please enter the password below:"</string> <string name="toast_backup_started" msgid="550354281452756121">"Backup starting..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"Backup finished"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-en-rIN/strings.xml b/packages/BackupRestoreConfirmation/res/values-en-rIN/strings.xml index d096d98a1a51..badad601114e 100644 --- a/packages/BackupRestoreConfirmation/res/values-en-rIN/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-en-rIN/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"Please enter your device encryption password below. This will also be used to encrypt the backup archive."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"Please enter a password to use for encrypting the full backup data. If this is left blank, your current backup password will be used:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"If you wish to encrypt the full backup data, enter a password below:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"Since your device is encrypted, you are required to encrypt your backup. Please enter a password below:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"If the restore data is encrypted, please enter the password below:"</string> <string name="toast_backup_started" msgid="550354281452756121">"Backup starting..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"Backup finished"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-en-rXC/strings.xml b/packages/BackupRestoreConfirmation/res/values-en-rXC/strings.xml index 1a612cc5450c..1db4a2aa5367 100644 --- a/packages/BackupRestoreConfirmation/res/values-en-rXC/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-en-rXC/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"Please enter your device encryption password below. This will also be used to encrypt the backup archive."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"Please enter a password to use for encrypting the full backup data. If this is left blank, your current backup password will be used:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"If you wish to encrypt the full backup data, enter a password below:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"Since your device is encrypted, you are required to encrypt your backup. Please enter a password below:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"If the restore data is encrypted, please enter the password below:"</string> <string name="toast_backup_started" msgid="550354281452756121">"Backup starting..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"Backup finished"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-es-rUS/strings.xml b/packages/BackupRestoreConfirmation/res/values-es-rUS/strings.xml index 13ce1da57050..2d76a1ed7a9c 100644 --- a/packages/BackupRestoreConfirmation/res/values-es-rUS/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-es-rUS/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"Introduce tu contraseña de encriptación del dispositivo a continuación. Esta contraseña también se utilizará para encriptar la copia de seguridad."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"Introduce una contraseña para encriptar los datos de la copia de seguridad completa. Si dejas este campo en blanco, se utilizará tu contraseña actual de copia de seguridad:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"Si deseas encriptar los datos de la copia de seguridad completa, introduce una contraseña a continuación:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"Dado que el dispositivo está encriptado, es necesario que encriptes la copia de seguridad. Ingresa una contraseña a continuación:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"Si los datos de recuperación están encriptados, vuelve a introducir la contraseña a continuación:"</string> <string name="toast_backup_started" msgid="550354281452756121">"Iniciando copia de seguridad..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"La realización de la copia de seguridad finalizó."</string> diff --git a/packages/BackupRestoreConfirmation/res/values-es/strings.xml b/packages/BackupRestoreConfirmation/res/values-es/strings.xml index 4ebc799178c8..58930dcf1586 100644 --- a/packages/BackupRestoreConfirmation/res/values-es/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-es/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"Introduce a continuación la contraseña de cifrado del dispositivo. Esta contraseña se usará también para cifrar el archivo de copia de seguridad."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"Introduce la contraseña que quieras usar para cifrar los datos de la copia de seguridad completa. Si dejas este campo en blanco, se usará tu contraseña de copia de seguridad actual:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"Si quieres cifrar los datos de la copia de seguridad completa, introduce la contraseña a continuación:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"Tu dispositivo está cifrado, por lo que debes cifrar tu copia de seguridad. Introduce una contraseña a continuación:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"Si los datos de restauración están cifrados, introduce la contraseña a continuación:"</string> <string name="toast_backup_started" msgid="550354281452756121">"Iniciando copia de seguridad..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"Copia de seguridad finalizada"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-et/strings.xml b/packages/BackupRestoreConfirmation/res/values-et/strings.xml index 0f5fde2c9a2e..4399068feae0 100644 --- a/packages/BackupRestoreConfirmation/res/values-et/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-et/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"Sisestage allpool oma seadme krüpteerimise parool. Seda kasutatakse ka varukoopiate arhiivi krüpteerimiseks."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"Sisestage parool kõikide varundatud andmete krüpteerimise jaoks. Kui jätate selle tühjaks, siis kasutatakse teie praegust varunduse parooli:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"Kui soovite kõik varundusandmed krüpteerida, siis sisestage allpool parool:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"Kuna seade on krüpteeritud, siis peate krüpteerima ka varukoopia. Sisestage all parool:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"Kui taasteandmed on krüpteeritud, siis sisestage allpool parool."</string> <string name="toast_backup_started" msgid="550354281452756121">"Algab varundamine ..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"Varundamine jõudis lõpule"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-eu/strings.xml b/packages/BackupRestoreConfirmation/res/values-eu/strings.xml index 5b522787032c..3905a0b4d7be 100644 --- a/packages/BackupRestoreConfirmation/res/values-eu/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-eu/strings.xml @@ -24,11 +24,12 @@ <string name="restore_confirm_text" msgid="7499866728030461776">"Konektatutako ordenagailu bateko datu guztiak leheneratzeko eskatu da. Horretarako baimena eman nahi duzu?\n\nEz baduzu leheneratzea zuk eskatu, ez eman eragiketarekin jarraitzeko baimena. Eragiketa gauzatzen bada, gailuan dituzun datu guztiak ordeztuko dira!"</string> <string name="allow_restore_button_label" msgid="3081286752277127827">"Leheneratu datuak"</string> <string name="deny_restore_button_label" msgid="1724367334453104378">"Ez leheneratu"</string> - <string name="current_password_text" msgid="8268189555578298067">"Idatzi babeskopien oraingo pasahitza behean:"</string> + <string name="current_password_text" msgid="8268189555578298067">"Idatzi babeskopien uneko pasahitza behean:"</string> <string name="device_encryption_restore_text" msgid="1570864916855208992">"Idatzi behean gailua enkriptatzeko pasahitza."</string> <string name="device_encryption_backup_text" msgid="5866590762672844664">"Idatzi gailua enkriptatzeko pasahitza behean. Babeskopiaren artxiboa enkriptatzeko ere erabiliko da."</string> - <string name="backup_enc_password_text" msgid="4981585714795233099">"Idatzi babeskopia osoaren datuak enkriptatzeko erabili nahi duzun pasahitza. Eremua hutsik uzten baduzu, babeskopien oraingo pasahitza erabiliko da:"</string> + <string name="backup_enc_password_text" msgid="4981585714795233099">"Idatzi babeskopia osoaren datuak enkriptatzeko erabili nahi duzun pasahitza. Eremua hutsik uzten baduzu, babeskopien uneko pasahitza erabiliko da:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"Babeskopia osoko datuak enkriptatu nahi badituzu, idatzi pasahitza behean:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"Gailua enkriptatuta daukazunez, babeskopiak ere enkriptatu egin behar dituzu. Idatzi pasahitza hemen:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"Leheneratze-datuak enkriptatuta badaude, idatzi pasahitza behean:"</string> <string name="toast_backup_started" msgid="550354281452756121">"Babeskopia egiten hasten…"</string> <string name="toast_backup_ended" msgid="3818080769548726424">"Babeskopia egin da"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-fa/strings.xml b/packages/BackupRestoreConfirmation/res/values-fa/strings.xml index 652d38a3c769..a8c9d9e1ab09 100644 --- a/packages/BackupRestoreConfirmation/res/values-fa/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-fa/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"لطفاً گذرواژه رمزگذاری دستگاه خود را در زیر وارد کنید. این برای رمزگذاری بایگانی پشتیبان نیز مورد استفاده قرار میگیرد."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"لطفاً یک گذرواژه برای رمزگذاری دادههای کامل نسخهٔ پشتیبانی وارد کنید. اگر این خالی بماند، گذرواژه فعلی نسخهٔ پشتیبان مورد استفاده قرار خواهد گرفت:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"اگر میخواهید تمام نسخه پشتیبانی داده را رمزدار کنید، یک گذرواژه در زیر وارد کنید:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"چون دستگاهتان رمزگذاری شده است، باید نسخه پشتیبان خودتان را رمزگذاری کنید. لطفاً گذرواژهای را در زیر وارد کنید:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"اگر داده بازیابی شده رمزگذاری شده است، لطفاً گذرواژه را در زیر وارد کنید:"</string> <string name="toast_backup_started" msgid="550354281452756121">"شروع پشتیبانگیری…"</string> <string name="toast_backup_ended" msgid="3818080769548726424">"پشتیبانگیری تمام شد"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-fi/strings.xml b/packages/BackupRestoreConfirmation/res/values-fi/strings.xml index 56184328e63e..bc9dbde20292 100644 --- a/packages/BackupRestoreConfirmation/res/values-fi/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-fi/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"Kirjoita laitteen salauksen salasana alle. Salasanaa käytetään myös varmuuskopioarkiston salaamiseen."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"Lisää salasana kaikkien varmuuskopiotietojen salaamiseksi. Jos tämä jätetään tyhjäksi, nykyistä varmuuskopioinnin salasanaa käytetään:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"Jos haluat salata kaikki varmuuskopiotiedot, kirjoita salasana alle:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"Koska laite on salattu, myös varmuuskopiointi on salattava. Kirjoita salasana alle:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"Jos palautustiedot on salattu, anna salasana alla:"</string> <string name="toast_backup_started" msgid="550354281452756121">"Varmuuskopiointi alkaa..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"Varmuuskopiointi valmis"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-fr-rCA/strings.xml b/packages/BackupRestoreConfirmation/res/values-fr-rCA/strings.xml index 8a70fb5def2b..769b721239af 100644 --- a/packages/BackupRestoreConfirmation/res/values-fr-rCA/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-fr-rCA/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"Veuillez saisir le mot de passe de chiffrement de l\'appareil ci-dessous. Il permettra également de chiffrer les archives de sauvegarde."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"Veuillez saisir un mot de passe à utiliser pour chiffrer les données de sauvegarde complète. Si ce champ n\'est pas renseigné, votre mot de passe de sauvegarde actuel sera utilisé :"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"Si vous souhaitez chiffrer l\'ensemble des données de sauvegarde, veuillez saisir un mot de passe ci-dessous :"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"Votre appareil est chiffré. Vous devez donc chiffrer votre sauvegarde. Veuillez entrer un mot de passe ci-dessous :"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"Si les données de restauration sont chiffrées, veuillez saisir le mot de passe ci-dessous :"</string> <string name="toast_backup_started" msgid="550354281452756121">"Démarrage de la sauvegarde…"</string> <string name="toast_backup_ended" msgid="3818080769548726424">"Sauvegarde terminée."</string> diff --git a/packages/BackupRestoreConfirmation/res/values-fr/strings.xml b/packages/BackupRestoreConfirmation/res/values-fr/strings.xml index dd198dff15ce..f40b02af3234 100644 --- a/packages/BackupRestoreConfirmation/res/values-fr/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-fr/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"Veuillez saisir le mot de passe de chiffrement de l\'appareil ci-dessous. Il permettra également de chiffrer les archives de sauvegarde."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"Veuillez saisir un mot de passe à utiliser pour chiffrer les données de sauvegarde complète. Si ce champ n\'est pas renseigné, votre mot de passe de sauvegarde actuel sera utilisé :"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"Si vous souhaitez chiffrer l\'ensemble des données de sauvegarde, veuillez saisir un mot de passe ci-dessous :"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"Votre appareil est chiffré. Vous devez donc chiffrer votre sauvegarde. Veuillez saisir un mot de passe ci-dessous :"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"Si les données de restauration sont chiffrées, veuillez saisir le mot de passe ci-dessous :"</string> <string name="toast_backup_started" msgid="550354281452756121">"Démarrage de la sauvegarde…"</string> <string name="toast_backup_ended" msgid="3818080769548726424">"Sauvegarde terminée."</string> diff --git a/packages/BackupRestoreConfirmation/res/values-gl/strings.xml b/packages/BackupRestoreConfirmation/res/values-gl/strings.xml index bb0b3d770062..0a12aa7364ff 100644 --- a/packages/BackupRestoreConfirmation/res/values-gl/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-gl/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"Insire o contrasinal de encriptación do dispositivo a continuación. Tamén se usará para encriptar o arquivo de copia de seguranza."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"Insire un contrasinal para encriptar os datos da copia de seguranza completa. Se queda en branco este campo, usarase o contrasinal da copia de seguranza actual."</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"Se queres encriptar os datos da copia de seguranza completa, insire un contrasinal a continuación:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"Como o teu dispositivo está cifrado, debes cifrar a túa copia de seguranza. Introduce un contrasinal a continuación:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"Se os datos de restauración están encriptados, insire o contrasinal a continuación:"</string> <string name="toast_backup_started" msgid="550354281452756121">"Iniciando copia de seguranza..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"A copia de seguranza rematou"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-gu/strings.xml b/packages/BackupRestoreConfirmation/res/values-gu/strings.xml index b72344b901e1..3a3058829572 100644 --- a/packages/BackupRestoreConfirmation/res/values-gu/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-gu/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"કૃપા કરીને તમારો ઉપકરણ એન્ક્રિપ્શન પાસવર્ડ નીચે દાખલ કરો. આનો ઉપયોગ બેકઅપ સંગ્રહને એન્ક્રિપ્ટ કરવા માટે પણ થશે."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"કૃપા કરીને પૂર્ણ બેકઅપ ડેટાને એન્ક્રિપ્ટ કરવા, ઉપયોગમાં લેવા માટેનો એક પાસવર્ડ દાખલ કરો. જો આ ખાલી છોડવામાં આવે, તો તમારો વર્તમાન બેકઅપ પાસવર્ડ ઉપયોગમાં લેવાશે:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"જો તમે પૂર્ણ બેકઅપ ડેટાને એન્ક્રિપ્ટ કરવા ઇચ્છો, તો નીચે એક પાસવર્ડ દાખલ કરો:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"તમારું ઉપકરણ એન્ક્રિપ્ટ કરેલું હોવાથી, તમારે તમારા બેકઅપને એન્ક્રિપ્ટ કરવાની જરૂર છે. કૃપા કરીને નીચે એક પાસવર્ડ દાખલ કરો:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"જો પુનર્સ્થાપિત ડેટા એન્ક્રિપ્ટ કરેલ છે, તો કૃપા કરીને નીચે પાસવર્ડ દાખલ કરો:"</string> <string name="toast_backup_started" msgid="550354281452756121">"બેકઅપ પ્રારંભ કરી રહ્યું છે..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"બેકઅપ સમાપ્ત થયું"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-hi/strings.xml b/packages/BackupRestoreConfirmation/res/values-hi/strings.xml index 698c6d3868ff..2e53cb6388a0 100644 --- a/packages/BackupRestoreConfirmation/res/values-hi/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-hi/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"कृपया अपना डिवाइस सुरक्षित तरीका पासवर्ड नीचे दर्ज करें. बैकअप मेमोरी को एन्क्रिप्ट करने के लिए भी इसका उपयोग किया जाएगा."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"कृपया संपूर्ण सुरक्षित डेटा को एन्क्रिप्ट करने में उपयोग के लिए पासवर्ड डालें. अगर यह खाली छोड़ दिया जाता है, तो आपके वर्तमान बैकअप पासवर्ड का उपयोग किया जाएगा:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"अगर आप संपूर्ण सुरक्षित डेटा को एन्क्रिप्ट करना चाहते हैं, तो नीचे पासवर्ड डालें:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"चूंकि आपका डिवाइस एन्क्रिप्ट किया हुआ है, इसलिए आपको अपने बैकअप को एन्क्रिप्ट करना आवश्यक है. कृपया नीचे पासवर्ड डालें:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"अगर रिस्टोर किया गया डेटा सुरक्षित किया गया है, तो कृपया नीचे पासवर्ड डालें:"</string> <string name="toast_backup_started" msgid="550354281452756121">"सुरक्षित करना शुरु हो रहा है..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"बैकअप करना पूरा हुआ"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-hr/strings.xml b/packages/BackupRestoreConfirmation/res/values-hr/strings.xml index 82b067988946..cda36cbfda90 100644 --- a/packages/BackupRestoreConfirmation/res/values-hr/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-hr/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"U nastavku unesite svoju zaporku enkripcije za uređaj. Ona će se upotrijebiti i za enkripciju te za arhivu sigurnosnih kopija."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"Unesite zaporku koju ćete upotrebljavati za kriptiranje podataka potpune sigurnosne kopije. Ako je ostavite praznom, bit će upotrijebljena vaša trenutačna zaporka za sigurnosno kopiranje:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"Ako želite šifrirati podatke potpune sigurnosne kopije, u nastavku unesite zaporku:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"Budući da vam je uređaj kriptiran, morate šifrirati sigurnosne kopije. Unesite zaporku u nastavku:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"Ako su podaci za vraćanje kriptirani, unesite zaporku u nastavku:"</string> <string name="toast_backup_started" msgid="550354281452756121">"Započinje stvaranje sigurnosne kopije..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"Sigurnosna kopija dovršena"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-hu/strings.xml b/packages/BackupRestoreConfirmation/res/values-hu/strings.xml index 73d9a6380a36..a402c56224d3 100644 --- a/packages/BackupRestoreConfirmation/res/values-hu/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-hu/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"Kérjük, adja meg az eszköz titkosítási jelszavát. Ezt használjuk a biztonsági mentések archívumának titkosításához is."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"Kérjük, írjon be egy jelszót a teljes biztonsági mentés adatainak titkosításához. Ha üresen hagyja, jelenlegi biztonsági jelszavát fogjuk használni:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"Ha minden mentett adatot szeretne titkosítani, adjon meg egy jelszót alább:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"Mivel az eszköz titkosítva van, a biztonsági mentést is titkosítani kell. Kérjük, alább adjon meg egy jelszót:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"Ha a visszaállítási adatok titkosítva vannak, kérjük, adja meg a jelszót alább:"</string> <string name="toast_backup_started" msgid="550354281452756121">"Biztonsági mentés indítása..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"A biztonsági mentés befejeződött"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-hy/strings.xml b/packages/BackupRestoreConfirmation/res/values-hy/strings.xml index 2c71735e3818..ca9834e30f08 100644 --- a/packages/BackupRestoreConfirmation/res/values-hy/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-hy/strings.xml @@ -28,8 +28,9 @@ <string name="device_encryption_restore_text" msgid="1570864916855208992">"Խնդրում ենք մուտքագրել ձեր սարքի գաղտնագրման գաղտնաբառը ներքևում:"</string> <string name="device_encryption_backup_text" msgid="5866590762672844664">"Խնդրում ենք մուտքագրել ձեր սարքի գաղտնագրման գաղտնաբառը ներքևում: Այն նաև կօգտագործվի պահուստային արխիվի գաղտնագրման համար:"</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"Խնդրում ենք մուտքագրել գաղտնաբառը` ամբողջական պահուստավորվող տվյալները գաղտնագրելու համար: Եթե այն դատարկ թողնեք, ապա կօգտագործվի ձեր առկա պահուստավորման գաղտնաբառը`"</string> - <string name="backup_enc_password_optional" msgid="1350137345907579306">"Եթե ցանկանում եք գաղտնագրել ամբողջական պահուստավորված տվյալները, մուտքագրեք գաղտնաբառ ստորև՝"</string> - <string name="restore_enc_password_text" msgid="6140898525580710823">"Եթե վերականգնվող տվյալները գաղտնագրված են, խնդրում ենք մուտքագրել գաղտնաբառը ստորև՝"</string> + <string name="backup_enc_password_optional" msgid="1350137345907579306">"Եթե ցանկանում եք գաղտնագրել ամբողջական պահուստավորված տվյալները, մուտքագրեք գաղտնաբառ ստորև`"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"Քանի որ ձեր սարքը գաղտնագրված է, դուք պետք է գաղտնագրեք նաև ձեր պահուստը: Խնդրում ենք ստորև սահմանել գաղտնաբառը՝"</string> + <string name="restore_enc_password_text" msgid="6140898525580710823">"Եթե վերականգնվող տվյալները գաղտնագրված են, խնդրում ենք մուտքագրել գաղտնաբառը ստորև`"</string> <string name="toast_backup_started" msgid="550354281452756121">"Պահուստավորումը սկսվում է..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"Պահուստավորումն ավարտված է"</string> <string name="toast_restore_started" msgid="7881679218971277385">"Վերականգնումը մեկնարկեց..."</string> diff --git a/packages/BackupRestoreConfirmation/res/values-in/strings.xml b/packages/BackupRestoreConfirmation/res/values-in/strings.xml index 99620c152399..5c82adff83fa 100644 --- a/packages/BackupRestoreConfirmation/res/values-in/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-in/strings.xml @@ -18,10 +18,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="backup_confirm_title" msgid="827563724209303345">"Pencadangan lengkap"</string> <string name="restore_confirm_title" msgid="5469365809567486602">"Pemulihan sepenuhnya"</string> - <string name="backup_confirm_text" msgid="1878021282758896593">"Pencadangan semua data ke komputer yang terhubung telah diminta. Apakah Anda ingin mengizinkan hal ini dilakukan?\n\nJika Anda tidak meminta pencadangan ini, jangan izinkan operasi dilanjutkan."</string> + <string name="backup_confirm_text" msgid="1878021282758896593">"Pencadangan semua data ke komputer yang tersambung telah diminta. Apakah Anda ingin mengizinkan hal ini dilakukan?\n\nJika Anda tidak meminta pencadangan ini, jangan izinkan operasi dilanjutkan."</string> <string name="allow_backup_button_label" msgid="4217228747769644068">"Cadangkan data saya"</string> <string name="deny_backup_button_label" msgid="6009119115581097708">"Jangan mencadangkan"</string> - <string name="restore_confirm_text" msgid="7499866728030461776">"Pemulihan lengkap semua data dari komputer desktop yang terhubung telah diminta. Apakah Anda ingin mengizinkan hal ini?\n\nJika Anda tidak meminta pemulihan ini, jangan izinkan operasi dilanjutkan. Operasi ini akan mengganti data apa pun yang saat ini ada dalam perangkat!"</string> + <string name="restore_confirm_text" msgid="7499866728030461776">"Pemulihan lengkap semua data dari komputer desktop yang tersambung telah diminta. Apakah Anda ingin mengizinkan hal ini?\n\nJika Anda tidak meminta pemulihan ini, jangan izinkan operasi dilanjutkan. Operasi ini akan mengganti data apa pun yang saat ini ada dalam perangkat!"</string> <string name="allow_restore_button_label" msgid="3081286752277127827">"Memulihkan data saya"</string> <string name="deny_restore_button_label" msgid="1724367334453104378">"Jangan pulihkan"</string> <string name="current_password_text" msgid="8268189555578298067">"Masukkan sandi cadangan Anda saat ini di bawah:"</string> @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"Masukkan sandi enkripsi perangkat Anda di bawah. Sandi ini juga akan digunakan untuk mengenkripsi arsip cadangan."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"Masukkan sandi yang digunakan untuk mengenkripsi data cadangan lengkap. Jika bidang ini dikosongkan, sandi cadangan Anda saat ini akan digunakan:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"Jika Anda ingin mengenkripsi data cadangan lengkap, masukkan sandi di bawah:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"Karena perangkat Anda dienkripsi, Anda perlu mengenkripsi cadangan. Masukkan sandi di bawah:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"Jika data pemulihan dienkripsi, masukkan sandi di bawah:"</string> <string name="toast_backup_started" msgid="550354281452756121">"Pencadangan dimulai..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"Pencadangan selesai"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-is/strings.xml b/packages/BackupRestoreConfirmation/res/values-is/strings.xml index c6ec0e3fecc2..13e5e5205639 100644 --- a/packages/BackupRestoreConfirmation/res/values-is/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-is/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"Sláðu inn aðgangsorð fyrir dulkóðun tækis hér fyrir neðan. Það verður einnig notað til að dulkóða afritasafnið."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"Sláðu inn aðgangsorð til að dulkóða gögn fullrar afritunar. Ef þetta er skilið eftir autt verður núverandi aðgangsorð fyrir afritun notað:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"Ef þú vilt dulkóða gögn fullrar afritunar skaltu slá inn aðgangsorð hér að neðan:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"Þar sem tækið er dulkóðað þarftu að dulkóða öryggisafritið. Veldu aðgangsorð hér fyrir neðan:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"Ef endurheimt gögn eru dulkóðuð skaltu slá inn aðgangsorðið hér að neðan:"</string> <string name="toast_backup_started" msgid="550354281452756121">"Afritun er að hefjast..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"Afritun lokið"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-it/strings.xml b/packages/BackupRestoreConfirmation/res/values-it/strings.xml index 141d4776240f..1cbb770583a8 100644 --- a/packages/BackupRestoreConfirmation/res/values-it/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-it/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"Inserisci la tua password di crittografia dispositivo di seguito. Verrà utilizzata anche per crittografare l\'archivio di backup."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"Inserisci una password da utilizzare per la crittografia dei dati di backup completi. Se non ne inserisci una, verrà utilizzata la tua password di backup corrente:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"Se desideri crittografare tutti i dati di backup, inserisci una password qui di seguito:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"Il dispositivo è criptato, quindi devi criptare il backup. Inserisci una password di seguito:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"Se i dati di ripristino sono criptati, inserisci la password qui di seguito:"</string> <string name="toast_backup_started" msgid="550354281452756121">"Avvio del backup..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"Backup terminato"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-iw/strings.xml b/packages/BackupRestoreConfirmation/res/values-iw/strings.xml index 41593bc5f3be..c060403c588e 100644 --- a/packages/BackupRestoreConfirmation/res/values-iw/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-iw/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"עליך להזין את סיסמת ההצפנה של המכשיר שלך בהמשך. הסיסמה תשמש גם להצפנת ארכיון הגיבוי."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"הזן סיסמה שתשמש להצפנה של נתוני הגיבוי המלא. אם תשאיר שדה זה ריק, ייעשה שימוש בסיסמת הגיבוי הנוכחית שלך:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"אם אתה רוצה להצפין את נתוני הגיבוי המלא, הזן סיסמה בהמשך:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"מכיוון שהמכשיר מוצפן, אתה נדרש להצפין את הגיבוי. הזן סיסמה בהמשך:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"אם נתוני השחזור מוצפנים, הזן את הסיסמה למטה:"</string> <string name="toast_backup_started" msgid="550354281452756121">"מתחיל בגיבוי..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"הגיבוי הסתיים"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-ja/strings.xml b/packages/BackupRestoreConfirmation/res/values-ja/strings.xml index df2f20acd861..58097f5160d0 100644 --- a/packages/BackupRestoreConfirmation/res/values-ja/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-ja/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"以下にデバイス暗号化用のパスワードを入力してください。このパスワードはバックアップアーカイブの暗号化にも使用します。"</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"フルバックアップデータの暗号化に使用するパスワードを入力してください。空白のままにした場合、現在のバックアップ用のパスワードが使用されます:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"フルバックアップのデータを暗号化する場合は、以下にパスワードを入力してください:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"デバイスは暗号化されているため、バックアップを暗号化する必要があります。下にパスワードを入力してください。"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"復元するデータが暗号化されている場合、以下にパスワードを入力してください:"</string> <string name="toast_backup_started" msgid="550354281452756121">"バックアップを開始しています..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"バックアップが終了しました"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-ka/strings.xml b/packages/BackupRestoreConfirmation/res/values-ka/strings.xml index 9c6f67ec6eb1..0c4b7c2a1805 100644 --- a/packages/BackupRestoreConfirmation/res/values-ka/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-ka/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"გთხოვთ, ქვემოთ მიუთითოთ თქვენი მოწყობილობის დაშიფვრის პაროლი. ეს ასევე გამოყენებული იქნება სათადარიგო არქივის დაშიფრვისათვის."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"გთხოვთ შეიყვანოთ ყველა სამარქაფო ასლის დაშიფრვის პაროლი. თუ ამ ველს ცარიელს დატოვებთ, გამოყენებული იქნება მიმდინარე პაროლი:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"თუ გსურთ სრული ლოკალური სარეზერვო კოპიის დაშიფრვა, შეიყვანეთ პაროლი ქვემოთ:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"ვინაიდან თქვენი მოწყობილობა დაშიფრულია, მოგიწევთ დაშიფროთ თქვენი მარქაფი. გთხოვთ, შეიყვანოთ ქვევით პაროლი:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"თუ აღსადგენი მონაცემები დაშიფრულია, გთხოვთ, შეიყვანოთ პაროლი ქვემოთ:"</string> <string name="toast_backup_started" msgid="550354281452756121">"ასლების მომზადება იწყება..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"სარეზერვო კოპირება დასრულებულია"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-kk/strings.xml b/packages/BackupRestoreConfirmation/res/values-kk/strings.xml index 76ce88477150..38d71724de0e 100644 --- a/packages/BackupRestoreConfirmation/res/values-kk/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-kk/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"Құрылғыңыздың кодтық кілтсөзін енгізіңіз. Ол сақтық көшірме мұрағатын кодтау үшін де қолданылады."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"Деректердің сақтық көшірмесін толығымен шифрлау үшін кілтсөзді енгізіңіз. Егер бұл бос қалдырылса, сіздің қазіргі сақтық көшірме кілтсөзіңіз қолданылады:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"Деректердің сақтық көшірмесін толығымен шифрлауды қаласаңыз, кілтсөзді енгізіңіз:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"Құрылғыңыз шифрланғандықтан, сақтық көшірмені шифрлау қажет. Төменде құпия сөзді енгізіңіз:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"Қалпына келтіру деректері кодталса, кілтсөзді енгізіңіз:"</string> <string name="toast_backup_started" msgid="550354281452756121">"Сақтық көшірме басталуда..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"Қалпына келтіру аяқталды"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-km/strings.xml b/packages/BackupRestoreConfirmation/res/values-km/strings.xml index 956fdd71dc1a..cc46d9e2813c 100644 --- a/packages/BackupRestoreConfirmation/res/values-km/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-km/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"សូមបញ្ចូលពាក្យសម្ងាត់ដាក់លេខកូដឧបករណ៍របស់អ្នកខាងក្រោម។ វានឹងត្រូវបានប្រើ ដើម្បីដាក់លេខកូដប័ណ្ណសារបម្រុងទុកផងដែរ។"</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"សូមបញ្ចូលពាក្យសម្ងាត់ដើម្បីប្រើសម្រាប់ដាក់លេខកូដទិន្នន័យបម្រុងទុកពេញលេញ។ បើទុកវាទទេ ពាក្យសម្ងាត់បម្រុងទុកបច្ចុប្បន្នរបស់អ្នកនឹងត្រូវបានប្រើ៖"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"បើអ្នកចង់ដាក់លេខកូដទិន្នន័យបម្រុងទុកពេញលេញ បញ្ចូលពាក្យសម្ងាត់ខាងក្រោម៖"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"ព្រោះថាឧបករណ៍របស់អ្នកត្រូវបានដាក់លេខកូដ អ្នកត្រូវបានទាមទារឲ្យដាក់លេខកូដការបម្រុងទុករបស់អ្នក។ សូមបញ្ចូលពាក្យសម្ងាត់ខាងក្រោម៖"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"បើទិន្នន័យស្ដារត្រូវបានដាក់លេខកូដ សូមបញ្ចូលពាក្យសម្ងាត់ខាងក្រោម៖"</string> <string name="toast_backup_started" msgid="550354281452756121">"កំពុងចាប់ផ្ដើមបម្រុងទុក..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"ការបម្រុងទុកបានបញ្ចប់"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-kn/strings.xml b/packages/BackupRestoreConfirmation/res/values-kn/strings.xml index 71c60f7b8945..77ff317229b6 100644 --- a/packages/BackupRestoreConfirmation/res/values-kn/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-kn/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"ದಯವಿಟ್ಟು ಕೆಳಗೆ ನಿಮ್ಮ ಸಾಧನದ ಎನ್ಕ್ರಿಪ್ಶನ್ ಪಾಸ್ವರ್ಡ್ ನಮೂದಿಸಿ. ಇದನ್ನು ಬ್ಯಾಕಪ್ ಆರ್ಕೈವ್ ಅನ್ನು ಎನ್ಕ್ರಿಪ್ಟ್ ಮಾಡಲು ಸಹ ಬಳಸಲಾಗುತ್ತದೆ."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"ಸಂಪೂರ್ಣ ಬ್ಯಾಕಪ್ ಡೇಟಾವನ್ನು ಎನ್ಕ್ರಿಪ್ಟ್ ಮಾಡಲು ಪಾಸ್ವರ್ಡ್ ನಮೂದಿಸಿ. ಇದನ್ನು ಖಾಲಿಯಾಗಿಯೇ ಬಿಟ್ಟರೆ, ನಿಮ್ಮ ಪ್ರಸ್ತುತ ಬ್ಯಾಕಪ್ ಪಾಸ್ವರ್ಡ್ ಅನ್ನು ಬಳಸಲಾಗುತ್ತದೆ:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"ನೀವು ಸಂಪೂರ್ಣ ಬ್ಯಾಕಪ್ ಡೇಟಾವನ್ನು ಎನ್ಕ್ರಿಪ್ಟ್ ಮಾಡಲು ಬಯಸಿದರೆ, ಕಳಗೆ ಪಾಸ್ವರ್ಡ್ ನಮೂದಿಸಿ:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"ನಿಮ್ಮ ಸಾಧನವನ್ನು ಎನ್ಕ್ರಿಪ್ಟ್ ಮಾಡಿರುವ ಕಾರಣ, ನಿಮ್ಮ ಬ್ಯಾಕಪ್ ಅನ್ನು ನಿವು ಎನ್ಕ್ರಿಪ್ಟ್ ಮಾಡುವ ಅಗತ್ಯವಿದೆ. ದಯವಿಟ್ಟು ಕೆಳಗೆ ಪಾಸ್ವರ್ಡ್ ನಮೂದಿಸಿ:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"ಮರುಸ್ಥಾಪಿಸಲಾದ ಡೇಟಾವನ್ನು ಎನ್ಕ್ರಿಪ್ಟ್ ಮಾಡಲಾಗಿದ್ದರೆ, ದಯವಿಟ್ಟು ಪಾಸ್ವರ್ಡ್ ಕೆಳಗೆ ನಮೂದಿಸಿ:"</string> <string name="toast_backup_started" msgid="550354281452756121">"ಬ್ಯಾಕಪ್ ಪ್ರಾರಂಭವಾಗುತ್ತಿದೆ..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"ಬ್ಯಾಕಪ್ ಪೂರ್ಣಗೊಂಡಿದೆ"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-ko/strings.xml b/packages/BackupRestoreConfirmation/res/values-ko/strings.xml index 23c8662436c1..600ae62f99da 100644 --- a/packages/BackupRestoreConfirmation/res/values-ko/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-ko/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"아래에 기기 암호화 비밀번호를 입력하세요. 백업 자료실을 암호화할 때에도 사용됩니다."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"전체 백업 데이터를 암호화하려면 사용할 비밀번호를 입력하세요. 공백으로 남겨 두면 현재 백업 비밀번호가 사용됩니다."</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"전체 백업 데이터를 암호화하려면 아래에 비밀번호를 입력하세요."</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"기기가 암호화되었으므로 백업을 암호화해야 합니다. 아래에 비밀번호를 입력하세요."</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"복원 데이터가 암호화되어 있는 경우, 아래에 비밀번호를 입력하세요."</string> <string name="toast_backup_started" msgid="550354281452756121">"백업 시작 중..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"백업을 완료했습니다."</string> diff --git a/packages/BackupRestoreConfirmation/res/values-ky/strings.xml b/packages/BackupRestoreConfirmation/res/values-ky/strings.xml index 1901cf147637..6333b18debc7 100644 --- a/packages/BackupRestoreConfirmation/res/values-ky/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-ky/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"Түзмөгүңүздүн шифрлөө сырсөзүн төмөндө киргизиңиз. Ал бэкап архивин шифрлегенге дагы колдонулат."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"Эгер сиз толук бэкапты шифрлегиңиз келсе, төмөндө сырсөз киргизиңиз. Эгер ал бош калтырылса, анда учурдагы сырсөз колдонулат:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"Эгер сиз толук бэкапты шифрлегиңиз келсе, төмөндө сырсөз киргизиңиз:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"Түзмөгүңүз шифрленген болгондуктан, камдооңузду шифрлешиңиз керек. Төмөнгө сырсөз киргизиңиз:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"Эгер калыбына келтирүү берилиштери шифрленген болсо, төмөндө сырсөздү киргизиңиз:"</string> <string name="toast_backup_started" msgid="550354281452756121">"Бэкап башталды..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"Бэкап аяктады"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-lo/strings.xml b/packages/BackupRestoreConfirmation/res/values-lo/strings.xml index fb28502a7e56..ccac8ed7b092 100644 --- a/packages/BackupRestoreConfirmation/res/values-lo/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-lo/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"ກະລຸນາປ້ອນລະຫັດຜ່ານການເຂົ້າລະຫັດອຸປະກອນຂອງທ່ານໃສ່ດ້ານລຸ່ມ. ລະຫັດນີ້ຍັງຈະໃຊ້ເພື່ອເຂົ້າລະຫັດຂໍ້ມູນທີ່ສຳຮອງໄວ້."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"ກະລຸນາປ້ອນລະຫັດຜ່ານ ເພື່ອໃຊ້ໃນການເຂົ້າລະຫັດການສຳຮອງຂໍ້ມູນເຕັມຮູບແບບ. ຖ້າປ່ອຍໃຫ້ເປົ່າຫວ່າງໄວ້, ລະຫັດຜ່ານສຳຮອງຂໍ້ມູນທີ່ທ່ານໃຊ້ຢູ່ຈະຖືກນຳໃຊ້ແທນ:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"ຫາກທ່ານຕ້ອງການທີ່ຈະເຂົ້າລະຫັດໃຫ້ກັບການສຳຮອງຂໍ້ມູນທັງໝົດ, ກະລຸນາໃສ່ລະຫັດທາງລຸ່ມນີ້:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"ເນື່ອງຈາກອຸປະກອນຂອງທ່ານຖືກເຂົ້າລະຫັດໄວ້, ທ່ານຈຶ່ງຕ້ອງເຂົ້າລະຫັດການສຳຮອງຂໍ້ມູນຂອງທ່ານ. ກະລຸນາລະບຸລະຫັດຜ່ານດ້ານລຸ່ມ:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"ຫາກຂໍ້ມູນສຳຮອງຖືກເຂົ້າລະຫັດໄວ້, ກະລຸນາໃສ່ລະຫັດຜ່ານທາງດ້ານລຸ່ມນີ້:"</string> <string name="toast_backup_started" msgid="550354281452756121">"ກຳລັງເລີ່ມການສຳຮອງຂໍ້ມູນ..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"ສຳຮອງຂໍ້ມູນສຳເລັດແລ້ວ"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-lt/strings.xml b/packages/BackupRestoreConfirmation/res/values-lt/strings.xml index 44e67de79bae..093ff9d67b73 100644 --- a/packages/BackupRestoreConfirmation/res/values-lt/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-lt/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"Toliau įveskite įrenginio šifruotės slaptažodį. Jis bus naudojamas ir atsarginės kopijos archyvui šifruoti."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"Įveskite slaptažodį, kuris bus naudojamas visai atsarginei duomenų kopijai šifruoti. Jei reikšmės neįvesite, bus naudojamas dabartinis atsarginės kopijos slaptažodis:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"Jei norite užšifruoti visą atsarginę duomenų kopiją, įveskite slaptažodį:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"Kadangi jūsų įrenginys užšifruotas, turite užšifruoti atsarginę kopiją. Toliau įveskite slaptažodį:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"Jei atkūrimo duomenys užšifruoti, įveskite toliau nurodytą slaptažodį:"</string> <string name="toast_backup_started" msgid="550354281452756121">"Pradedama kurti atsarginę kopiją..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"Atsarginė kopija sukurta"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-lv/strings.xml b/packages/BackupRestoreConfirmation/res/values-lv/strings.xml index c58d6fde4dcd..c969726edebe 100644 --- a/packages/BackupRestoreConfirmation/res/values-lv/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-lv/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"Lūdzu, ievadiet ierīces šifrēšanas paroli. Tā tiks arī izmantota, lai šifrētu dublējuma arhīvu."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"Lūdzu, ievadiet paroli, kas tiks izmantota dublējuma datu pilnīgai šifrēšanai. Ja paroles lauciņu atstāsiet tukšu, tiks izmantota jūsu pašreizējā dublējuma parole:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"Ja vēlaties pilnībā šifrēt dublējuma datus, tālāk ievadiet paroli:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"Tā kā ierīce ir šifrēta, jums ir jāšifrē dublējums. Lūdzu, tālāk ievadiet paroli."</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"Ja atjaunošanas dati ir šifrēti, lūdzu, ievadiet tālāk paroli:"</string> <string name="toast_backup_started" msgid="550354281452756121">"Tiek sākta dublēšana..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"Dublēšana ir pabeigta."</string> diff --git a/packages/BackupRestoreConfirmation/res/values-mk/strings.xml b/packages/BackupRestoreConfirmation/res/values-mk/strings.xml index e7d33b799846..d1cfe4aa1229 100644 --- a/packages/BackupRestoreConfirmation/res/values-mk/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-mk/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"Внесете ја лозинката за шифрирање на вашиот уред подолу. Таа ќе се користи и за шифрирање на архивата на бекапот."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"Внесете лозинка што ќе се користи за шифрирање на целосната резервна копија на податоците. Ако ова поле остане празно, ќе се користи вашата тековна лозинка за резервна копија:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"Ако сакате да ја шифрирате целосната резервна копија на податоци, внесете лозинка подолу:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"Бидејќи уредот е шифриран, треба да го шифрирате и бекапот. Внесете лозинка подолу:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"Ако податоците што се враќаат се шифрирани, внесете ја лозинката подолу:"</string> <string name="toast_backup_started" msgid="550354281452756121">"Започнува правење резервна копија..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"Правењето резервна копија заврши"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-ml/strings.xml b/packages/BackupRestoreConfirmation/res/values-ml/strings.xml index bba6ecd649c1..5f97afa6e8cd 100644 --- a/packages/BackupRestoreConfirmation/res/values-ml/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-ml/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"നിങ്ങളുടെ ഉപകരണ എൻക്രിപ്ഷൻ പാസ്വേഡ് ചുവടെ നൽകുക. ബാക്കപ്പ് ആർക്കൈവ് എൻക്രിപ്റ്റുചെയ്യാനും ഇത് ഉപയോഗിക്കുന്നു."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"പൂർണ്ണ ബാക്കപ്പ് ഡാറ്റ എൻക്രിപ്റ്റ് ചെയ്യുന്നതിനായി ഉപയോഗിക്കാൻ ഒരു പാസ്വേഡ് നൽകുക. ഇത് ശൂന്യമായി വിടുകയാണെങ്കിൽ, നിങ്ങളുടെ നിലവിലെ ബാക്കപ്പ് പാസ്വേഡ് ഉപയോഗിക്കും:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"പൂർണ്ണ ബാക്കപ്പ് ഡാറ്റ എൻക്രിപ്റ്റ് ചെയ്യണമെങ്കിൽ, ചുവടെ ഒരു പാസ്വേഡ് നൽകുക:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"നിങ്ങളുടെ ഉപകരണം എൻക്രിപ്റ്റുചെയ്തതിനാൽ, ബാക്കപ്പ് എൻക്രിപ്റ്റുചെയ്യേണ്ടതുണ്ട്. ചുവടെ പാസ്വേഡ് നൽകുക:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"പുനഃസ്ഥാപിച്ച ഡാറ്റ എൻക്രിപ്റ്റ് ചെയ്തിട്ടുണ്ടെങ്കിൽ, പാസ്വേഡ് ചുവടെ നൽകുക:"</string> <string name="toast_backup_started" msgid="550354281452756121">"ബാക്കപ്പ് ആരംഭിക്കുന്നു..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"ബാക്കപ്പ് പൂർത്തിയായി"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-mn/strings.xml b/packages/BackupRestoreConfirmation/res/values-mn/strings.xml index b2738c0e86ba..dc8aa1746c11 100644 --- a/packages/BackupRestoreConfirmation/res/values-mn/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-mn/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"Төхөөрөмж шифрлэх нууц үгийг доор оруулна уу. Энэ нууц үгийг нөөшлөх архивийг шифрлэхэд бас ашиглана."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"Бүрэн дата нөөшлөлтийг шифрлэхэд ашиглах нууц үгийг оруулна уу. Хэрэв та хоосон үлдээвэл таны одоогийн нөөшлөлтийн нууц үг ашиглагдах болно:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"Хэрэв та бүрэн нөөшлөх датаг шифрлэх бол доор нууц үгийг оруулна уу:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"Таны төхөөрөмж шифрлэгдсэн тул та нөөшлөлтийг мөн шифрлэх шаардлагатай. Нууц үгийг доор оруулна уу:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"Хэрэв сэргээх дата шифрлэгдсэн бол доор нууц үгийг оруулна уу:"</string> <string name="toast_backup_started" msgid="550354281452756121">"Нөөшлөж эхлэх..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"Нөөшлөлт дуусав"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-mr/strings.xml b/packages/BackupRestoreConfirmation/res/values-mr/strings.xml index 616e6bd4b843..b3541717c96e 100644 --- a/packages/BackupRestoreConfirmation/res/values-mr/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-mr/strings.xml @@ -18,10 +18,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="backup_confirm_title" msgid="827563724209303345">"पूर्ण बॅकअप"</string> <string name="restore_confirm_title" msgid="5469365809567486602">"पूर्ण पुनर्संचयन"</string> - <string name="backup_confirm_text" msgid="1878021282758896593">"कनेक्ट केलेल्या डेस्कटॉप काँप्युटरवरील सर्व डेटाच्या पूर्ण बॅकअपची विनंती केली गेली आहे. तुम्ही असे होण्यासाठी अनुमती देऊ इच्छिता?\n\nतुम्ही स्वत: बॅकअपची विनंती केली नसल्यास, कार्य पुढे सुरू राहण्यास अनुमती देऊ नका."</string> + <string name="backup_confirm_text" msgid="1878021282758896593">"कनेक्ट केलेल्या डेस्कटॉप काँप्युटरवरील सर्व डेटाच्या पूर्ण बॅकअपची विनंती केली गेली आहे. तुम्ही असे होण्यासाठी अनुमती देऊ इच्छिता?\n\nतुम्ही स्वत: बॅकअपची विनंती केली नसल्यास, कार्य पुढे सुरु राहण्यास अनुमती देऊ नका."</string> <string name="allow_backup_button_label" msgid="4217228747769644068">"माझ्या डेटाचा बॅकअप घ्या"</string> <string name="deny_backup_button_label" msgid="6009119115581097708">"बॅकअप घेऊ नका"</string> - <string name="restore_confirm_text" msgid="7499866728030461776">"कनेक्ट केलेल्या डेस्कटॉप काँप्युटरवरील सर्व डेटाच्या पूर्ण पुनर्संचयनाची विनंती केली गेली आहे. तुम्ही असे होण्यासाठी अनुमती देऊ इच्छिता?\n\nतुम्ही स्वत: पुनर्संचयनाची विनंती केली नसल्यास, कार्य पुढे सुरू राहण्यास अनुमती देऊ नका. हे आपल्या डिव्हाइसवरील कोणत्याही वर्तमान डेटास पुनर्स्थित करेल!"</string> + <string name="restore_confirm_text" msgid="7499866728030461776">"कनेक्ट केलेल्या डेस्कटॉप काँप्युटरवरील सर्व डेटाच्या पूर्ण पुनर्संचयनाची विनंती केली गेली आहे. तुम्ही असे होण्यासाठी अनुमती देऊ इच्छिता?\n\nतुम्ही स्वत: पुनर्संचयनाची विनंती केली नसल्यास, कार्य पुढे सुरु राहण्यास अनुमती देऊ नका. हे आपल्या डिव्हाइसवरील कोणत्याही वर्तमान डेटास पुनर्स्थित करेल!"</string> <string name="allow_restore_button_label" msgid="3081286752277127827">"माझा डेटा पुनर्संचयित करा"</string> <string name="deny_restore_button_label" msgid="1724367334453104378">"पुनर्संचयित करू नका"</string> <string name="current_password_text" msgid="8268189555578298067">"कृपया तुमचा वर्तमान बॅकअप संकेतशब्द खाली प्रविष्ट करा:"</string> @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"कृपया तुमचे डिव्हाइस एंक्रिप्शन पासवर्ड खाली एंटर करा. हा बॅकअप संग्रह एंक्रिप्ट करण्यासाठी देखील वापरला जाईल."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"कृपया पूर्ण बॅकअप डेटा एंक्रिप्ट करण्यासाठी वापरण्याकरिता पासवर्ड एंटर करा. हे रिक्त सोडल्यास, तुमचा वर्तमान बॅकअप पासवर्ड वापरला जाईल:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"तुम्ही पूर्ण बॅकअप डेटा एंक्रिप्ट करू इच्छित असल्यास, खालील पासवर्ड एंटर करा:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"तुमचे डिव्हाइस एंक्रिप्ट केले असल्यामुळे, तुम्हाला तुमचा बॅक अप एंक्रिप्ट करणे आवश्यक आहे. कृपया खाली एक पासवर्ड एंटर करा:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"पुनर्स्टोअर केलेला डेटा एंक्रिप्ट केला असल्यास, कृपया पासवर्ड खाली एंटर करा:"</string> <string name="toast_backup_started" msgid="550354281452756121">"बॅकअप सुरू होत आहे..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"बॅकअप समाप्त झाले"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-ms/strings.xml b/packages/BackupRestoreConfirmation/res/values-ms/strings.xml index 65a9ede7482d..78ddd1cff351 100644 --- a/packages/BackupRestoreConfirmation/res/values-ms/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-ms/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"Sila masukkan kata laluan penyulitan peranti anda di bawah. Ini juga akan digunakan untuk menyulitkan arkib sandaran."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"Sila masukkan kata laluan yang hendak digunakan untuk menyulitkan data sandaran lengkap. Jika dibiarkan kosong, kata laluan sandaran semasa anda akan digunakan:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"Jika anda ingin menyulitkan data sandaran lengkap, masukkan kata laluan di bawah:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"Memandangkan peranti anda disulitkan, anda perlu menyulitkan sandaran anda. Sila masukkan kata laluan di bawah:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"Jika pemulihan data disulitkan, sila masukkan kata laluan di bawah:"</string> <string name="toast_backup_started" msgid="550354281452756121">"Sandaran bermula..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"Sandaran selesai"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-my/strings.xml b/packages/BackupRestoreConfirmation/res/values-my/strings.xml index 3072fb061c96..91346499bd2a 100644 --- a/packages/BackupRestoreConfirmation/res/values-my/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-my/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"သင့်စက်၏အသွင်ပြောင်းခြင်းအတွက် စကားဝှက်ကို ထည့်ပါ။ အရန်မှတ်တမ်းတွင်လည်း အသုံးပြုပါမည်။"</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"ဒေတာအားလုံးအားအရန်သိမ်းဆည်းခြင်းပြီးလျှို့ဝှက်အသွင်ပြောင်းခြင်းအတွက် လျှို့ဝှက်နံပါတ်/စာကိုထည့်ပါ။ အကယ်၍ ကွက်လပ်ထားပါက ယခုသင့်လက်ရှိလျှို့ဝှက်စကားဝှက်အား အသုံးပြုပါမည်။"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"အကယ်၍ ဒေတာအားလုံးအားအရန်သိမ်းဆည်းခြင်းကို ဝှက်လိုပါက အောက်တွင်လျှို့ဝှက်နံပါတ်/စာကိုထည့်ပါ။"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"သင်၏ ကိရိယာကို လျှို့ဝျက်ကုဒ် သွင်းထားရာ၊ သင်သည် သင်၏ ဘက်အာပ်ကိုပါ လျှို့ဝျက်ကုဒ် သွင်းရန် လိုအပ်သည်။ ကျေးဇူးပြုပြီး အောက်မှာ စကားဝှက်ကို ထည့်သွင်းပါ:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"အကယ်၍ ပြန်လည်ရယူမည့်ဒေတာမှာလျှို့ဝှက်အသွင်ပြောင်းထားပါက အောက်တွင်စကားဝှက်ကိုထည့်ပါ-"</string> <string name="toast_backup_started" msgid="550354281452756121">"Backupစတင်ပြုလုပ်နေသည်"</string> <string name="toast_backup_ended" msgid="3818080769548726424">"Backupလုပ်ခြင်းပြီးဆုံးပါပြီ"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-nb/strings.xml b/packages/BackupRestoreConfirmation/res/values-nb/strings.xml index d43ec2f25204..8d5bc19260d9 100644 --- a/packages/BackupRestoreConfirmation/res/values-nb/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-nb/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"Skriv inn krypteringspassordet for enheten din nedenfor. Dette brukes også til å kryptere arkivet for sikkerhetskopier."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"Skriv inn et passord for kryptering av full sikkerhetskopi. Hvis feltet er tomt, brukes det gjeldende passordet ditt for sikkerhetskopiering:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"Hvis du vil kryptere alle de sikkerhetskopierte dataene, skriver du inn et passord nedenfor:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"Siden enheten din er kryptert, er du nødt til å kryptere sikkerhetskopien din. Angi et passord nedenfor:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"Hvis de gjenopprettede dataene er krypterte, må du skrive inn passordet nedenfor:"</string> <string name="toast_backup_started" msgid="550354281452756121">"Sikkerhetskopiering er i gang …"</string> <string name="toast_backup_ended" msgid="3818080769548726424">"Sikkerhetskopieringen er fullført"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-ne/strings.xml b/packages/BackupRestoreConfirmation/res/values-ne/strings.xml index 46945e1cd362..2296b9fb72a5 100644 --- a/packages/BackupRestoreConfirmation/res/values-ne/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-ne/strings.xml @@ -25,10 +25,11 @@ <string name="allow_restore_button_label" msgid="3081286752277127827">"मेरो डेटा पुनःबहाली गर्नुहोस्"</string> <string name="deny_restore_button_label" msgid="1724367334453104378">"पुन:स्थापना नगर्नुहोस्"</string> <string name="current_password_text" msgid="8268189555578298067">"कृपया तल तपाईंको हालको ब्याकअप पासवर्ड प्रविष्टि गर्नुहोस्:"</string> - <string name="device_encryption_restore_text" msgid="1570864916855208992">"कृपया तल तपाईंको उपकरण इन्क्रिप्सन पासवर्ड प्रविष्टि गर्नुहोस्:"</string> - <string name="device_encryption_backup_text" msgid="5866590762672844664">"कृपया तल तपाईंको उपकरण इन्क्रिप्सन पासवर्ड प्रविष्टि गर्नुहोस्: यो ब्याकप सँग्रह एन्क्रिप्ट गर्न पनि प्रयोग हुने छ।"</string> + <string name="device_encryption_restore_text" msgid="1570864916855208992">"कृपया तल तपाईंको उपकरण एन्क्रिप्सन पासवर्ड प्रविष्टि गर्नुहोस्:"</string> + <string name="device_encryption_backup_text" msgid="5866590762672844664">"कृपया तल तपाईंको उपकरण एन्क्रिप्सन पासवर्ड प्रविष्टि गर्नुहोस्: यो ब्याकप सँग्रह एन्क्रिप्ट गर्न पनि प्रयोग हुने छ।"</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"ब्याकप डेटालाई encrypt गर्न पासवर्ड प्रविष्टि गर्नुहोस्, यदि यो खालि छोडिएको खण्डमा तपाईको पुरानै पासवर्ड प्रयोग हुने छ।"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"यदि तपाईं पूर्ण ब्याकअप डेटा इन्क्रिप्ट गर्न चाहनु हुन्छ भने तल पासवर्ड प्रविष्टि गर्नुहोस्।"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"तपाईँको उपकरण गुप्तिकरण गरिए देखि, तपाईंले आफ्नो जगेडा गुप्तिकरण गर्न आवश्यक छ। कृपया तल पासवर्ड प्रविष्टि गर्नुहोस्:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"यदि पुनःबहाली डेटा इन्क्रिप्ट छ भने कृपया तल पासवर्ड प्रविष्टि गर्नुहोस्:"</string> <string name="toast_backup_started" msgid="550354281452756121">"जगेडा राख्न सुरु हुँदै..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"ब्याकअप सकियो"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-nl/strings.xml b/packages/BackupRestoreConfirmation/res/values-nl/strings.xml index cb23f317c22a..a1d97462dec4 100644 --- a/packages/BackupRestoreConfirmation/res/values-nl/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-nl/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"Geef hieronder je wachtwoord voor apparaatversleuteling op. Dit wordt ook gebruikt om het back-uparchief te versleutelen."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"Geef een wachtwoord op dat je wilt gebruiken voor het coderen van de gegevens van de volledige back-up. Als je dit leeg laat, wordt je huidige back-upwachtwoord gebruikt:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"Als je de gegevens van de volledige back-up wilt versleutelen, geef je daarvoor hieronder een wachtwoord op:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"Aangezien je apparaat is gecodeerd, moet je je back-up coderen. Geef hieronder een wachtwoord op:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"Als deze herstelgegevens zijn gecodeerd, geef je hieronder het wachtwoord op:"</string> <string name="toast_backup_started" msgid="550354281452756121">"Back-up starten..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"Back-up voltooid"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-or/strings.xml b/packages/BackupRestoreConfirmation/res/values-or/strings.xml index 1c54569d6837..77f3efb62bd8 100644 --- a/packages/BackupRestoreConfirmation/res/values-or/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-or/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"ଦୟାକରି, ତଳେ ନିଜର ଡିଭାଇସ୍ ଏନକ୍ରିପ୍ସନ୍ ପାସ୍ୱର୍ଡ ଦିଅନ୍ତୁ। ବ୍ୟାକଅପ୍ ଆର୍କାଇଭ୍ ଏନ୍କ୍ରିପ୍ଟ କରିବା ପାଇଁ ମଧ୍ୟ ଏହା ବ୍ୟବହୃତ ହେବ।"</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"ପୂର୍ଣ୍ଣ ବ୍ୟାକଅପ୍ ଡାଟାକୁ ଏନକ୍ରୀପ୍ଟ ବ୍ୟବହାର କରିବା ପାଇଁ ଏକ ପାସୱର୍ଡ ଦିଅନ୍ତୁ। ଯଦି ଏହାକୁ ଖାଲି ଛାଡ଼ି ଦିଆଯାଏ, ତେବେ ଆପଣଙ୍କ ବର୍ତ୍ତମାନର ପାସୱର୍ଡ ବ୍ୟବହାର କରାଯିବ।"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"ଯଦି ଆପଣ ସମ୍ପୂର୍ଣ୍ଣ ବ୍ୟାକଅପ୍କୁ ଏନ୍କ୍ରିପ୍ଟ କରିବାକୁ ଚାହାନ୍ତି, ତେବେ ତଳେ ଗୋଟିଏ ପାସ୍ୱର୍ଡ ଦିଅନ୍ତୁ:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"ଆପଣଙ୍କ ଡିଭାଇସ୍କୁ ଏନକ୍ରିପ୍ଟ କରାଯାଇଥିବାରୁ ଆପଣଙ୍କୁ ନିଜ ବ୍ୟାକଅପକୁ ଏନକ୍ରିପ୍ଟ କରିବାକୁ ଦରକାର ପଡ଼ିବ। ଦୟାକରି ତଳେ ପାସ୍ୱର୍ଡ ଲେଖନ୍ତୁ:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"ଯଦି ରିଷ୍ଟୋର୍ ଡାଟା ଏନକ୍ରିପ୍ଟ ହୋଇଯାଇଥାଏ, ତେବେ ତଳେ ପାସ୍ୱର୍ଡ ଲେଖନ୍ତୁ:"</string> <string name="toast_backup_started" msgid="550354281452756121">"ବ୍ୟାକଅପ୍ ଆରମ୍ଭ କରୁଛି..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"ବ୍ୟାକଅପ୍ ସମାପ୍ତ ହେଲା"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-pa/strings.xml b/packages/BackupRestoreConfirmation/res/values-pa/strings.xml index 023ca9eebf86..72513bacabb6 100644 --- a/packages/BackupRestoreConfirmation/res/values-pa/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-pa/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"ਕਿਰਪਾ ਕਰਕੇ ਹੇਠਾਂ ਆਪਣਾ ਡੀਵਾਈਸ ਇਨਕ੍ਰਿਪਸ਼ਨ ਪਾਸਵਰਡ ਦਾਖਲ ਕਰੋ। ਇਹ ਬੈਕਅੱਪ ਪੁਰਾਲੇਖ ਇਨਕ੍ਰਿਪਟ ਕਰਨ ਲਈ ਵੀ ਵਰਤਿਆ ਜਾਏਗਾ।"</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"ਕਿਰਪਾ ਕਰਕੇ ਪੂਰਾ ਬੈਕਅੱਪ ਡਾਟਾ ਇਨਕ੍ਰਿਪਟ ਕਰਨ ਦੀ ਵਰਤੋਂ ਲਈ ਇੱਕ ਪਾਸਵਰਡ ਦਾਖਲ ਕਰੋ। ਜੇਕਰ ਇਸਨੂੰ ਖਾਲੀ ਛੱਡਿਆ ਜਾਂਦਾ ਹੈ, ਤਾਂ ਤੁਹਾਡਾ ਵਰਤਮਾਨ ਬੈਕਅੱਪ ਪਾਸਵਰਡ ਵਰਤਿਆ ਜਾਏਗਾ:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"ਜੇਕਰ ਤੁਸੀਂ ਪੂਰਾ ਬੈਕਅੱਪ ਡਾਟਾ ਇਨਕ੍ਰਿਪਟ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ, ਤਾਂ ਹੇਠਾਂ ਇੱਕ ਪਾਸਵਰਡ ਦਾਖਲ ਕਰੋ:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"ਕਿਉਂਕਿ ਤੁਹਾਡਾ ਡੀਵਾਈਸ ਇਨਕ੍ਰਿਪਟਡ ਹੈ, ਇਸਲਈ ਤੁਹਾਡੇ ਤੋਂ ਆਪਣਾ ਬੈਕਅੱਪ ਇਨਕ੍ਰਿਪਟ ਕਰਨ ਦੀ ਮੰਗ ਕੀਤੀ ਜਾਂਦੀ ਹੈ। ਕਿਰਪਾ ਕਰਕੇ ਹੇਠਾਂ ਇੱਕ ਪਾਸਵਰਡ ਦਾਖਲ ਕਰੋ:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"ਜੇਕਰ ਰੀਸਟੋਰ ਡਾਟਾ ਇਨਕ੍ਰਿਪਟ ਕੀਤਾ ਗਿਆ ਹੈ, ਤਾਂ ਹੇਠਾਂ ਪਾਸਵਰਡ ਦਾਖਲ ਕਰੋ:"</string> <string name="toast_backup_started" msgid="550354281452756121">"ਬੈਕਅੱਪ ਚਾਲੂ ਕਰ ਰਿਹਾ ਹੈ..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"ਬੈਕਅੱਪ ਪੂਰਾ ਹੋਇਆ"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-pl/strings.xml b/packages/BackupRestoreConfirmation/res/values-pl/strings.xml index 122b5dfd10ad..81908b328385 100644 --- a/packages/BackupRestoreConfirmation/res/values-pl/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-pl/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"Wpisz poniżej hasło szyfrowania urządzenia. Służy ono również do szyfrowania archiwum kopii zapasowych."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"Wpisz hasło do zaszyfrowania pełnej kopii zapasowej. Jeśli pozostawisz puste pole, zostanie użyte aktualne hasło kopii zapasowej:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"Jeśli chcesz zaszyfrować pełną kopię zapasową, wprowadź poniżej hasło:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"Ponieważ Twoje urządzenie jest szyfrowane, musisz też zaszyfrować jego kopię zapasową. Wpisz hasło poniżej:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"Jeśli przywracane dane są zaszyfrowane, wpisz poniżej hasło:"</string> <string name="toast_backup_started" msgid="550354281452756121">"Tworzenie kopii zapasowej..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"Utworzono kopię zapasową"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-pt-rBR/strings.xml b/packages/BackupRestoreConfirmation/res/values-pt-rBR/strings.xml index 4107d812f603..d7c56b856e07 100644 --- a/packages/BackupRestoreConfirmation/res/values-pt-rBR/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-pt-rBR/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"Insira sua senha de criptografia do dispositivo abaixo. Ela também será usada para criptografar o arquivo de backup."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"Digite uma senha para usar para criptografar os dados de backup por completo. Se isso for deixado em branco, sua senha atual de backup será usada:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"Se você quer criptografar os dados de backup por completo, digite uma senha abaixo:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"Como seu dispositivo está criptografado, é necessário criptografar seu backup. Insira uma senha abaixo:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"Se os dados restaurados forem criptografada, digite a senha abaixo:"</string> <string name="toast_backup_started" msgid="550354281452756121">"Iniciando backup..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"O backup foi concluído"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-pt-rPT/strings.xml b/packages/BackupRestoreConfirmation/res/values-pt-rPT/strings.xml index a1e61676402a..ecaa06983184 100644 --- a/packages/BackupRestoreConfirmation/res/values-pt-rPT/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-pt-rPT/strings.xml @@ -18,10 +18,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="backup_confirm_title" msgid="827563724209303345">"Cópia de segurança completa"</string> <string name="restore_confirm_title" msgid="5469365809567486602">"Restauro completo"</string> - <string name="backup_confirm_text" msgid="1878021282758896593">"Foi solicitada uma cópia de segurança completa de todos os dados para um computador. Permitir esta operação?\n\nCaso não tenha solicitado a cópia de segurança, não permita que a operação prossiga."</string> + <string name="backup_confirm_text" msgid="1878021282758896593">"Foi solicitada uma cópia de segurança completa de todos os dados para um computador. Pretende permitir esta operação?\n\nCaso não tenha solicitado a cópia de segurança, não permita que a operação prossiga."</string> <string name="allow_backup_button_label" msgid="4217228747769644068">"Fazer cópia de seg. dos dados"</string> <string name="deny_backup_button_label" msgid="6009119115581097708">"Não efetuar cópia de seg."</string> - <string name="restore_confirm_text" msgid="7499866728030461776">"Foi solicitado um restauro completo de todos os dados a partir de um computador. Permitir esta operação?\n\nCaso não tenha solicitado o restauro, não permita que a operação prossiga. Isto substituirá os dados existentes no equipamento!"</string> + <string name="restore_confirm_text" msgid="7499866728030461776">"Foi solicitado um restauro completo de todos os dados a partir de um computador. Pretende permitir esta operação?\n\nCaso não tenha solicitado o restauro, não permita que a operação prossiga. Isto substituirá os dados existentes no equipamento!"</string> <string name="allow_restore_button_label" msgid="3081286752277127827">"Restaurar os meus dados"</string> <string name="deny_restore_button_label" msgid="1724367334453104378">"Não restaurar"</string> <string name="current_password_text" msgid="8268189555578298067">"Introduza a palavra-passe de cópia de segurança atual abaixo:"</string> @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"Introduza a palavra-passe de encriptação do dispositivo abaixo. Esta também será utilizada para encriptar o arquivo da cópia de segurança."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"Introduza uma palavra-passe a utilizar para encriptar os dados da cópia de segurança completa. Se deixar o campo em branco, será utilizada a palavra-passe de cópia de segurança atual."</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"Se pretender encriptar os dados da cópia de segurança completa, introduza uma palavra-passe abaixo:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"Uma vez que o seu dispositivo está encriptado, tem de encriptar a sua cópia de segurança. Introduza uma palavra-passe abaixo:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"Se os dados a restaurar estiverem encriptados, introduza a palavra-passe abaixo:"</string> <string name="toast_backup_started" msgid="550354281452756121">"A iniciar cópia de segurança..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"Cópia de segurança concluída"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-pt/strings.xml b/packages/BackupRestoreConfirmation/res/values-pt/strings.xml index 4107d812f603..d7c56b856e07 100644 --- a/packages/BackupRestoreConfirmation/res/values-pt/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-pt/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"Insira sua senha de criptografia do dispositivo abaixo. Ela também será usada para criptografar o arquivo de backup."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"Digite uma senha para usar para criptografar os dados de backup por completo. Se isso for deixado em branco, sua senha atual de backup será usada:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"Se você quer criptografar os dados de backup por completo, digite uma senha abaixo:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"Como seu dispositivo está criptografado, é necessário criptografar seu backup. Insira uma senha abaixo:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"Se os dados restaurados forem criptografada, digite a senha abaixo:"</string> <string name="toast_backup_started" msgid="550354281452756121">"Iniciando backup..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"O backup foi concluído"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-ro/strings.xml b/packages/BackupRestoreConfirmation/res/values-ro/strings.xml index fccef23bc89d..6a7c266c1d68 100644 --- a/packages/BackupRestoreConfirmation/res/values-ro/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-ro/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"Introduceți mai jos parola de criptare a dispozitivului. Aceasta va fi utilizată, de asemenea, pentru a cripta arhiva copiei de rezervă."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"Introduceți o parolă pentru a o utiliza la criptarea datelor copiei de rezervă complete. Dacă acest câmp rămâne necompletat, pentru copierea de rezervă se va utiliza parola dvs. actuală."</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"Dacă doriți să criptați datele copiei de rezervă complete, introduceți o parolă mai jos:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"Întrucât dispozitivul este criptat, trebuie să criptați backupurile. Introduceți o parolă mai jos:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"Dacă datele pentru restabilire sunt criptate, introduceți parola mai jos:"</string> <string name="toast_backup_started" msgid="550354281452756121">"Se începe copierea de rezervă..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"Copierea de rezervă a fost finalizată"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-ru/strings.xml b/packages/BackupRestoreConfirmation/res/values-ru/strings.xml index f516493899d8..43fcf3b3c33f 100644 --- a/packages/BackupRestoreConfirmation/res/values-ru/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-ru/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"Введите пароль для шифрования устройства и архива резервных копий."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"Введите пароль для шифрования всех резервных данных. Если поле останется пустым, будет использован текущий пароль:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"Чтобы зашифровать все резервные данные, введите пароль:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"На устройстве включено шифрование. Оно будет применено и к резервной копии данных. Введите пароль."</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"Если восстановленные данные зашифрованы, введите пароль:"</string> <string name="toast_backup_started" msgid="550354281452756121">"Резервное копирование..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"Резервное копирование завершено"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-si/strings.xml b/packages/BackupRestoreConfirmation/res/values-si/strings.xml index ed32e73ca23b..cbc130df9c9a 100644 --- a/packages/BackupRestoreConfirmation/res/values-si/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-si/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"කරුණාකර ඔබගේ උපාංගයේ සංකේතන මුරපදය පහත ඇතුලත් කරන්න. සංරක්ෂිත උපස්ථ සංකේතනය කිරීමට මෙය භාවිත කළ හැක."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"කරුණාකර සියලු උපස්ථ දත්ත සංකේතනය කිරීම සඳහා භාවිතයට මුරපදයක් ඇතුළත් කරන්න. මෙය හිස්ව තැබුවොත්, ඔබගේ වර්තමාන උපස්ථ මුරපදය භාවිත වෙයි:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"සියලු උපස්ථ දත්ත සංකේතනය කිරීමට ඔබ අදහස් කරන්නේ නම්, මුරපදය පහලින් ඇතුලත් කරන්න:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"ඔබගේ උපාංගය සංකේතනය කර තිබෙන නිසා, ඔබගේ උපස්ථය සංකේතනය ඔබට අවශ්ය වී තිබේ. මුරපදය පහළින් එක් කරන්න:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"යළි පිහිටුවන දත්ත සංකේතනය කරන ලද ඒවානම්, කරුණාකර මුරපදය පහලින් ඇතුල් කරන්න:"</string> <string name="toast_backup_started" msgid="550354281452756121">"උපස්ථ කිරීම ආරම්භ කරමින්..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"උපස්ථය අවසන්"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-sk/strings.xml b/packages/BackupRestoreConfirmation/res/values-sk/strings.xml index 668394c0086a..44d01deafe6b 100644 --- a/packages/BackupRestoreConfirmation/res/values-sk/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-sk/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"Zadajte svoje heslo na šifrovanie zariadenia nižšie. Bude tiež použité na šifrovanie archívu zálohy."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"Zadajte heslo, ktoré sa použije pri šifrovaní údajov úplnej zálohy. Ak pole ponecháte prázdne, použije sa vaše aktuálne heslo zálohy:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"Ak chcete šifrovať údaje úplnej zálohy, zadajte heslo nižšie:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"Pretože je vaše zariadenie šifrované, musíte zašifrovať aj svoju zálohu. Zadajte heslo nižšie:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"Ak sú údaje obnovenia šifrované, zadajte heslo nižšie:"</string> <string name="toast_backup_started" msgid="550354281452756121">"Vytváranie zálohy..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"Zálohovanie bolo dokončené"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-sl/strings.xml b/packages/BackupRestoreConfirmation/res/values-sl/strings.xml index 17d4d8043882..80551d6c59d7 100644 --- a/packages/BackupRestoreConfirmation/res/values-sl/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-sl/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"Vnesite geslo za šifriranje naprave spodaj. Uporabljeno bo tudi za šifriranje arhiva varnostnih kopij."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"Vnesite geslo za šifriranje podatkov popolnega varnostnega kopiranja. Če to pustite prazno, bo uporabljeno trenutno geslo za varnostno kopiranje:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"Če želite šifrirati vse varnostno kopirane podatke, spodaj vnesite geslo:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"Vaša naprava je šifrirana, zato morate šifrirati varnostno kopirane podatke. Spodaj vnesite geslo:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"Če so podatki za obnovitev šifrirani, spodaj vnesite geslo:"</string> <string name="toast_backup_started" msgid="550354281452756121">"Varnostno kopiranje se začenja ..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"Varnostno kopiranje končano"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-sq/strings.xml b/packages/BackupRestoreConfirmation/res/values-sq/strings.xml index 628d951dfa44..c0e0e0daa581 100644 --- a/packages/BackupRestoreConfirmation/res/values-sq/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-sq/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"Fut fjalëkalimin e enkriptimit të pajisjes tënde më poshtë. Ai do të përdoret gjithashtu për të enkriptuar arkivin e rezervimit."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"Fut një fjalëkalim për të enkriptuar të dhënat e rezervimit të plotë. Nëse hapësira lihet bosh, do të përdoret fjalëkalimi aktual i rezervimit:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"Nëse dëshiron të enkriptosh të dhënat e plota të rezervimit, fut një fjalëkalim më poshtë:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"Meqenëse pajisja jote është e enkriptuar, të kërkohet ta enkriptosh rezervimin tënd. Fut një fjalëkalim më poshtë:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"Nëse të dhënat e restaurimit janë të enkriptuara, fut një fjalëkalim më poshtë:"</string> <string name="toast_backup_started" msgid="550354281452756121">"Rezervimi po fillon..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"Rezervimi përfundoi"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-sr/strings.xml b/packages/BackupRestoreConfirmation/res/values-sr/strings.xml index e7bdd2f84bc8..7f48e48e1c15 100644 --- a/packages/BackupRestoreConfirmation/res/values-sr/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-sr/strings.xml @@ -18,10 +18,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="backup_confirm_title" msgid="827563724209303345">"Резервна копије свих података"</string> <string name="restore_confirm_title" msgid="5469365809567486602">"Потпуно враћање"</string> - <string name="backup_confirm_text" msgid="1878021282758896593">"Захтевана је потпуна резервна копија свих података на повезани рачунар. Да ли желите да дозволите то?\n\nАко нисте лично захтевали резервну копију, не дозвољавајте наставак радње."</string> + <string name="backup_confirm_text" msgid="1878021282758896593">"Захтевана је потпуна резервна копија свих података на повезани стони рачунар. Да ли желите да дозволите то?\n\nАко нисте лично захтевали резервну копију, не дозвољавајте наставак радње."</string> <string name="allow_backup_button_label" msgid="4217228747769644068">"Направи резервну копију мојих података"</string> <string name="deny_backup_button_label" msgid="6009119115581097708">"Не прави резервне копије"</string> - <string name="restore_confirm_text" msgid="7499866728030461776">"Захтевано је потпуно враћање свих података са повезаног рачунара. Да ли желите да дозволите то?\n\nАко нисте лично захтевали враћање, не дозвољавајте наставак радње. Тиме ћете заменити све податке који су тренутно на уређају!"</string> + <string name="restore_confirm_text" msgid="7499866728030461776">"Захтевано је потпуно враћање свих података са повезаног стоног рачунара. Да ли желите да дозволите то?\n\nАко нисте лично захтевали враћање, не дозвољавајте наставак радње. Тиме ћете заменити све податке који су тренутно на уређају!"</string> <string name="allow_restore_button_label" msgid="3081286752277127827">"Врати моје податке"</string> <string name="deny_restore_button_label" msgid="1724367334453104378">"Не враћај"</string> <string name="current_password_text" msgid="8268189555578298067">"Унесите тренутну лозинку резервне копије у наставку:"</string> @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"Унесите лозинку уређаја за шифровање. Ово ће се користити и за шифровање резервне архиве."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"Унесите лозинку коју ћете користити за шифровање података потпуне резервне копије. Ако то поље оставите празно, користиће се тренутна лозинка резервне копије:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"Ако желите да шифрујете податке потпуне резервне копије, унесите лозинку у наставку."</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"Пошто вам је уређај шифрован, морате да шифрујете резервну копију. Унесите лозинку у наставку:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"Ако су подаци за враћање шифровани, унесите лозинку у наставку:"</string> <string name="toast_backup_started" msgid="550354281452756121">"Покретање прављења резервне копије..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"Резервна копија је направљена"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-sv/strings.xml b/packages/BackupRestoreConfirmation/res/values-sv/strings.xml index e4b1a133bb33..dee8bc2e88ba 100644 --- a/packages/BackupRestoreConfirmation/res/values-sv/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-sv/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"Ange lösenordet för enhetskryptering nedan. Lösenordet kommer även att användas för att kryptera säkerhetskopian."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"Ange ett lösenord för kryptering av alla säkerhetskopierade data. Om det här lämnas tomt kommer ditt nuvarande lösenord för säkerhetskopior att användas:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"Om du vill kryptera alla säkerhetskopierade data anger du ett lösenord nedan:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"Eftersom enheten är krypterad måste du kryptera säkerhetskopierade data. Ange lösenordet nedan:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"Om återställda data är krypterade anger du lösenordet nedan:"</string> <string name="toast_backup_started" msgid="550354281452756121">"Säkerhetskopieringen har startat ..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"Säkerhetskopieringen har slutförts"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-sw/strings.xml b/packages/BackupRestoreConfirmation/res/values-sw/strings.xml index e4f118531a5b..ed75344d7fbb 100644 --- a/packages/BackupRestoreConfirmation/res/values-sw/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-sw/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"Tafadhali weka nenosiri lako la kusimba kifaa kwa njia fiche hapo chini. Pia litatumika kusimba kumbukumbu za nakala kwa njia fiche."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"Tafadhali weka nenosiri la kutumia katika kusimba nakala kamili za data kwa njia fiche. Ikiwa sehemu hii itawachwa wazi, nenosiri lako la sasa litatumika:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"Ikiwa unataka kusimba nakala za data kwa njia fiche, weka nenosiri hapo chini:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"Kwa kuwa kifaa chako kimesimbwa kwa njia fiche, unatakiwa usimbe hifadhi rudufu yako kwa njia fiche. Tafadhali weka nenosiri hapo chini:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"Ikiwa data imesimbwa kwa njia fiche, tafadhali weka nenosiri lake hapo chini:"</string> <string name="toast_backup_started" msgid="550354281452756121">"Inaanza kuhifadhi..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"Imemaliza kuhifadhi"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-ta/strings.xml b/packages/BackupRestoreConfirmation/res/values-ta/strings.xml index 507aae103680..fc34482f6d4e 100644 --- a/packages/BackupRestoreConfirmation/res/values-ta/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-ta/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"சாதனம் என்க்ரிப்ட் செய்யும் கடவுச்சொல்லைக் கீழே உள்ளிடவும். இது காப்புப் பிரதி இயக்ககத்தை என்க்ரிப்ட் செய்யவும் பயன்படுத்தப்படும்."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"காப்புப் பிரதி எடுக்கப்பட்ட முழு தரவையும் என்க்ரிப்ட் செய்ய கடவுச்சொல்லை உள்ளிடவும். இதைக் காலியாக விட்டால், உங்கள் தற்போதைய காப்புப் பிரதி கடவுச்சொல் பயன்படுத்தப்படும்:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"காப்புப் பிரதி எடுக்கப்பட்ட முழு தரவையும் என்க்ரிப்ட் செய்ய விரும்பினால், கடவுச்சொல்லை உள்ளிடவும்:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"சாதனம் மறையாக்கப்பட்டுள்ளதால், காப்புப்பிரதியையும் மறையாக்க வேண்டும். கீழே கடவுச்சொல்லை உள்ளிடவும்:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"மீட்டமைக்கப்பட்ட தரவு முறைமையாக்கப்பட்டிருந்தால், கீழே கடவுச்சொல்லை உள்ளிடவும்:"</string> <string name="toast_backup_started" msgid="550354281452756121">"காப்புப் பிரதி எடுக்க தொடங்குகிறது..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"காப்புப் பிரதி எடுப்பது முடிந்தது"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-te/strings.xml b/packages/BackupRestoreConfirmation/res/values-te/strings.xml index 2b4806c55e03..35e9492a0683 100644 --- a/packages/BackupRestoreConfirmation/res/values-te/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-te/strings.xml @@ -18,10 +18,10 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="backup_confirm_title" msgid="827563724209303345">"పూర్తి బ్యాకప్"</string> <string name="restore_confirm_title" msgid="5469365809567486602">"పూర్తి పునరుద్ధరణ"</string> - <string name="backup_confirm_text" msgid="1878021282758896593">"కనెక్ట్ చేసిన డెస్క్టాప్ కంప్యూటర్లో మొత్తం డేటాను పూర్తిగా బ్యాకప్ చేయాలని రిక్వెస్ట్ అందింది. మీరు ఇలా చేయడానికి అనుమతించాలనుకుంటున్నారా?\n\nబ్యాకప్ను మీరు అభ్యర్థించి ఉండకపోతే, ఆ చర్య చేయడానికి అనుమతించవద్దు."</string> + <string name="backup_confirm_text" msgid="1878021282758896593">"కనెక్ట్ చేసిన డెస్క్టాప్ కంప్యూటర్లో మొత్తం డేటాను పూర్తిగా బ్యాకప్ చేయాలని అభ్యర్థన అందింది. మీరు ఇలా చేయడానికి అనుమతించాలనుకుంటున్నారా?\n\nబ్యాకప్ను మీరు అభ్యర్థించి ఉండకపోతే, ఆ చర్య చేయడానికి అనుమతించవద్దు."</string> <string name="allow_backup_button_label" msgid="4217228747769644068">"నా డేటాను బ్యాకప్ చేయి"</string> <string name="deny_backup_button_label" msgid="6009119115581097708">"బ్యాకప్ చేయవద్దు"</string> - <string name="restore_confirm_text" msgid="7499866728030461776">"కనెక్ట్ చేసిన డెస్క్టాప్ కంప్యూటర్ నుండి మొత్తం డేటాను పూర్తిగా పునరుద్ధరించాలని రిక్వెస్ట్ అందింది. మీరు ఇలా చేయడానికి అనుమతించాలనుకుంటున్నారా?\n\nపునరుద్ధరణను మీరు అభ్యర్థించి ఉండకపోతే, ఆ చర్య చేయడానికి అనుమతించవద్దు. దీని వల్ల ప్రస్తుతం పరికరంలో ఉన్న డేటా ఏదైనా భర్తీ చేయబడుతుంది!"</string> + <string name="restore_confirm_text" msgid="7499866728030461776">"కనెక్ట్ చేసిన డెస్క్టాప్ కంప్యూటర్ నుండి మొత్తం డేటాను పూర్తిగా పునరుద్ధరించాలని అభ్యర్థన అందింది. మీరు ఇలా చేయడానికి అనుమతించాలనుకుంటున్నారా?\n\nపునరుద్ధరణను మీరు అభ్యర్థించి ఉండకపోతే, ఆ చర్య చేయడానికి అనుమతించవద్దు. దీని వల్ల ప్రస్తుతం పరికరంలో ఉన్న డేటా ఏదైనా భర్తీ చేయబడుతుంది!"</string> <string name="allow_restore_button_label" msgid="3081286752277127827">"నా డేటాను పునరుద్ధరించు"</string> <string name="deny_restore_button_label" msgid="1724367334453104378">"పునరుద్ధరించవద్దు"</string> <string name="current_password_text" msgid="8268189555578298067">"దయచేసి దిగువ మీ ప్రస్తుత బ్యాకప్ పాస్వర్డ్ను నమోదు చేయండి:"</string> @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"దయచేసి దిగువ మీ పరికర ఎన్క్రిప్షన్ పాస్వర్డ్ను నమోదు చేయండి. ఇది బ్యాకప్ ఆర్కైవ్ను ఎన్క్రిప్ట్ చేయడానికి కూడా ఉపయోగించబడుతుంది."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"దయచేసి పూర్తి బ్యాకప్ డేటాను గుప్తీకరించడం కోసం ఉపయోగించడానికి పాస్వర్డ్ను నమోదు చేయండి. దీన్ని ఖాళీగా వదిలిపెడితే, మీ ప్రస్తుత బ్యాకప్ పాస్వర్డ్ ఉపయోగించబడుతుంది:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"మీరు పూర్తి బ్యాకప్ డేటాను గుప్తీకరించాలని కోరుకుంటున్నట్లయితే, దిగువ పాస్వర్డ్ను నమోదు చేయండి:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"మీ పరికరం గుప్తీకరించబడినందున, మీరు మీ బ్యాకప్ని గుప్తీకరించాల్సి ఉంటుంది. దయచేసి దిగువ పాస్వర్డ్ని నమోదు చేయండి:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"పునరుద్ధరణ డేటా గుప్తీకరించబడుంటే, దయచేసి దిగువ పాస్వర్డ్ను నమోదు చేయండి:"</string> <string name="toast_backup_started" msgid="550354281452756121">"బ్యాకప్ ప్రారంభమవుతోంది..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"బ్యాకప్ పూర్తయింది"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-th/strings.xml b/packages/BackupRestoreConfirmation/res/values-th/strings.xml index c0543a026dc5..a79cc6f280dc 100644 --- a/packages/BackupRestoreConfirmation/res/values-th/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-th/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"โปรดป้อนรหัสผ่านการเข้ารหัสอุปกรณ์ของคุณด้านล่างนี้ ซึ่งจะใช้ในการเข้ารหัสที่เก็บข้อมูลสำรองด้วย"</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"โปรดป้อนรหัสผ่านเพื่อใช้สำหรับเข้ารหัสข้อมูลที่สำรองแบบเต็มรูปแบบ หากเว้นว่างไว้ รหัสผ่านการสำรองข้อมูลปัจจุบันของคุณจะถูกใช้:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"หากคุณต้องการเข้ารหัสข้อมูลที่สำรองเต็มรูปแบบ โปรดป้อนรหัสผ่านด้านล่างนี้:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"เนื่องจากอุปกรณ์ของคุณมีการเข้ารหัสไว้ คุณจึงต้องเข้ารหัสการสำรองข้อมูล โปรดป้อนรหัสผ่านด้านล่าง:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"หากมีการเข้ารหัสข้อมูลที่คืนค่า โปรดป้อนรหัสผ่านด้านล่างนี้:"</string> <string name="toast_backup_started" msgid="550354281452756121">"กำลังเริ่มการสำรองข้อมูล..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"สำรองข้อมูลเสร็จแล้ว"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-tl/strings.xml b/packages/BackupRestoreConfirmation/res/values-tl/strings.xml index 5c564bafc18f..dac816b180aa 100644 --- a/packages/BackupRestoreConfirmation/res/values-tl/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-tl/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"Mangyaring ilagay ang password ng pag-encrypt ng iyong device sa ibaba. Gagamitin rin ito upang i-encrypt ang backup na archive."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"Mangyaring maglagay ng password na gamitin sa pag-e-encrypt ng buong data sa pag-backup. Kung iiwanan itong blangko, gagamitin ang iyong kasalukuyang backup na password:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"Kung nais mong i-encrypt ang buong data ng backup, maglagay ng password sa ibaba:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"Dahil naka-encrypt ang iyong device, hinihiling sa iyo na i-encrypt ang iyong backup. Pakilagay ang password sa ibaba:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"Kung naka-encrypt ang data sa pagpapanumbalik, pakilagay ang password sa ibaba:"</string> <string name="toast_backup_started" msgid="550354281452756121">"Sinisimulan ang pag-backup..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"Tapos na ang pag-backup"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-tr/strings.xml b/packages/BackupRestoreConfirmation/res/values-tr/strings.xml index 591be7c63fd8..ee0c483ee52a 100644 --- a/packages/BackupRestoreConfirmation/res/values-tr/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-tr/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"Lütfen cihazınızı şifrelemek için kullandığınız şifreyi aşağıya girin. Bu şifre aynı zamanda yedekleme arşivini şifrelemek için de kullanılacaktır."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"Tam yedekleme verilerini şifrelemek için lütfen bir şifre girin. Boş bırakılırsa, mevcut yedekleme şifreniz kullanılır:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"Yedeklenen tüm verileri şifrelemek isterseniz, aşağıya bir şifre girin:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"Cihazınız şifrelenmiş olduğundan yedeklemenizi şifrelemeniz gerekmektedir. Lütfen şifreyi aşağıya girin:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"Geri yükleme verileri şifreliyse, lütfen şifreyi aşağıya girin:"</string> <string name="toast_backup_started" msgid="550354281452756121">"Yedekleme başlıyor..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"Yedekleme işlemi sona erdi"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-uk/strings.xml b/packages/BackupRestoreConfirmation/res/values-uk/strings.xml index b4ddef1ed2ce..f3d529e167db 100644 --- a/packages/BackupRestoreConfirmation/res/values-uk/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-uk/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"Нижче введіть свій пароль шифрування пристрою. Він також використовуватиметься для шифрування архіву резервної копії."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"Введіть пароль, який використовується для шифрування повного резервного копіювання даних. Якщо залишити це поле порожнім, буде використано поточний пароль резервного копіювання."</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"Якщо ви хочете зашифрувати повне резервне копіювання даних, введіть пароль нижче:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"Оскільки ваш пристрій зашифровано, потрібно також зашифрувати резервну копію даних. Введіть пароль нижче."</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"Якщо дані для відновлення зашифровано, введіть пароль нижче:"</string> <string name="toast_backup_started" msgid="550354281452756121">"Початок резервного копіювання..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"Резервне копіювання закінчено"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-ur/strings.xml b/packages/BackupRestoreConfirmation/res/values-ur/strings.xml index 8c6cc480ea50..6f1c9b57582a 100644 --- a/packages/BackupRestoreConfirmation/res/values-ur/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-ur/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"براہ کرم ذیل میں اپنے آلہ کی مرموز کاری کا پاس ورڈ درج کریں۔ یہ بیک اپ آرکائیو کی مرموز کاری کرنے کیلئے بھی استعمال کیا جائے گا۔"</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"مکمل بیک اپ ڈیٹا کی مرموز کاری کرنے کیلئے استعمال کیلئے براہ کرم ایک پاس ورڈ درج کریں۔ اگر یہ خالی رہتا ہے تو آپ کا موجودہ بیک اپ پاس ورڈ استعمال کیا جائے گا:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"اگر آپ مکمل بیک اپ ڈیٹا کی مرموز کاری کرنا چاہتے ہیں تو ذیل میں ایک پاس ورڈ درج کریں:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"چونکہ آپ کا آلہ مرموز کردہ ہے، آپ کو اپنے بیک اپ کی مرموز کاری کرنے کی ضرورت ہے۔ براہ کرم ذیل میں ایک پاس ورڈ درج کریں:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"اگر بحال ہونے والا ڈیٹا مرموز کردہ ہے تو براہ کرم ذیل میں پاس ورڈ درج کریں:"</string> <string name="toast_backup_started" msgid="550354281452756121">"بیک اپ شروع ہو رہا ہے…"</string> <string name="toast_backup_ended" msgid="3818080769548726424">"بیک اپ مکمل ہو گیا"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-uz/strings.xml b/packages/BackupRestoreConfirmation/res/values-uz/strings.xml index 5a12e4dabef8..213b31ff66a0 100644 --- a/packages/BackupRestoreConfirmation/res/values-uz/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-uz/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"Qurilmangizning shifr parolini kiriting. U zahira arxivni shifrlash uchun ham ishlatiladi."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"To‘liq zahira fayllarini shifrlash uchun parol kiriting. Agar bo‘sh qoldirsangiz, joriy zahiralash parolingizdan foydalaniladi:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"To‘liq zahira ma’lumotlarini shifrlashni xohlasangiz, quyidagi parolni kiriting:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"Qurilmangiz shifrlangani bois ma’lumotlaringizning zaxira nusxasini ham shifrlash zarur. Shifrlash uchun parolni kiriting:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"Agar tiklash ma’lumoti shifrlangan bo‘lsa, pastga parolni kiriting:"</string> <string name="toast_backup_started" msgid="550354281452756121">"Zahiralash jarayoni boshlandi..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"Zahiralash jarayoni bajarildi"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-vi/strings.xml b/packages/BackupRestoreConfirmation/res/values-vi/strings.xml index 69e8f9c57cd7..264164f6de20 100644 --- a/packages/BackupRestoreConfirmation/res/values-vi/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-vi/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"Vui lòng nhập mật khẩu mã hóa thiết bị của bạn bên dưới. Mật khẩu này cũng được sử dụng để mã hóa kho lưu trữ sao lưu."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"Vui lòng nhập mật khẩu dùng để mã hóa toàn bộ dữ liệu sao lưu. Nếu trường này bị bỏ trống, mật khẩu sao lưu hiện tại của bạn sẽ được sử dụng:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"Nếu bạn muốn mã hóa toàn bộ dữ liệu sao lưu, hãy nhập mật khẩu bên dưới:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"Vì thiết bị của bạn được mã hóa nên bạn phải mã hóa bản sao lưu của mình. Vui lòng nhập mật khẩu bên dưới:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"Nếu dữ liệu khôi phục được mã hóa, vui lòng nhập mật khẩu bên dưới:"</string> <string name="toast_backup_started" msgid="550354281452756121">"Đang bắt đầu sao lưu..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"Đã hoàn thành sao lưu"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-zh-rCN/strings.xml b/packages/BackupRestoreConfirmation/res/values-zh-rCN/strings.xml index dbc6bd4e73f7..23688aec9ace 100644 --- a/packages/BackupRestoreConfirmation/res/values-zh-rCN/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-zh-rCN/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"请在下方输入您的设备加密密码。此密码还会用于加密备份存档。"</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"请输入用于加密完整备份数据的密码。如果留空,系统将会使用您当前的备份密码:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"如果您想为整个备份数据加密,请在下方输入密码:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"由于您的设备进行了加密,因此您需要加密备份。请在下方输入密码:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"如果恢复数据已加密,请在下方输入密码:"</string> <string name="toast_backup_started" msgid="550354281452756121">"开始备份..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"备份已完成"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-zh-rHK/strings.xml b/packages/BackupRestoreConfirmation/res/values-zh-rHK/strings.xml index d3bcd6e97582..c6180d2412c7 100644 --- a/packages/BackupRestoreConfirmation/res/values-zh-rHK/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-zh-rHK/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"請在下面輸入您的裝置加密密碼,這也會用來將封存備份加密。"</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"請輸入為完整備份資料加密的專用密碼。如果留空,系統將使用您目前的備份密碼:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"如果您想將完整的備份資料加密,請在下面輸入一組密碼:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"您的裝置已加密,因此您必須將您的備份加密。請在下方輸入密碼:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"如果還原的資料經過加密處理,請在下面輸入密碼:"</string> <string name="toast_backup_started" msgid="550354281452756121">"正在開始備份..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"備份完畢"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-zh-rTW/strings.xml b/packages/BackupRestoreConfirmation/res/values-zh-rTW/strings.xml index 4ad3126be05f..ce3208e9bbe2 100644 --- a/packages/BackupRestoreConfirmation/res/values-zh-rTW/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-zh-rTW/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"請在下方輸入你的裝置加密密碼,這也會用來加密備份封存檔。"</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"請輸入完整備份資料加密專用的密碼。如果你沒有輸入密碼,系統會使用你目前的備用密碼:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"如果你想要將完整備份資料進行加密,請在下面輸入一組密碼:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"由於你的裝置已加密,因此你必須為你的備份加密。請在下方輸入密碼:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"如果還原的資料經過加密處理,請在下面輸入密碼:"</string> <string name="toast_backup_started" msgid="550354281452756121">"正在開始備份..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"備份完畢"</string> diff --git a/packages/BackupRestoreConfirmation/res/values-zu/strings.xml b/packages/BackupRestoreConfirmation/res/values-zu/strings.xml index 955b26f88c6f..90259e1a6b45 100644 --- a/packages/BackupRestoreConfirmation/res/values-zu/strings.xml +++ b/packages/BackupRestoreConfirmation/res/values-zu/strings.xml @@ -29,6 +29,7 @@ <string name="device_encryption_backup_text" msgid="5866590762672844664">"Uyacelwa ukuba ufake iphasiwedi efakwe kudivayisi yakho ngezansi. lokhu kuzosetshenziswa ukufaka kusilondoloza sokusiza lapho kudingeka."</string> <string name="backup_enc_password_text" msgid="4981585714795233099">"Sicela ufake iphasiwedi ezosetshenziselwa ukubhala ngokufihlekileyo imininingo eyesekwe ngokulondoloza. Uma lokhu kushiywe kungabhalwe lutho, kuzosetshenziswa iphasiwedi yokweseka ngokulondoloza yamanje:"</string> <string name="backup_enc_password_optional" msgid="1350137345907579306">"Uma ufuna ukufaka ikhowudi kwimininingo yonke eyesekelwe ngokulondoloza faka i-passowrd engezansi:"</string> + <string name="backup_enc_password_required" msgid="7889652203371654149">"Njengoba idivayisi yakho ibethelwe, kudingeka ukuthi ubethele isipele sakho. Sicela ufake iphasiwedi ngezansi:"</string> <string name="restore_enc_password_text" msgid="6140898525580710823">"Uma uhlelo lokusebenza yokubuyiselwa esimweni kwmininingo ibhalwe ngokufihlekileyo, sicela ufake iphasiwedi engezansi:"</string> <string name="toast_backup_started" msgid="550354281452756121">"Ukulondoloza kuyaqala..."</string> <string name="toast_backup_ended" msgid="3818080769548726424">"Ukulondoloza kuphelile"</string> diff --git a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java index 86604a2cd085..610e3d5f3af9 100644 --- a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java @@ -165,6 +165,31 @@ public class InfoMediaManager extends MediaManager { return sessionInfos.get(sessionInfos.size() - 1); } + boolean isRoutingSessionAvailableForVolumeControl() { + if (mVolumeAdjustmentForRemoteGroupSessions) { + return true; + } + List<RoutingSessionInfo> sessions = + mRouterManager.getRoutingSessions(mPackageName); + boolean foundNonSystemSession = false; + boolean isGroup = false; + for (RoutingSessionInfo session : sessions) { + if (!session.isSystemSession()) { + foundNonSystemSession = true; + int selectedRouteCount = session.getSelectedRoutes().size(); + if (selectedRouteCount > 1) { + isGroup = true; + break; + } + } + } + if (!foundNonSystemSession) { + Log.d(TAG, "No routing session for " + mPackageName); + return false; + } + return !isGroup; + } + /** * Remove a {@code device} from current media. * diff --git a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java index 865c2f0bc836..c8db65494382 100644 --- a/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/media/LocalMediaManager.java @@ -172,8 +172,8 @@ public class LocalMediaManager implements BluetoothCallback { } } - if (device == mCurrentConnectedDevice) { - Log.d(TAG, "connectDevice() this device all ready connected! : " + device.getName()); + if (device.equals(mCurrentConnectedDevice)) { + Log.d(TAG, "connectDevice() this device is already connected! : " + device.getName()); return false; } @@ -197,6 +197,14 @@ public class LocalMediaManager implements BluetoothCallback { } /** + * Returns if the media session is available for volume control. + * @return True if this media session is available for colume control, false otherwise. + */ + public boolean isMediaSessionAvailableForVolumeControl() { + return mInfoMediaManager.isRoutingSessionAvailableForVolumeControl(); + } + + /** * Start scan connected MediaDevice */ public void startScan() { diff --git a/packages/SettingsLib/src/com/android/settingslib/users/EditUserPhotoController.java b/packages/SettingsLib/src/com/android/settingslib/users/EditUserPhotoController.java index f9584a3e15e9..c346142c20f6 100644 --- a/packages/SettingsLib/src/com/android/settingslib/users/EditUserPhotoController.java +++ b/packages/SettingsLib/src/com/android/settingslib/users/EditUserPhotoController.java @@ -21,6 +21,8 @@ import android.content.ClipData; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; +import android.content.pm.ActivityInfo; +import android.content.pm.PackageManager; import android.database.Cursor; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; @@ -83,6 +85,7 @@ public class EditUserPhotoController { private static final int DEFAULT_PHOTO_SIZE = 500; private static final String IMAGES_DIR = "multi_user"; + private static final String PRE_CROP_PICTURE_FILE_NAME = "PreCropEditUserPhoto.jpg"; private static final String CROP_PICTURE_FILE_NAME = "CropEditUserPhoto.jpg"; private static final String TAKE_PICTURE_FILE_NAME = "TakeEditUserPhoto.jpg"; private static final String NEW_USER_PHOTO_FILE_NAME = "NewUserPhoto.png"; @@ -95,6 +98,7 @@ public class EditUserPhotoController { private final String mFileAuthority; private final File mImagesDir; + private final Uri mPreCropPictureUri; private final Uri mCropPictureUri; private final Uri mTakePictureUri; @@ -110,6 +114,7 @@ public class EditUserPhotoController { mImagesDir = new File(activity.getCacheDir(), IMAGES_DIR); mImagesDir.mkdir(); + mPreCropPictureUri = createTempImageUri(activity, PRE_CROP_PICTURE_FILE_NAME, !waiting); mCropPictureUri = createTempImageUri(activity, CROP_PICTURE_FILE_NAME, !waiting); mTakePictureUri = createTempImageUri(activity, TAKE_PICTURE_FILE_NAME, !waiting); mPhotoSize = getPhotoSize(activity); @@ -143,7 +148,7 @@ public class EditUserPhotoController { case REQUEST_CODE_CHOOSE_PHOTO: if (mTakePictureUri.equals(pictureUri)) { if (PhotoCapabilityUtils.canCropPhoto(mActivity)) { - cropPhoto(); + cropPhoto(pictureUri); } else { onPhotoNotCropped(pictureUri); } @@ -224,7 +229,7 @@ public class EditUserPhotoController { protected Void doInBackground(Void... params) { final ContentResolver cr = mActivity.getContentResolver(); try (InputStream in = cr.openInputStream(pictureUri); - OutputStream out = cr.openOutputStream(mTakePictureUri)) { + OutputStream out = cr.openOutputStream(mPreCropPictureUri)) { Streams.copy(in, out); } catch (IOException e) { Log.w(TAG, "Failed to copy photo", e); @@ -235,28 +240,41 @@ public class EditUserPhotoController { @Override protected void onPostExecute(Void result) { if (!mActivity.isFinishing() && !mActivity.isDestroyed()) { - cropPhoto(); + cropPhoto(mPreCropPictureUri); } } }.execute(); } - private void cropPhoto() { + private void cropPhoto(final Uri pictureUri) { // TODO: Use a public intent, when there is one. Intent intent = new Intent("com.android.camera.action.CROP"); - intent.setDataAndType(mTakePictureUri, "image/*"); + intent.setDataAndType(pictureUri, "image/*"); appendOutputExtra(intent, mCropPictureUri); appendCropExtras(intent); - if (intent.resolveActivity(mActivity.getPackageManager()) != null) { - try { - StrictMode.disableDeathOnFileUriExposure(); - mActivityStarter.startActivityForResult(intent, REQUEST_CODE_CROP_PHOTO); - } finally { - StrictMode.enableDeathOnFileUriExposure(); + try { + StrictMode.disableDeathOnFileUriExposure(); + if (startSystemActivityForResult(intent, REQUEST_CODE_CROP_PHOTO)) { + return; } - } else { - onPhotoNotCropped(mTakePictureUri); + } finally { + StrictMode.enableDeathOnFileUriExposure(); + } + + onPhotoNotCropped(mTakePictureUri); + + } + + private boolean startSystemActivityForResult(Intent intent, int code) { + ActivityInfo info = intent.resolveActivityInfo(mActivity.getPackageManager(), + PackageManager.MATCH_SYSTEM_ONLY); + if (info == null) { + Log.w(TAG, "No system package activity could be found for code " + code); + return false; } + intent.setPackage(info.packageName); + mActivityStarter.startActivityForResult(intent, code); + return true; } private void appendOutputExtra(Intent intent, Uri pictureUri) { diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java index 77fff0f08d4c..a150dbf18a49 100644 --- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java +++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java @@ -192,5 +192,6 @@ public class SecureSettings { Settings.Secure.LOCKSCREEN_SHOW_CONTROLS, Settings.Secure.LOCKSCREEN_SHOW_WALLET, Settings.Secure.LOCKSCREEN_USE_DOUBLE_LINE_CLOCK, + Settings.Secure.STATUS_BAR_SHOW_VIBRATE_ICON }; } diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java index d0448ef63793..389d271043ba 100644 --- a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java +++ b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java @@ -21,6 +21,7 @@ import static android.provider.settings.validators.SettingsValidators.ANY_INTEGE import static android.provider.settings.validators.SettingsValidators.ANY_STRING_VALIDATOR; import static android.provider.settings.validators.SettingsValidators.BOOLEAN_VALIDATOR; import static android.provider.settings.validators.SettingsValidators.NONE_NEGATIVE_LONG_VALIDATOR; +import static android.provider.settings.validators.SettingsValidators.NON_NEGATIVE_INTEGER_VALIDATOR; import static android.provider.settings.validators.SettingsValidators.PACKAGE_NAME_VALIDATOR; import static android.provider.settings.validators.SettingsValidators.PERCENTAGE_INTEGER_VALIDATOR; import static android.view.Display.HdrCapabilities.HDR_TYPES; @@ -83,6 +84,8 @@ public class GlobalSettingsValidators { VALIDATORS.put(Global.WIFI_WATCHDOG_POOR_NETWORK_TEST_ENABLED, ANY_STRING_VALIDATOR); VALIDATORS.put( Global.EMERGENCY_TONE, new DiscreteValueValidator(new String[] {"0", "1", "2"})); + VALIDATORS.put(Global.EMERGENCY_GESTURE_POWER_BUTTON_COOLDOWN_PERIOD_MS, + NON_NEGATIVE_INTEGER_VALIDATOR); VALIDATORS.put(Global.CALL_AUTO_RETRY, BOOLEAN_VALIDATOR); VALIDATORS.put(Global.DOCK_AUDIO_MEDIA_ENABLED, BOOLEAN_VALIDATOR); VALIDATORS.put( diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java index 9f883960981b..1e8e05f025c7 100644 --- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java +++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java @@ -151,6 +151,7 @@ public class SecureSettingsValidators { VALIDATORS.put(Secure.LOCKSCREEN_SHOW_CONTROLS, BOOLEAN_VALIDATOR); VALIDATORS.put(Secure.LOCKSCREEN_SHOW_WALLET, BOOLEAN_VALIDATOR); VALIDATORS.put(Secure.LOCKSCREEN_USE_DOUBLE_LINE_CLOCK, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.STATUS_BAR_SHOW_VIBRATE_ICON, BOOLEAN_VALIDATOR); VALIDATORS.put(Secure.DOZE_ENABLED, BOOLEAN_VALIDATOR); VALIDATORS.put(Secure.DOZE_ALWAYS_ON, BOOLEAN_VALIDATOR); VALIDATORS.put(Secure.DOZE_PICK_UP_GESTURE, BOOLEAN_VALIDATOR); diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java index 6a8e87679cfd..1f26fb2ef51d 100644 --- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java +++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java @@ -256,6 +256,7 @@ public class SettingsBackupTest { Settings.Global.DROPBOX_RESERVE_PERCENT, Settings.Global.DROPBOX_TAG_PREFIX, Settings.Global.EMERGENCY_AFFORDANCE_NEEDED, + Settings.Global.EMERGENCY_GESTURE_POWER_BUTTON_COOLDOWN_PERIOD_MS, Settings.Global.EMULATE_DISPLAY_CUTOUT, Settings.Global.ENABLE_ACCESSIBILITY_GLOBAL_GESTURE_ENABLED, Settings.Global.ENABLE_CACHE_QUOTA_CALCULATION, diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java index 8c7011253c8a..4183c0885033 100644 --- a/packages/Shell/src/com/android/shell/BugreportProgressService.java +++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java @@ -157,6 +157,7 @@ public class BugreportProgressService extends Service { static final String EXTRA_BUGREPORT = "android.intent.extra.BUGREPORT"; static final String EXTRA_BUGREPORT_TYPE = "android.intent.extra.BUGREPORT_TYPE"; + static final String EXTRA_BUGREPORT_NONCE = "android.intent.extra.BUGREPORT_NONCE"; static final String EXTRA_SCREENSHOT = "android.intent.extra.SCREENSHOT"; static final String EXTRA_ID = "android.intent.extra.ID"; static final String EXTRA_NAME = "android.intent.extra.NAME"; @@ -415,7 +416,7 @@ public class BugreportProgressService extends Service { final String bugreportFilePath = mInfo.bugreportFile.getAbsolutePath(); if (mInfo.type == BugreportParams.BUGREPORT_MODE_REMOTE) { sendRemoteBugreportFinishedBroadcast(mContext, bugreportFilePath, - mInfo.bugreportFile); + mInfo.bugreportFile, mInfo.nonce); } else { cleanupOldFiles(MIN_KEEP_COUNT, MIN_KEEP_AGE, mBugreportsDir); final Intent intent = new Intent(INTENT_BUGREPORT_FINISHED); @@ -428,7 +429,7 @@ public class BugreportProgressService extends Service { } private static void sendRemoteBugreportFinishedBroadcast(Context context, - String bugreportFileName, File bugreportFile) { + String bugreportFileName, File bugreportFile, long nonce) { cleanupOldFiles(REMOTE_BUGREPORT_FILES_AMOUNT, REMOTE_MIN_KEEP_AGE, bugreportFile.getParentFile()); final Intent intent = new Intent(DevicePolicyManager.ACTION_REMOTE_BUGREPORT_DISPATCH); @@ -439,6 +440,7 @@ public class BugreportProgressService extends Service { } intent.setDataAndType(bugreportUri, BUGREPORT_MIMETYPE); intent.putExtra(DevicePolicyManager.EXTRA_REMOTE_BUGREPORT_HASH, bugreportHash); + intent.putExtra(DevicePolicyManager.EXTRA_REMOTE_BUGREPORT_NONCE, nonce); intent.putExtra(EXTRA_BUGREPORT, bugreportFileName); context.sendBroadcastAsUser(intent, UserHandle.SYSTEM, android.Manifest.permission.DUMP); @@ -613,11 +615,12 @@ public class BugreportProgressService extends Service { String shareDescription = intent.getStringExtra(EXTRA_DESCRIPTION); int bugreportType = intent.getIntExtra(EXTRA_BUGREPORT_TYPE, BugreportParams.BUGREPORT_MODE_INTERACTIVE); + long nonce = intent.getLongExtra(EXTRA_BUGREPORT_NONCE, 0); String baseName = getBugreportBaseName(bugreportType); String name = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date()); BugreportInfo info = new BugreportInfo(mContext, baseName, name, - shareTitle, shareDescription, bugreportType, mBugreportsDir); + shareTitle, shareDescription, bugreportType, mBugreportsDir, nonce); synchronized (mLock) { if (info.bugreportFile.exists()) { Log.e(TAG, "Failed to start bugreport generation, the requested bugreport file " @@ -1915,6 +1918,11 @@ public class BugreportProgressService extends Service { */ final int type; + /** + * Nonce of the bugreport + */ + final long nonce; + private final Object mLock = new Object(); /** @@ -1922,12 +1930,13 @@ public class BugreportProgressService extends Service { */ BugreportInfo(Context context, String baseName, String name, @Nullable String shareTitle, @Nullable String shareDescription, - @BugreportParams.BugreportMode int type, File bugreportsDir) { + @BugreportParams.BugreportMode int type, File bugreportsDir, long nonce) { this.context = context; this.name = this.initialName = name; this.shareTitle = shareTitle == null ? "" : shareTitle; this.shareDescription = shareDescription == null ? "" : shareDescription; this.type = type; + this.nonce = nonce; this.baseName = baseName; this.bugreportFile = new File(bugreportsDir, getFileName(this, ".zip")); } @@ -2167,6 +2176,7 @@ public class BugreportProgressService extends Service { screenshotCounter = in.readInt(); shareDescription = in.readString(); type = in.readInt(); + nonce = in.readLong(); } @Override @@ -2195,6 +2205,7 @@ public class BugreportProgressService extends Service { dest.writeInt(screenshotCounter); dest.writeString(shareDescription); dest.writeInt(type); + dest.writeLong(nonce); } @Override diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt index a0d335db92d6..84fb8d450e54 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt +++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt @@ -151,7 +151,7 @@ class ActivityLaunchAnimator( if (packageName != null && animationAdapter != null) { try { ActivityTaskManager.getService().registerRemoteAnimationForNextActivityStart( - packageName, animationAdapter) + packageName, animationAdapter, null /* launchCookie */) } catch (e: RemoteException) { Log.w(TAG, "Unable to register the remote animation", e) } diff --git a/packages/SystemUI/docs/usb_audio.md b/packages/SystemUI/docs/usb_audio.md new file mode 100644 index 000000000000..66e2df944fbc --- /dev/null +++ b/packages/SystemUI/docs/usb_audio.md @@ -0,0 +1,30 @@ +# USB audio Permission and Confirmation warning dialog resource string id matrix table +### go/support-usb-access-aoc-offload-feature + + |---|------------|----------------|------------------|-----------------|--------------------| + | # | Permission |isUsbAudioDevice| hasAudioPlayback | hasAudioCapture | string resource ID | + |---|------------|----------------|------------------|-----------------|--------------------| + | 1 | TRUE | TRUE | TRUE | FALSE | usb_audio_device_ + permission_prompt | + |---|------------|----------------|------------------|-----------------|--------------------| + | 2 | TRUE | TRUE | FALSE | TRUE | usb_audio_device_ + permission_prompt | + |---|------------|----------------|------------------|-----------------|--------------------| + | 3 | TRUE | TRUE | TRUE | TRUE | usb_audio_device_ + permission_prompt | + |---|------------|----------------|------------------|-----------------|--------------------| + | 4 | TRUE | FALSE | N/A | N/A | usb_device_ + permission_prompt | + |---|------------|----------------|------------------|-----------------|--------------------| + | 5 | FALSE | TRUE | TRUE | FALSE | usb_audio_device_ + permission_prompt | + |---|------------|----------------|------------------|-----------------|--------------------| + | 6 | FALSE | TRUE | FALSE | TRUE | usb_audio_device_ + permission_prompt_warn + |---|------------|----------------|------------------|-----------------|--------------------| + | 7 | FALSE | TRUE | TRUE | TRUE | usb_audio_device_ + permission_prompt_warn + |---|------------|----------------|------------------|-----------------|--------------------| + | 8 | FALSE | FALSE | N/A | N/A | usb_device_ + permission_prompt | + |---|------------|----------------|------------------|-----------------|--------------------| diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml index a946318cb313..0a2d226a33eb 100644 --- a/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml +++ b/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml @@ -16,7 +16,6 @@ ** limitations under the License. */ --> - <com.android.keyguard.KeyguardPINView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:androidprv="http://schemas.android.com/apk/res-auto" @@ -186,8 +185,6 @@ </androidx.constraintlayout.widget.ConstraintLayout> - - <include layout="@layout/keyguard_eca" android:id="@+id/keyguard_selector_fade_container" android:layout_width="match_parent" diff --git a/packages/SystemUI/res-keyguard/values-land/dimens.xml b/packages/SystemUI/res-keyguard/values-land/dimens.xml index 6342b9c0c7f0..af284a87295b 100644 --- a/packages/SystemUI/res-keyguard/values-land/dimens.xml +++ b/packages/SystemUI/res-keyguard/values-land/dimens.xml @@ -19,7 +19,7 @@ --> <resources> <dimen name="num_pad_row_margin_bottom">3dp</dimen> - <dimen name="keyguard_eca_top_margin">0dp</dimen> + <dimen name="keyguard_eca_top_margin">2dp</dimen> <dimen name="keyguard_eca_bottom_margin">2dp</dimen> <dimen name="keyguard_password_height">26dp</dimen> <dimen name="num_pad_entry_row_margin_bottom">0dp</dimen> diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml index aac5b3fc6fc0..544447faec08 100644 --- a/packages/SystemUI/res/values-af/strings.xml +++ b/packages/SystemUI/res/values-af/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Outodraai skerm"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"Gee <xliff:g id="APPLICATION">%1$s</xliff:g> toegang tot <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Laat <xliff:g id="APPLICATION">%1$s</xliff:g> toe om by <xliff:g id="USB_DEVICE">%2$s</xliff:g> in te gaan?\nOpneemtoestemming is nie aan hierdie program verleen nie, maar dit kan oudio deur hierdie USB-toestel vasvang."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"Gee <xliff:g id="APPLICATION">%1$s</xliff:g> toegang tot <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"Maak <xliff:g id="APPLICATION">%1$s</xliff:g> oop om <xliff:g id="USB_DEVICE">%2$s</xliff:g> te hanteer?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"Opneemtoestemming is nie aan hierdie program verleen nie, maar dit kan oudio deur hierdie USB-toestel opneem. As jy <xliff:g id="APPLICATION">%1$s</xliff:g> met hierdie toestel gebruik, kan dit verhinder dat jy oproepe, kennisgewings en wekkers hoor."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"As jy <xliff:g id="APPLICATION">%1$s</xliff:g> met hierdie toestel gebruik, kan dit verhinder dat jy oproepe, kennisgewings en wekkers hoor."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"Gee <xliff:g id="APPLICATION">%1$s</xliff:g> toegang tot <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"Hanteer <xliff:g id="USB_DEVICE">%2$s</xliff:g> met <xliff:g id="APPLICATION">%1$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"Maak <xliff:g id="APPLICATION">%1$s</xliff:g> oop om <xliff:g id="USB_DEVICE">%2$s</xliff:g> te hanteer?\nOpneemtoestemming is nie aan hierdie program verleen nie, maar dit kan oudio deur hierdie USB-toestel vasvang."</string> diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml index 940e6f1d2116..9c0342abde9e 100644 --- a/packages/SystemUI/res/values-am/strings.xml +++ b/packages/SystemUI/res/values-am/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"ማያ በራስ ሰር አሽከርክር"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"<xliff:g id="APPLICATION">%1$s</xliff:g> <xliff:g id="USB_DEVICE">%2$s</xliff:g>ን እንዲደርስበት ይፈቀድለት?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"<xliff:g id="APPLICATION">%1$s</xliff:g> <xliff:g id="USB_DEVICE">%2$s</xliff:g>ን እንዲደርስ ይፈቀድለት?\nይህ መተግበሪያ የመቅዳት ፈቃድ አልተሰጠውም፣ ነገር ግን በዩኤስቢ መሣሪያ በኩል ኦዲዮን መቅዳት ይችላል።"</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"<xliff:g id="APPLICATION">%1$s</xliff:g> <xliff:g id="USB_DEVICE">%2$s</xliff:g>ን እንዲደርስበት ይፈቀድለት?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>ን እንዲይዘው <xliff:g id="APPLICATION">%1$s</xliff:g> ይክፈት?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"ይህ መተግበሪያ የመቅረጽ ፈቃድ አልተሰጠውም፣ ነገር ግን በዚህ ዩኤስቢ መሣሪያ በኩል ኦዲዮን መቅረጽ ይችላል። <xliff:g id="APPLICATION">%1$s</xliff:g>ን ከዚህ መሣሪያ ጋር መጠቀም ጥሪዎችን፣ ማሳወቂያዎችን እና ማንቂያዎችን ከመስማት ሊከለክል ይችላል።"</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"<xliff:g id="APPLICATION">%1$s</xliff:g>ን ከዚህ መሣሪያ ጋር መጠቀም ጥሪዎችን፣ ማሳወቂያዎችን እና ማንቂያዎችን ከመስማት ሊከለክል ይችላል።"</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"<xliff:g id="APPLICATION">%1$s</xliff:g> <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>ን እንዲደርስበት ይፈቀድለት?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>ን እንዲይዘው <xliff:g id="APPLICATION">%1$s</xliff:g> ይክፈት?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"<xliff:g id="APPLICATION">%1$s</xliff:g> ን <xliff:g id="USB_DEVICE">%2$s</xliff:g> ለማስተናገድ ይከፈት?\nይህ መተግበሪያ የቅጂ ፈቃድ አልተሰጠውም ሆኖም ግን በዩኤስቢ መሣሪያ በኩል ኦዲዮን መቅዳት ይችላል።"</string> diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml index dd76b8126cc2..c1ea073bf692 100644 --- a/packages/SystemUI/res/values-ar/strings.xml +++ b/packages/SystemUI/res/values-ar/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"التدوير التلقائي للشاشة"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"هل تريد السماح لتطبيق <xliff:g id="APPLICATION">%1$s</xliff:g> بالدخول إلى <xliff:g id="USB_DEVICE">%2$s</xliff:g>؟"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"هل تريد السماح لتطبيق <xliff:g id="APPLICATION">%1$s</xliff:g> بالدخول إلى <xliff:g id="USB_DEVICE">%2$s</xliff:g>؟\nلم يتم منح هذا التطبيق إذن تسجيل، ولكن يمكنه تسجيل الصوت من خلال جهاز USB هذا."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"هل تريد السماح لتطبيق \"<xliff:g id="APPLICATION">%1$s</xliff:g>\" بالوصول إلى <xliff:g id="USB_DEVICE">%2$s</xliff:g>؟"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"هل تريد فتح تطبيق \"<xliff:g id="APPLICATION">%1$s</xliff:g>\" لإدارة <xliff:g id="USB_DEVICE">%2$s</xliff:g>؟"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"لم يتم منح هذا التطبيق الإذن بتسجيل الصوت، ولكن يمكنه التقاط الصوت من خلال جهاز USB هذا. إنّ استخدام التطبيق <xliff:g id="APPLICATION">%1$s</xliff:g> مع هذا الجهاز قد يحول دون سماع المكالمات والإشعارات والمنبّهات."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"قد يحول استخدام التطبيق <xliff:g id="APPLICATION">%1$s</xliff:g> على هذا الجهاز دون سماع المكالمات والإشعارات والمنبّهات."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"هل تريد السماح لتطبيق <xliff:g id="APPLICATION">%1$s</xliff:g> بالدخول إلى <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>؟"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"هل تريد فتح <xliff:g id="APPLICATION">%1$s</xliff:g> للتعامل مع <xliff:g id="USB_DEVICE">%2$s</xliff:g>؟"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"هل تريد فتح تطبيق <xliff:g id="APPLICATION">%1$s</xliff:g> للتعامل مع <xliff:g id="USB_DEVICE">%2$s</xliff:g>؟\nلم يتم منح هذا التطبيق إذن تسجيل، ولكن يمكنه تسجيل الصوت من خلال جهاز USB هذا."</string> diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml index a960743e92b4..1fb815e3c0f1 100644 --- a/packages/SystemUI/res/values-as/strings.xml +++ b/packages/SystemUI/res/values-as/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"স্বয়ং-ঘূৰ্ণন স্ক্ৰীন"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>ত প্ৰৱেশ কৰিবলৈ <xliff:g id="APPLICATION">%1$s</xliff:g>ক অনুমতি দিবনে?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"<xliff:g id="APPLICATION">%1$s</xliff:g>ক <xliff:g id="USB_DEVICE">%2$s</xliff:g> এক্সেছ কৰিবলৈ অনুমতি দিবনে?\nএই এপ্টোক ৰেকর্ড কৰাৰ অনুমতি দিয়া হোৱা নাই কিন্তু ই এই ইউএছবি ডিভাইচটোৰ জৰিয়তে অডিঅ\' ৰেকর্ড কৰিব পাৰে।"</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"<xliff:g id="APPLICATION">%1$s</xliff:g>ক <xliff:g id="USB_DEVICE">%2$s</xliff:g> এক্সেছ কৰিবলৈ অনুমতি দিবনে?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> নিয়ন্ত্ৰণ কৰিবলৈ <xliff:g id="APPLICATION">%1$s</xliff:g> খুলিবনে?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"এই এপ্টোক ৰেকর্ড কৰাৰ অনুমতি দিয়া হোৱা নাই কিন্তু ই এই ইউএছবি ডিভাইচটোৰ জৰিয়তে অডিঅ\' ৰেকর্ড কৰিব পাৰে। এইটো ডিভাইচৰ সৈতে <xliff:g id="APPLICATION">%1$s</xliff:g> ব্যৱহাৰ কৰিলে কল, জাননী আৰু এলাৰ্ম শুনাটো অৱৰুদ্ধ হ’ব পাৰে।"</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"এইটো ডিভাইচৰ সৈতে <xliff:g id="APPLICATION">%1$s</xliff:g> ব্যৱহাৰ কৰিলে কল, জাননী আৰু এলাৰ্ম শুনাটো অৱৰুদ্ধ হ’ব পাৰে।"</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"<xliff:g id="APPLICATION">%1$s</xliff:g>ক <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>ত প্ৰৱেশ কৰিবলৈ অনুমতি দিবনে?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>ক ব্যৱহাৰ কৰিবলৈ <xliff:g id="APPLICATION">%1$s</xliff:g>ক খোলেনে?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ব্যৱহাৰ কৰিবলৈ <xliff:g id="APPLICATION">%1$s</xliff:g>ক খুলিবনে?\nএই এপ্টোক ৰেকর্ড কৰাৰ অনুমতি দিয়া হোৱা নাই কিন্তু ই এই ইউএছবি ডিভাইচটোৰ জৰিয়তে অডিঅ\' ৰেকর্ড কৰিব পাৰে।"</string> diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml index efe983bfc2fc..1096d803ba4d 100644 --- a/packages/SystemUI/res/values-az/strings.xml +++ b/packages/SystemUI/res/values-az/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Ekranın avtomatik dönməsi"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"<xliff:g id="APPLICATION">%1$s</xliff:g> tətbiqinə <xliff:g id="USB_DEVICE">%2$s</xliff:g> cihazına giriş icazəsi verilsin?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"<xliff:g id="APPLICATION">%1$s</xliff:g> tətbiqinə <xliff:g id="USB_DEVICE">%2$s</xliff:g> cihazına giriş verilsin?\nTətbiqə qeydə almaq icazəsi verilməsə də, bu USB vasitəsilə səsi qeydə ala bilər."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"<xliff:g id="APPLICATION">%1$s</xliff:g> tətbiqinə <xliff:g id="USB_DEVICE">%2$s</xliff:g> cihazına giriş icazəsi verilsin?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> cihazını idarə etmək üçün <xliff:g id="APPLICATION">%1$s</xliff:g> tətbiqi açılsın?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"Tətbiqə qeydə almaq icazəsi verilməsə də, bu USB vasitəsilə səsi qeydə ala bilər. <xliff:g id="APPLICATION">%1$s</xliff:g> tətbiqinin bu cihazla istifadəsi zənglərin və bildirişlərin eşidilməməsinə səbəb ola bilər."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"<xliff:g id="APPLICATION">%1$s</xliff:g> tətbiqindən bu cihazla istifadə etsəniz zənglər, bildirişlər və siqnallar eşidilməyə bilər."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"<xliff:g id="APPLICATION">%1$s</xliff:g> tətbiqinə <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> cihazına giriş icazəsi verilsin?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> cihazını idarə etmək üçün <xliff:g id="APPLICATION">%1$s</xliff:g> tətbiqi açılsın?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"<xliff:g id="APPLICATION">%1$s</xliff:g> tətbiqinə <xliff:g id="USB_DEVICE">%2$s</xliff:g> cihazına giriş verilsin?\nTətbiqə qeydə almaq icazəsi verilməsə də, bu USB vasitəsilə səsi qeydə ala bilər."</string> diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml index f4a149112c36..deadd0aad259 100644 --- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml +++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Automatsko rotiranje ekrana"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"Dozvoljavate da <xliff:g id="APPLICATION">%1$s</xliff:g> pristupa uređaju <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Želite li da dozvolite da <xliff:g id="APPLICATION">%1$s</xliff:g> pristupa uređaju <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nOva aplikacija nema dozvolu za snimanje, ali bi mogla da snima zvuk pomoću ovog USB uređaja."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"Dozvoljavate da <xliff:g id="APPLICATION">%1$s</xliff:g> pristupa uređaju <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"Želite li da otvorite aplikaciju <xliff:g id="APPLICATION">%1$s</xliff:g> da biste koristili uređaj <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"Ova aplikacija nema dozvolu za snimanje, ali bi mogla da snima zvuk pomoću ovog USB uređaja. Ako koristite aplikaciju <xliff:g id="APPLICATION">%1$s</xliff:g> sa ovim uređajem, možda nećete čuti pozive, obaveštenja i alarme."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"Ako koristite aplikaciju <xliff:g id="APPLICATION">%1$s</xliff:g> sa ovim uređajem, možda nećete čuti pozive, obaveštenja i alarme."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"Dozvoljavate da <xliff:g id="APPLICATION">%1$s</xliff:g> pristupa uređaju <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"Želite da otvorite <xliff:g id="APPLICATION">%1$s</xliff:g> da biste koristili <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"Želite li da otvorite aplikaciju <xliff:g id="APPLICATION">%1$s</xliff:g> radi rukovanja uređajem <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nOva aplikacija nema dozvolu za snimanje, ali bi mogla da snima zvuk pomoću ovog USB uređaja."</string> diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml index fe7a341a11f8..fc520252060c 100644 --- a/packages/SystemUI/res/values-be/strings.xml +++ b/packages/SystemUI/res/values-be/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Аўтаматычны паварот экрана"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"Дазволіць праграме <xliff:g id="APPLICATION">%1$s</xliff:g> доступ да прылады <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Даць праграме \"<xliff:g id="APPLICATION">%1$s</xliff:g>\" доступ да прылады \"<xliff:g id="USB_DEVICE">%2$s</xliff:g>\"?\nУ гэтай праграмы няма дазволу на запіс, аднак яна зможа запісваць аўдыя праз гэту прыладу USB."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"Дазволіць праграме \"<xliff:g id="APPLICATION">%1$s</xliff:g>\" доступ да прылады \"<xliff:g id="USB_DEVICE">%2$s</xliff:g>\"?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"Адкрыць праграму \"<xliff:g id="APPLICATION">%1$s</xliff:g>\" для працы з прыладай \"<xliff:g id="USB_DEVICE">%2$s</xliff:g>\"?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"У гэтай праграмы няма дазволу на запіс, аднак яна зможа запісваць аўдыя праз гэту USB-прыладу. Выкарыстоўваючы праграму \"<xliff:g id="APPLICATION">%1$s</xliff:g>\" з гэтай прыладай, вы можаце не пачуць гукі выклікаў, апавяшчэнняў і будзільнікаў."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"Выкарыстоўваючы праграму \"<xliff:g id="APPLICATION">%1$s</xliff:g>\" з гэтай прыладай, вы можаце не пачуць гукі выклікаў, апавяшчэнняў і будзільнікаў."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"Дазволіць праграме <xliff:g id="APPLICATION">%1$s</xliff:g> доступ да прылады <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"Адкрыць праграму <xliff:g id="APPLICATION">%1$s</xliff:g> для працы з прыладай <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"Адкрыць праграму \"<xliff:g id="APPLICATION">%1$s</xliff:g>\", каб выкарыстоўваць прыладу \"<xliff:g id="USB_DEVICE">%2$s</xliff:g>\"?\nУ гэтай праграмы няма дазволу на запіс, аднак яна зможа запісваць аўдыя праз гэту USB-прыладу."</string> diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml index 2c3d723658aa..b7b9ebc833e1 100644 --- a/packages/SystemUI/res/values-bg/strings.xml +++ b/packages/SystemUI/res/values-bg/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Авт. завъртане на екрана"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"Да се разреши ли на <xliff:g id="APPLICATION">%1$s</xliff:g> достъп до <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Наистина ли искате да разрешите на <xliff:g id="APPLICATION">%1$s</xliff:g> достъп до <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nНа приложението не е предоставено разрешение за записване, но е възможно да запише звук чрез това USB устройство."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"Да се разреши ли на <xliff:g id="APPLICATION">%1$s</xliff:g> достъп до <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"Да се използва ли <xliff:g id="APPLICATION">%1$s</xliff:g> за <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"Приложението няма разрешение за записване, но може да записва звук чрез това USB устройство. Ако използвате <xliff:g id="APPLICATION">%1$s</xliff:g> с това устройство, е възможно да не чувате обажданията, известията и будилниците."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"Ако използвате <xliff:g id="APPLICATION">%1$s</xliff:g> с това устройство, е възможно да не чувате обажданията, известията и будилниците."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"Да се разреши ли на <xliff:g id="APPLICATION">%1$s</xliff:g> достъп до <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"Да се използва ли <xliff:g id="APPLICATION">%1$s</xliff:g> за работата с/ъс <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"Искате ли да използвате <xliff:g id="APPLICATION">%1$s</xliff:g> за работа с(ъс) <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nПриложението няма разрешение за записване, но може да записва звук чрез това USB устройство."</string> diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml index 9041b37c9832..86dc6cc812a9 100644 --- a/packages/SystemUI/res/values-bn/strings.xml +++ b/packages/SystemUI/res/values-bn/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"অটো-রোটেট স্ক্রিন"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"<xliff:g id="APPLICATION">%1$s</xliff:g> কে <xliff:g id="USB_DEVICE">%2$s</xliff:g> অ্যাক্সেস করতে দেবেন?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> অ্যাক্সেস করতে <xliff:g id="APPLICATION">%1$s</xliff:g>-কে কি অনুমতি দেবেন?\nএই অ্যাপকে রেকর্ড করার অনুমতি দেওয়া হয়নি কিন্তু USB ডিভাইসের মাধ্যমে সেটি অডিও রেকর্ড করতে পারে।"</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> অ্যাক্সেস করতে <xliff:g id="APPLICATION">%1$s</xliff:g> অ্যাপকে অনুমতি দিতে চান?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ব্যবহার করার জন্য <xliff:g id="APPLICATION">%1$s</xliff:g> চালু করতে চান?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"এই অ্যাপকে রেকর্ড করার অনুমতি দেওয়া হয়নি কিন্তু USB ডিভাইসের সাহায্যে সেটি অডিও রেকর্ড করতে পারে। <xliff:g id="APPLICATION">%1$s</xliff:g> অ্যাপের ব্যবহার এই ডিভাইসের সাথে করার ফলে হতে পারে কল, বিজ্ঞপ্তি এবং অ্যালার্মের আওয়াজ শোনা যাবে না।"</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"<xliff:g id="APPLICATION">%1$s</xliff:g> অ্যাপের ব্যবহার এই ডিভাইসের সাথে করার ফলে হতে পারে কল, বিজ্ঞপ্তি এবং অ্যালার্মের আওয়াজ শোনা যাবে না।"</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"<xliff:g id="APPLICATION">%1$s</xliff:g> কে <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> অ্যাক্সেস করতে দেবেন?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ব্যবহার করার জন্য <xliff:g id="APPLICATION">%1$s</xliff:g> চালু করবেন?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> অ্যাক্সেস করার জন্য <xliff:g id="APPLICATION">%1$s</xliff:g> খুলবেন?\nএই অ্যাপকে রেকর্ড করার অনুমতি দেওয়া হয়নি কিন্তু USB ডিভাইসের মাধ্যমে সেটি অডিও রেকর্ড করতে পারে।"</string> diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml index aa6ba093e2ff..b95e0dac4524 100644 --- a/packages/SystemUI/res/values-bs/strings.xml +++ b/packages/SystemUI/res/values-bs/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Automatsko rotiranje ekrana"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"Dozvoliti aplikaciji <xliff:g id="APPLICATION">%1$s</xliff:g> pristup uređaju: <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Dozvoliti aplikaciji <xliff:g id="APPLICATION">%1$s</xliff:g> pristup uređaju <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nOvoj aplikaciji nije dato odobrenje za snimanje, ali može snimati zvuk putem ovog USB uređaja."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"Dozvoliti da <xliff:g id="APPLICATION">%1$s</xliff:g> pristupa uređaju <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"Otvoriti aplikaciju <xliff:g id="APPLICATION">%1$s</xliff:g> da upravlja uređajem <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"Ovoj aplikaciji nije dato odobrenje za snimanje, ali može snimati zvuk putem ovog USB uređaja. Korištenje aplikacije <xliff:g id="APPLICATION">%1$s</xliff:g> s ovim uređajem može vas spriječiti da čujete pozive, obavještenja i alarme."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"Korištenje aplikacije <xliff:g id="APPLICATION">%1$s</xliff:g> s ovim uređajem može vas spriječiti da čujete pozive, obavještenja i alarme."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"Dozvoliti da <xliff:g id="APPLICATION">%1$s</xliff:g> pristupa uređaju <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"Otvoriti aplikaciju <xliff:g id="APPLICATION">%1$s</xliff:g> da upravlja uređajem <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"Želite li upravljati uređajem <xliff:g id="USB_DEVICE">%2$s</xliff:g> putem aplikacije <xliff:g id="APPLICATION">%1$s</xliff:g>?\nOvoj aplikaciji nije dato odobrenje za snimanje, ali može snimati zvuk putem ovog USB uređaja."</string> diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml index b4c0dc5247ca..35f59e31efb5 100644 --- a/packages/SystemUI/res/values-ca/strings.xml +++ b/packages/SystemUI/res/values-ca/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Gira la pantalla automàticament"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"Vols permetre que <xliff:g id="APPLICATION">%1$s</xliff:g> accedeixi a <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Vols permetre que <xliff:g id="APPLICATION">%1$s</xliff:g> accedeixi a <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nAquesta aplicació no té permís de gravació, però pot capturar àudio a través d\'aquest dispositiu USB."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"Vols permetre que <xliff:g id="APPLICATION">%1$s</xliff:g> accedeixi a <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"Vols obrir <xliff:g id="APPLICATION">%1$s</xliff:g> per gestionar <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"Aquesta aplicació no té permís de gravació, però pot capturar àudio a través d\'aquest dispositiu USB. Si utilitzes <xliff:g id="APPLICATION">%1$s</xliff:g> amb aquest dispositiu, és possible que no s\'escoltin les trucades, les notificacions ni les alarmes."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"Si utilitzes <xliff:g id="APPLICATION">%1$s</xliff:g> amb aquest dispositiu, és possible que no s\'escoltin les trucades, les notificacions ni les alarmes."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"Vols permetre que <xliff:g id="APPLICATION">%1$s</xliff:g> accedeixi a <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"Vols obrir <xliff:g id="APPLICATION">%1$s</xliff:g> per gestionar <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"Vols permetre que <xliff:g id="APPLICATION">%1$s</xliff:g> accedeixi a <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nAquesta aplicació no té permís de gravació, però pot capturar àudio a través d\'aquest dispositiu USB."</string> diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml index d940d3c1627a..93a59b6e9c05 100644 --- a/packages/SystemUI/res/values-cs/strings.xml +++ b/packages/SystemUI/res/values-cs/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Automatické otočení obrazovky"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"Povolit aplikaci <xliff:g id="APPLICATION">%1$s</xliff:g> přístup k zařízení <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Povolit aplikaci <xliff:g id="APPLICATION">%1$s</xliff:g> přístup k zařízení <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nTato aplikace nemá oprávnění k nahrávání, ale může zaznamenávat zvuk prostřednictvím tohoto zařízení USB."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"Povolit aplikaci <xliff:g id="APPLICATION">%1$s</xliff:g> přístup k zařízení <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"Otevřít aplikaci <xliff:g id="APPLICATION">%1$s</xliff:g> ke správě zařízení <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"Tato aplikace nemá oprávnění k nahrávání, ale může zaznamenávat zvuk prostřednictvím tohoto zařízení USB. Při používání aplikace <xliff:g id="APPLICATION">%1$s</xliff:g> s tímto zařízením nemusíte slyšet volání, oznámení a budíky."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"Při používání aplikace <xliff:g id="APPLICATION">%1$s</xliff:g> s tímto zařízením nemusíte slyšet volání, oznámení a budíky."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"Povolit aplikaci <xliff:g id="APPLICATION">%1$s</xliff:g> přístup k zařízení <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"Otevřít aplikaci <xliff:g id="APPLICATION">%1$s</xliff:g> ke správě zařízení <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"Otevřít aplikaci <xliff:g id="APPLICATION">%1$s</xliff:g> ke správě zařízení <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nTato aplikace nemá oprávnění k nahrávání, ale může zaznamenávat zvuk prostřednictvím tohoto zařízení USB."</string> diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml index 45b6b40cc47f..820d576a6fbd 100644 --- a/packages/SystemUI/res/values-da/strings.xml +++ b/packages/SystemUI/res/values-da/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Roter skærm automatisk"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"Vil du give <xliff:g id="APPLICATION">%1$s</xliff:g> adgang til <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Vil du give <xliff:g id="APPLICATION">%1$s</xliff:g> adgang til <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nDenne app har ikke fået tilladelse til at optage, men optager muligvis lyd via denne USB-enhed."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"Vil du give <xliff:g id="APPLICATION">%1$s</xliff:g> adgang til <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"Vil du åbne <xliff:g id="APPLICATION">%1$s</xliff:g> til håndtering af <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"Denne app har ikke fået tilladelse til at optage, men optager muligvis lyd via denne USB-enhed. Hvis du bruger <xliff:g id="APPLICATION">%1$s</xliff:g> med denne enhed, kan du muligvis ikke høre opkald, notifikationer og alarmer."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"Hvis du bruger <xliff:g id="APPLICATION">%1$s</xliff:g> med denne enhed, kan du muligvis ikke høre opkald, notifikationer og alarmer."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"Vil du give <xliff:g id="APPLICATION">%1$s</xliff:g> adgang til <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"Vil du åbne <xliff:g id="APPLICATION">%1$s</xliff:g> til håndtering af <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"Vil du åbne <xliff:g id="APPLICATION">%1$s</xliff:g> for at håndtere <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nDenne app har ikke fået tilladelse til at optage, men optager muligvis lyd via denne USB-enhed."</string> diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml index 33c3b3e1ae8e..aeb3fda59b1a 100644 --- a/packages/SystemUI/res/values-de/strings.xml +++ b/packages/SystemUI/res/values-de/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Bildschirm automatisch drehen"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"<xliff:g id="APPLICATION">%1$s</xliff:g> den Zugriff auf <xliff:g id="USB_DEVICE">%2$s</xliff:g> gewähren?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"<xliff:g id="APPLICATION">%1$s</xliff:g> den Zugriff auf <xliff:g id="USB_DEVICE">%2$s</xliff:g> gewähren?\nDiese App hat noch nicht die Berechtigung zum Aufnehmen erhalten, könnte jedoch Audio über dieses USB-Gerät aufnehmen."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"<xliff:g id="APPLICATION">%1$s</xliff:g> Zugriff auf <xliff:g id="USB_DEVICE">%2$s</xliff:g> gewähren?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"<xliff:g id="APPLICATION">%1$s</xliff:g> öffnen zur Verwendung von <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"Diese App hat noch keine Berechtigung zum Aufnehmen erhalten, könnte aber Audioaufnahmen über dieses USB-Gerät machen. Wenn du <xliff:g id="APPLICATION">%1$s</xliff:g> mit diesem Gerät verwendest, hörst du möglicherweise keine Anrufe, Benachrichtigungen und Wecker mehr."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"Wenn du <xliff:g id="APPLICATION">%1$s</xliff:g> mit diesem Gerät verwendest, hörst du möglicherweise keine Anrufe, Benachrichtigungen und Wecker mehr."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"<xliff:g id="APPLICATION">%1$s</xliff:g> den Zugriff auf <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> gewähren?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"Für <xliff:g id="USB_DEVICE">%2$s</xliff:g> <xliff:g id="APPLICATION">%1$s</xliff:g> öffnen?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"<xliff:g id="APPLICATION">%1$s</xliff:g> öffnen, um <xliff:g id="USB_DEVICE">%2$s</xliff:g> zu bedienen?\nDiese App hat noch keine Berechtigung zum Aufnehmen erhalten, könnte aber Audioaufnahmen über dieses USB-Gerät machen."</string> diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml index fd2e07d706cd..7a78e260382c 100644 --- a/packages/SystemUI/res/values-el/strings.xml +++ b/packages/SystemUI/res/values-el/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Αυτόματη περιστροφή οθόνης"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"Να επιτρέπεται η πρόσβαση της εφαρμογής <xliff:g id="APPLICATION">%1$s</xliff:g> στη συσκευή <xliff:g id="USB_DEVICE">%2$s</xliff:g>;"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Να επιτρέπεται στο <xliff:g id="APPLICATION">%1$s</xliff:g> να έχει πρόσβαση στη συσκευή <xliff:g id="USB_DEVICE">%2$s</xliff:g>;\nΔεν έχει εκχωρηθεί άδεια εγγραφής σε αυτήν την εφαρμογή, αλλά μέσω αυτής της συσκευής USB θα μπορεί να εγγράφει ήχο."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"Να επιτρέπεται στο <xliff:g id="APPLICATION">%1$s</xliff:g> η πρόσβαση στη συσκευή <xliff:g id="USB_DEVICE">%2$s</xliff:g>;"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"Άνοιγμα <xliff:g id="APPLICATION">%1$s</xliff:g> για διαχείριση συσκευής <xliff:g id="USB_DEVICE">%2$s</xliff:g>;"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"Δεν έχει εκχωρηθεί άδεια εγγραφής σε αυτήν την εφαρμογή, αλλά μέσω αυτής της συσκευής USB θα μπορεί να εγγράφει ήχο. Η χρήση της εφαρμογής <xliff:g id="APPLICATION">%1$s</xliff:g> με αυτήν τη συσκευή μπορεί να σας εμποδίσει να ακούσετε κλήσεις, ειδοποιήσεις και ξυπνητήρια."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"Η χρήση της εφαρμογής <xliff:g id="APPLICATION">%1$s</xliff:g> με αυτήν τη συσκευή μπορεί να σας εμποδίσει να ακούσετε κλήσεις, ειδοποιήσεις και ξυπνητήρια."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"Να επιτρέπεται η πρόσβαση της εφαρμογής <xliff:g id="APPLICATION">%1$s</xliff:g> στο αξεσουάρ <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>;"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"Να ανοίγει η εφαρμογή <xliff:g id="APPLICATION">%1$s</xliff:g> για τη διαχείριση της συσκευής <xliff:g id="USB_DEVICE">%2$s</xliff:g>;"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"Άνοιγμα της εφαρμογής <xliff:g id="APPLICATION">%1$s</xliff:g> για τον χειρισμό της συσκευής <xliff:g id="USB_DEVICE">%2$s</xliff:g>;\nΔεν έχει εκχωρηθεί άδεια εγγραφής σε αυτήν την εφαρμογή, αλλά μέσω αυτής της συσκευής USB θα μπορεί να εγγράφει ήχο."</string> diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml index ba2f9f20d8d6..eaff1256fdca 100644 --- a/packages/SystemUI/res/values-en-rAU/strings.xml +++ b/packages/SystemUI/res/values-en-rAU/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Auto-rotate screen"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"Allow <xliff:g id="APPLICATION">%1$s</xliff:g> to access <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Allow <xliff:g id="APPLICATION">%1$s</xliff:g> to access <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nThis app has not been granted record permission but could capture audio through this USB device."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"Allow <xliff:g id="APPLICATION">%1$s</xliff:g> to access <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"Open <xliff:g id="APPLICATION">%1$s</xliff:g> to handle <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"This app has not been granted record permission but could capture audio through this USB device. Using <xliff:g id="APPLICATION">%1$s</xliff:g> with this device might prevent hearing calls, notifications and alarms."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"Using <xliff:g id="APPLICATION">%1$s</xliff:g> with this device might prevent hearing calls, notifications and alarms."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"Allow <xliff:g id="APPLICATION">%1$s</xliff:g> to access <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"Open <xliff:g id="APPLICATION">%1$s</xliff:g> to handle <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"Open <xliff:g id="APPLICATION">%1$s</xliff:g> to handle <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nThis app has not been granted record permission but could capture audio through this USB device."</string> diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml index 0cc0ed295d59..69cb4c6f4f23 100644 --- a/packages/SystemUI/res/values-en-rCA/strings.xml +++ b/packages/SystemUI/res/values-en-rCA/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Auto-rotate screen"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"Allow <xliff:g id="APPLICATION">%1$s</xliff:g> to access <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Allow <xliff:g id="APPLICATION">%1$s</xliff:g> to access <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nThis app has not been granted record permission but could capture audio through this USB device."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"Allow <xliff:g id="APPLICATION">%1$s</xliff:g> to access <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"Open <xliff:g id="APPLICATION">%1$s</xliff:g> to handle <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"This app has not been granted record permission but could capture audio through this USB device. Using <xliff:g id="APPLICATION">%1$s</xliff:g> with this device might prevent hearing calls, notifications and alarms."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"Using <xliff:g id="APPLICATION">%1$s</xliff:g> with this device might prevent hearing calls, notifications and alarms."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"Allow <xliff:g id="APPLICATION">%1$s</xliff:g> to access <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"Open <xliff:g id="APPLICATION">%1$s</xliff:g> to handle <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"Open <xliff:g id="APPLICATION">%1$s</xliff:g> to handle <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nThis app has not been granted record permission but could capture audio through this USB device."</string> diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml index ba2f9f20d8d6..eaff1256fdca 100644 --- a/packages/SystemUI/res/values-en-rGB/strings.xml +++ b/packages/SystemUI/res/values-en-rGB/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Auto-rotate screen"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"Allow <xliff:g id="APPLICATION">%1$s</xliff:g> to access <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Allow <xliff:g id="APPLICATION">%1$s</xliff:g> to access <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nThis app has not been granted record permission but could capture audio through this USB device."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"Allow <xliff:g id="APPLICATION">%1$s</xliff:g> to access <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"Open <xliff:g id="APPLICATION">%1$s</xliff:g> to handle <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"This app has not been granted record permission but could capture audio through this USB device. Using <xliff:g id="APPLICATION">%1$s</xliff:g> with this device might prevent hearing calls, notifications and alarms."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"Using <xliff:g id="APPLICATION">%1$s</xliff:g> with this device might prevent hearing calls, notifications and alarms."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"Allow <xliff:g id="APPLICATION">%1$s</xliff:g> to access <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"Open <xliff:g id="APPLICATION">%1$s</xliff:g> to handle <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"Open <xliff:g id="APPLICATION">%1$s</xliff:g> to handle <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nThis app has not been granted record permission but could capture audio through this USB device."</string> diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml index ba2f9f20d8d6..eaff1256fdca 100644 --- a/packages/SystemUI/res/values-en-rIN/strings.xml +++ b/packages/SystemUI/res/values-en-rIN/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Auto-rotate screen"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"Allow <xliff:g id="APPLICATION">%1$s</xliff:g> to access <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Allow <xliff:g id="APPLICATION">%1$s</xliff:g> to access <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nThis app has not been granted record permission but could capture audio through this USB device."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"Allow <xliff:g id="APPLICATION">%1$s</xliff:g> to access <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"Open <xliff:g id="APPLICATION">%1$s</xliff:g> to handle <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"This app has not been granted record permission but could capture audio through this USB device. Using <xliff:g id="APPLICATION">%1$s</xliff:g> with this device might prevent hearing calls, notifications and alarms."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"Using <xliff:g id="APPLICATION">%1$s</xliff:g> with this device might prevent hearing calls, notifications and alarms."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"Allow <xliff:g id="APPLICATION">%1$s</xliff:g> to access <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"Open <xliff:g id="APPLICATION">%1$s</xliff:g> to handle <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"Open <xliff:g id="APPLICATION">%1$s</xliff:g> to handle <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nThis app has not been granted record permission but could capture audio through this USB device."</string> diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml index 620f9957c596..b2e8494c9275 100644 --- a/packages/SystemUI/res/values-en-rXC/strings.xml +++ b/packages/SystemUI/res/values-en-rXC/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Auto-rotate screen"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"Allow <xliff:g id="APPLICATION">%1$s</xliff:g> to access <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Allow <xliff:g id="APPLICATION">%1$s</xliff:g> to access <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nThis app has not been granted record permission but could capture audio through this USB device."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"Allow <xliff:g id="APPLICATION">%1$s</xliff:g> to access <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"Open <xliff:g id="APPLICATION">%1$s</xliff:g> to handle <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"This app has not been granted record permission but could capture audio through this USB device. Using <xliff:g id="APPLICATION">%1$s</xliff:g> with this device might prevent hearing calls, notifications and alarms."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"Using <xliff:g id="APPLICATION">%1$s</xliff:g> with this device might prevent hearing calls, notifications and alarms."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"Allow <xliff:g id="APPLICATION">%1$s</xliff:g> to access <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"Open <xliff:g id="APPLICATION">%1$s</xliff:g> to handle <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"Open <xliff:g id="APPLICATION">%1$s</xliff:g> to handle <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nThis app has not been granted record permission but could capture audio through this USB device."</string> diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml index b52a877a1cc7..88569b9fe24e 100644 --- a/packages/SystemUI/res/values-es-rUS/strings.xml +++ b/packages/SystemUI/res/values-es-rUS/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Girar la pantalla automáticamente"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"¿Deseas permitir que <xliff:g id="APPLICATION">%1$s</xliff:g> acceda a <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"¿Quieres permitir que <xliff:g id="APPLICATION">%1$s</xliff:g> acceda a <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nLa app no tiene permiso para grabar, pero podría capturar audio mediante este dispositivo USB."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"¿Deseas permitir que <xliff:g id="APPLICATION">%1$s</xliff:g> acceda a <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"¿Deseas abrir <xliff:g id="APPLICATION">%1$s</xliff:g> para usar <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"Aunque no se le otorgó permiso de grabación a esta app, puede capturar audio con este dispositivo USB. Es posible que el uso de <xliff:g id="APPLICATION">%1$s</xliff:g> en este dispositivo impida escuchar llamadas, notificaciones y alarmas."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"Es posible que el uso de <xliff:g id="APPLICATION">%1$s</xliff:g> en este dispositivo impida escuchar llamadas, notificaciones y alarmas."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"¿Deseas permitir que <xliff:g id="APPLICATION">%1$s</xliff:g> acceda a <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"¿Deseas abrir <xliff:g id="APPLICATION">%1$s</xliff:g> para usar <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"¿Quieres abrir <xliff:g id="APPLICATION">%1$s</xliff:g> para administrar <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nLa app no tiene permiso para grabar, pero puede capturar audio mediante este dispositivo USB."</string> diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml index 57bb446775e3..00af8c2fffe1 100644 --- a/packages/SystemUI/res/values-es/strings.xml +++ b/packages/SystemUI/res/values-es/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Girar pantalla automáticamente"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"¿Permitir que <xliff:g id="APPLICATION">%1$s</xliff:g> acceda a <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"¿Quieres que <xliff:g id="APPLICATION">%1$s</xliff:g> pueda acceder a <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nEsta aplicación no tiene permisos para grabar, pero podría capturar audio a través de este dispositivo USB."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"¿Permitir que <xliff:g id="APPLICATION">%1$s</xliff:g> acceda a <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"¿Abrir <xliff:g id="APPLICATION">%1$s</xliff:g> para controlar <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"Esta aplicación no tiene permiso para grabar, pero podría capturar audio con este dispositivo USB. Si usas <xliff:g id="APPLICATION">%1$s</xliff:g> en este dispositivo, puede que no oigas llamadas, notificaciones ni alarmas."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"Si usas <xliff:g id="APPLICATION">%1$s</xliff:g> en este dispositivo, puede que no oigas llamadas, notificaciones ni alarmas."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"¿Permitir que <xliff:g id="APPLICATION">%1$s</xliff:g> acceda a <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"¿Abrir <xliff:g id="APPLICATION">%1$s</xliff:g> para usar <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"¿Abrir <xliff:g id="APPLICATION">%1$s</xliff:g> para controlar <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nEsta aplicación no tiene permisos para grabar, pero puede capturar audio mediante este dispositivo USB."</string> diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml index c014028b0a8b..c03b788dd9a1 100644 --- a/packages/SystemUI/res/values-et/strings.xml +++ b/packages/SystemUI/res/values-et/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Kuva automaatne pööramine"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"Kas lubada rakendusele <xliff:g id="APPLICATION">%1$s</xliff:g> juurdepääs seadmele <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Kas lubada rakendusel <xliff:g id="APPLICATION">%1$s</xliff:g> seadmele <xliff:g id="USB_DEVICE">%2$s</xliff:g> juurde pääseda?\nSellele rakendusele pole antud salvestamise luba, kuid see saab heli jäädvustada selle USB-seadme kaudu."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"Kas lubada rakendusele <xliff:g id="APPLICATION">%1$s</xliff:g> juurdepääs seadmele <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"Kas avada <xliff:g id="APPLICATION">%1$s</xliff:g> seadme <xliff:g id="USB_DEVICE">%2$s</xliff:g> kasutamiseks?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"Sellele rakendusele pole antud salvestamise luba, kuid see saab heli jäädvustada selle USB-seadme kaudu. Rakenduse <xliff:g id="APPLICATION">%1$s</xliff:g> kasutamine selle seadmega võib takistada kõnede, märguannete ja äratuste kuulmist."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"Rakenduse <xliff:g id="APPLICATION">%1$s</xliff:g> kasutamine selle seadmega võib takistada kõnede, märguannete ja äratuste kuulmist."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"Kas lubada rakendusele <xliff:g id="APPLICATION">%1$s</xliff:g> juurdepääs seadmele <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"Kas avada <xliff:g id="APPLICATION">%1$s</xliff:g> seadme <xliff:g id="USB_DEVICE">%2$s</xliff:g> kasutamiseks?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"Kas avada <xliff:g id="APPLICATION">%1$s</xliff:g>, et käsitseda seadet <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nSellele rakendusele pole antud salvestamise luba, kuid see saab heli jäädvustada selle USB-seadme kaudu."</string> diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml index 30383d1a3867..bf8d0c638ba6 100644 --- a/packages/SystemUI/res/values-eu/strings.xml +++ b/packages/SystemUI/res/values-eu/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Biratu pantaila automatikoki"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> atzitzeko baimena eman nahi diozu <xliff:g id="APPLICATION">%1$s</xliff:g> aplikazioari?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> erabiltzeko baimena eman nahi diozu <xliff:g id="APPLICATION">%1$s</xliff:g> aplikazioari?\nAplikazioak ez du grabatzeko baimenik, baina baliteke USB bidezko gailu horren bidez audioa grabatzea."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> atzitzeko baimena eman nahi diozu <xliff:g id="APPLICATION">%1$s</xliff:g> aplikazioari?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"<xliff:g id="APPLICATION">%1$s</xliff:g> ireki nahi duzu <xliff:g id="USB_DEVICE">%2$s</xliff:g> kudeatzeko?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"Aplikazioak ez du grabatzeko baimenik, baina baliteke USB bidezko gailu honen bidez audioa grabatzea. <xliff:g id="APPLICATION">%1$s</xliff:g> gailu honekin erabiliz gero, baliteke deiak, jakinarazpenak eta alarmak ez entzutea."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"<xliff:g id="APPLICATION">%1$s</xliff:g> gailu honekin erabiliz gero, baliteke deiak, jakinarazpenak eta alarmak ez entzutea."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> atzitzeko baimena eman nahi diozu <xliff:g id="APPLICATION">%1$s</xliff:g> aplikazioari?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"<xliff:g id="APPLICATION">%1$s</xliff:g> ireki nahi duzu <xliff:g id="USB_DEVICE">%2$s</xliff:g> kudeatzeko?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"<xliff:g id="APPLICATION">%1$s</xliff:g> ireki nahi duzu <xliff:g id="USB_DEVICE">%2$s</xliff:g> erabiltzeko?\nAplikazioak ez du grabatzeko baimenik, baina baliteke audioa grabatzea USB bidezko gailu horren bidez."</string> diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml index 16dc803ed355..3839c02552ea 100644 --- a/packages/SystemUI/res/values-fa/strings.xml +++ b/packages/SystemUI/res/values-fa/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"چرخش خودکار صفحه"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"به <xliff:g id="APPLICATION">%1$s</xliff:g> برای دسترسی به <xliff:g id="USB_DEVICE">%2$s</xliff:g> اجازه داده شود؟"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"به <xliff:g id="APPLICATION">%1$s</xliff:g> اجازه میدهید به <xliff:g id="USB_DEVICE">%2$s</xliff:g>دسترسی داشته باشد؟\nمجوز ضبط به این برنامه داده نشده است اما میتواند صدا را ازطریق این دستگاه USB ضبط کند."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"به <xliff:g id="APPLICATION">%1$s</xliff:g> اجازه دسترسی به <xliff:g id="USB_DEVICE">%2$s</xliff:g> داده شود؟"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"برای استفاده از <xliff:g id="USB_DEVICE">%2$s</xliff:g>، <xliff:g id="APPLICATION">%1$s</xliff:g> باز شود؟"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"اجازه ضبط به این برنامه داده نشده است اما میتواند صدا را ازطریق این دستگاه USB ضبط کند. استفاده از <xliff:g id="APPLICATION">%1$s</xliff:g> با این دستگاه میتواند مانع از شنیدن تماسها، اعلانها، و زنگهای ساعت شود."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"استفاده از <xliff:g id="APPLICATION">%1$s</xliff:g> با این دستگاه میتواند مانع از شنیدن تماسها، اعلانها، و زنگهای ساعت شود."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"به <xliff:g id="APPLICATION">%1$s</xliff:g> برای دسترسی به <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> اجازه داده شود؟"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"برای استفاده از <xliff:g id="USB_DEVICE">%2$s</xliff:g>، <xliff:g id="APPLICATION">%1$s</xliff:g> باز شود؟"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"برای استفاده از <xliff:g id="USB_DEVICE">%2$s</xliff:g>، <xliff:g id="APPLICATION">%1$s</xliff:g> باز شود؟\nمجوز ضبط به این برنامه داده نشده است اما میتواند صدا را ازطریق این دستگاه USB ضبط کند."</string> diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml index 73f94aef0e00..ed93a50c5e49 100644 --- a/packages/SystemUI/res/values-fi/strings.xml +++ b/packages/SystemUI/res/values-fi/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Näytön automaattinen kääntö"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"Saako <xliff:g id="APPLICATION">%1$s</xliff:g> käyttöoikeuden (<xliff:g id="USB_DEVICE">%2$s</xliff:g>)?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Saako <xliff:g id="APPLICATION">%1$s</xliff:g> tämän pääsyoikeuden: <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nSovellus ei ole saanut tallennuslupaa, mutta voi tallentaa ääntä tämän USB-laitteen avulla."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"Saako <xliff:g id="APPLICATION">%1$s</xliff:g> pääsyn (<xliff:g id="USB_DEVICE">%2$s</xliff:g>)?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"Avaa <xliff:g id="APPLICATION">%1$s</xliff:g>, jotta <xliff:g id="USB_DEVICE">%2$s</xliff:g> voidaan ottaa käyttöön?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"Sovellus ei ole saanut tallennuslupaa mutta voi tallentaa audiota tämän USB-laitteen avulla. Jos <xliff:g id="APPLICATION">%1$s</xliff:g> on käytössä laitteella, puheluita, ilmoituksia ja herätyksiä ei välttämättä kuulu."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"Jos <xliff:g id="APPLICATION">%1$s</xliff:g> on käytössä laitteella, puheluita, ilmoituksia ja herätyksiä ei välttämättä kuulu."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"Saako <xliff:g id="APPLICATION">%1$s</xliff:g> käyttöoikeuden (<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>)?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"Avaa <xliff:g id="APPLICATION">%1$s</xliff:g>, jotta <xliff:g id="USB_DEVICE">%2$s</xliff:g> voidaan ottaa käyttöön?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"Avataanko <xliff:g id="APPLICATION">%1$s</xliff:g>, jotta <xliff:g id="USB_DEVICE">%2$s</xliff:g> voidaan ottaa käyttöön?\nSovellus ei ole saanut tallennuslupaa, mutta voi tallentaa ääntä tämän USB-laitteen avulla."</string> diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml index ce03ed8652d3..96a820986a29 100644 --- a/packages/SystemUI/res/values-fr-rCA/strings.xml +++ b/packages/SystemUI/res/values-fr-rCA/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Rotation auto de l\'écran"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"Autoriser <xliff:g id="APPLICATION">%1$s</xliff:g> à accéder à <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Autorisé <xliff:g id="APPLICATION">%1$s</xliff:g> à accéder à <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nCette application n\'a pas été autorisée à effectuer des enregistrements, mais elle pourrait enregistrer du contenu audio par l\'intermédiaire de cet appareil USB."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"Autoriser <xliff:g id="APPLICATION">%1$s</xliff:g> à accéder à <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"Ouvrir <xliff:g id="APPLICATION">%1$s</xliff:g> pour utiliser <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"Cette application n\'a pas été autorisée à effectuer des enregistrements, mais elle pourrait capturer du contenu audio par l\'intermédiaire de cet appareil USB. L\'utilisation de <xliff:g id="APPLICATION">%1$s</xliff:g> avec cet appareil peut empêcher d\'entendre les appels, les notifications et les alarmes."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"L\'utilisation de <xliff:g id="APPLICATION">%1$s</xliff:g> avec cet appareil peut empêcher d\'entendre les appels, les notifications et les alarmes."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"Autoriser <xliff:g id="APPLICATION">%1$s</xliff:g> à accéder à <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"Ouvrir <xliff:g id="APPLICATION">%1$s</xliff:g> pour utiliser <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"Ouvrir <xliff:g id="APPLICATION">%1$s</xliff:g> pour gérer <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nCette application n\'a pas été autorisée à effectuer des enregistrements, mais elle pourrait enregistrer du contenu audio par l\'intermédiaire de cet appareil USB."</string> diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml index 565b2b449652..e709ea1ff891 100644 --- a/packages/SystemUI/res/values-fr/strings.xml +++ b/packages/SystemUI/res/values-fr/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Rotation automatique de l\'écran"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"Autoriser <xliff:g id="APPLICATION">%1$s</xliff:g> à accéder à <xliff:g id="USB_DEVICE">%2$s</xliff:g> ?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Autoriser <xliff:g id="APPLICATION">%1$s</xliff:g> à accéder à <xliff:g id="USB_DEVICE">%2$s</xliff:g> ?\nCette application n\'a pas été autorisée à effectuer des enregistrements, mais elle pourrait enregistrer du contenu audio via ce périphérique USB."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"Autoriser l\'application <xliff:g id="APPLICATION">%1$s</xliff:g> à accéder à <xliff:g id="USB_DEVICE">%2$s</xliff:g> ?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"Ouvrir l\'application <xliff:g id="APPLICATION">%1$s</xliff:g> pour gérer <xliff:g id="USB_DEVICE">%2$s</xliff:g> ?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"Cette appli n\'a pas été autorisée à enregistrer de contenus audio, mais elle peut le faire via ce périphérique USB. En utilisant <xliff:g id="APPLICATION">%1$s</xliff:g> avec ce périphérique, vous risquez de ne pas entendre les appels, notifications et alarmes."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"Vous risquez de ne pas entendre les appels, notifications et alarmes si vous utilisez <xliff:g id="APPLICATION">%1$s</xliff:g> avec ce périphérique."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"Autoriser <xliff:g id="APPLICATION">%1$s</xliff:g> à accéder à <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> ?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"Ouvrir <xliff:g id="APPLICATION">%1$s</xliff:g> pour utiliser <xliff:g id="USB_DEVICE">%2$s</xliff:g> ?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"Ouvrir <xliff:g id="APPLICATION">%1$s</xliff:g> pour gérer <xliff:g id="USB_DEVICE">%2$s</xliff:g> ?\nCette application n\'a pas reçu l\'autorisation d\'enregistrer des contenus audio, mais peut le faire via ce périphérique USB."</string> diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml index 9992743de64f..19e682a6a303 100644 --- a/packages/SystemUI/res/values-gl/strings.xml +++ b/packages/SystemUI/res/values-gl/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Xirar pantalla automaticamente"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"Queres permitir que <xliff:g id="APPLICATION">%1$s</xliff:g> acceda a <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Queres permitir que a aplicación <xliff:g id="APPLICATION">%1$s</xliff:g> acceda ao dispositivo (<xliff:g id="USB_DEVICE">%2$s</xliff:g>)?\nEsta aplicación non está autorizada para realizar gravacións, pero podería capturar audio a través deste dispositivo USB."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"Permitir que <xliff:g id="APPLICATION">%1$s</xliff:g> acceda a <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"Abrir <xliff:g id="APPLICATION">%1$s</xliff:g> para usar <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"Esta aplicación non está autorizada a realizar gravacións, pero podería capturar audio a través deste dispositivo USB. Ao usar a aplicación <xliff:g id="APPLICATION">%1$s</xliff:g> con este dispositivo, é posible que non se escoiten chamadas, notificacións nin alarmas."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"Ao usar a aplicación <xliff:g id="APPLICATION">%1$s</xliff:g> con este dispositivo, é posible que non se escoiten chamadas, notificacións nin alarmas."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"Queres permitir que <xliff:g id="APPLICATION">%1$s</xliff:g> acceda a <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"Queres abrir <xliff:g id="APPLICATION">%1$s</xliff:g> para utilizar <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"Queres abrir a aplicación <xliff:g id="APPLICATION">%1$s</xliff:g> para xestionar o dispositivo (<xliff:g id="USB_DEVICE">%2$s</xliff:g>)?\nEsta aplicación non está autorizada a realizar gravacións, pero podería capturar audio a través deste dispositivo USB."</string> diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml index e5f12b90aeac..881e3f57a235 100644 --- a/packages/SystemUI/res/values-gu/strings.xml +++ b/packages/SystemUI/res/values-gu/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"ઑટો રોટેટ સ્ક્રીન"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>ના ઍક્સેસ માટે <xliff:g id="APPLICATION">%1$s</xliff:g>ને મંજૂરી આપીએ?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"<xliff:g id="APPLICATION">%1$s</xliff:g>ને <xliff:g id="USB_DEVICE">%2$s</xliff:g> ઍક્સેસ કરવાની મંજૂરી આપીએ?\nઆ ઍપને રેકૉર્ડ કરવાની પરવાનગી આપવામાં આવી નથી પરંતુ તે આ USB ડિવાઇસ મારફત ઑડિયો કૅપ્ચર કરી શકે છે."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>ના ઍક્સેસ માટે <xliff:g id="APPLICATION">%1$s</xliff:g>ને મંજૂરી આપીએ?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>ને હૅન્ડલ કરવા માટે <xliff:g id="APPLICATION">%1$s</xliff:g>ને ખોલીએ?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"આ ઍપને રેકોર્ડ કરવાની પરવાનગી આપવામાં આવી નથી પરંતુ તે આ USB ડિવાઇસ મારફતે ઑડિયો કૅપ્ચર કરી શકે છે. આ ડિવાઇસ સાથે <xliff:g id="APPLICATION">%1$s</xliff:g>નો ઉપયોગ કરવાથી કૉલ, નોટિફિકેશન અને અલાર્મ ન સંભળાય તેમ બની શકે."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"આ ડિવાઇસ સાથે <xliff:g id="APPLICATION">%1$s</xliff:g>નો ઉપયોગ કરવાથી કૉલ, નોટિફિકેશન અને અલાર્મ ન સંભળાય તેમ બની શકે."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>ના ઍક્સેસ માટે <xliff:g id="APPLICATION">%1$s</xliff:g>ને મંજૂરી આપીએ?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>ને હૅન્ડલ કરવા માટે <xliff:g id="APPLICATION">%1$s</xliff:g>ને ખોલીએ?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>ને હેન્ડલ કરવા માટે <xliff:g id="APPLICATION">%1$s</xliff:g> ખોલીએ?\nઆ ઍપને રેકૉર્ડ કરવાની પરવાનગી આપવામાં આવી નથી પરંતુ તે આ USB ડિવાઇસ મારફત ઑડિયો કૅપ્ચર કરી શકે છે."</string> diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml index dc027e49a874..7330b960a8c6 100644 --- a/packages/SystemUI/res/values-hi/strings.xml +++ b/packages/SystemUI/res/values-hi/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"स्क्रीन अपने आप घुमाना"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"<xliff:g id="APPLICATION">%1$s</xliff:g> को <xliff:g id="USB_DEVICE">%2$s</xliff:g> के ऐक्सेस की अनुमति दें?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"आप <xliff:g id="APPLICATION">%1$s</xliff:g> को <xliff:g id="USB_DEVICE">%2$s</xliff:g> ऐक्सेस करने की अनुमति देना चाहते हैं?\nइस ऐप्लिकेशन को रिकॉर्ड करने की अनुमति नहीं दी गई है. हालांकि, ऐप्लिकेशन इस यूएसबी डिवाइस से ऑडियो कैप्चर कर सकता है."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"क्या <xliff:g id="APPLICATION">%1$s</xliff:g> को <xliff:g id="USB_DEVICE">%2$s</xliff:g> का ऐक्सेस देना है?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> का इस्तेमाल करने के लिए <xliff:g id="APPLICATION">%1$s</xliff:g> खोलना है?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"इस ऐप्लिकेशन को रिकॉर्ड करने की अनुमति नहीं दी गई है. हालांकि, ऐप्लिकेशन इस यूएसबी डिवाइस से ऑडियो रिकॉर्ड कर सकता है. <xliff:g id="APPLICATION">%1$s</xliff:g> का इस्तेमाल इस डिवाइस के साथ करने पर, हो सकता है कि कॉल, सूचनाएं, और अलार्म की आवाज़ सुनाई न दे."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"<xliff:g id="APPLICATION">%1$s</xliff:g> का इस्तेमाल इस डिवाइस के साथ करने पर, हो सकता है कि कॉल, सूचनाएं, और अलार्म की आवाज़ सुनाई न दे."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"<xliff:g id="APPLICATION">%1$s</xliff:g> को <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> के ऐक्सेस की अनुमति दें?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> के लिए <xliff:g id="APPLICATION">%1$s</xliff:g> खोलें?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> का इस्तेमाल करने के लिए <xliff:g id="APPLICATION">%1$s</xliff:g> को खोलना चाहते हैं?\n इस ऐप्लिकेशन को रिकॉर्ड करने की अनुमति नहीं दी गई है. हालांकि, ऐप्लिकेशन इस यूएसबी डिवाइस से ऑडियो कैप्चर कर सकता है."</string> diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml index a19c8b3e93c5..4ac40ac1f3d0 100644 --- a/packages/SystemUI/res/values-hr/strings.xml +++ b/packages/SystemUI/res/values-hr/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Automatski zakreni zaslon"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"Želite li dopustiti aplikaciji <xliff:g id="APPLICATION">%1$s</xliff:g> pristup uređaju <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Želite li dopustiti aplikaciji <xliff:g id="APPLICATION">%1$s</xliff:g> da pristupa uređaju <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nTa aplikacija nema dopuštenje za snimanje, no mogla bi primati zvuk putem tog USB uređaja."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"Dopustiti aplikaciji <xliff:g id="APPLICATION">%1$s</xliff:g> pristup uređaju <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"Želite li otvoriti aplikaciju <xliff:g id="APPLICATION">%1$s</xliff:g> radi upravljanja uređajem <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"Ta aplikacija nema dopuštenje za snimanje, no mogla bi primati zvuk putem ovog USB uređaja. Zbog upotrebe aplikacije <xliff:g id="APPLICATION">%1$s</xliff:g> s ovim uređajem možda nećete čuti pozive, obavijesti i alarme."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"Zbog upotrebe aplikacije <xliff:g id="APPLICATION">%1$s</xliff:g> s ovim uređajem možda nećete čuti pozive, obavijesti i alarme."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"Želite li dopustiti aplikaciji <xliff:g id="APPLICATION">%1$s</xliff:g> pristup uređaju <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"Otvoriti aplikaciju <xliff:g id="APPLICATION">%1$s</xliff:g> radi upravljanja uređajem <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"Želite li upravljati uređajem <xliff:g id="USB_DEVICE">%2$s</xliff:g> putem aplikacije <xliff:g id="APPLICATION">%1$s</xliff:g>?\nTa aplikacija nema dopuštenje za snimanje, no mogla bi primati zvuk putem tog USB uređaja."</string> diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml index 9d96b461bcfd..4b3ab42a9f67 100644 --- a/packages/SystemUI/res/values-hu/strings.xml +++ b/packages/SystemUI/res/values-hu/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Képernyő automatikus forgatása"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"Engedélyezi a(z) <xliff:g id="APPLICATION">%1$s</xliff:g> számára, hogy hozzáférjen a következőhöz: <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Lehetővé teszi a(z) <xliff:g id="APPLICATION">%1$s</xliff:g> alkalmazásnak, hogy hozzáférjen a következőhöz: <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nEz az alkalmazás nem rendelkezik rögzítési engedéllyel, de ezzel az USB-eszközzel képes a hangfelvételre."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"A(z) <xliff:g id="APPLICATION">%1$s</xliff:g> hozzáférhet ehhez: <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"Megnyitja a(z) <xliff:g id="APPLICATION">%1$s</xliff:g> appot a(z) <xliff:g id="USB_DEVICE">%2$s</xliff:g> kezeléséhez?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"Ez az alkalmazás nem rendelkezik rögzítési engedéllyel, de ezzel az USB-eszközzel képes a hangfelvételre. Ha a(z) <xliff:g id="APPLICATION">%1$s</xliff:g> alkalmazást használja ezzel az eszközzel, előfordulhat, hogy nem hallja meg a hívásokat, értesítéseket és riasztásokat."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"Ha a(z) <xliff:g id="APPLICATION">%1$s</xliff:g> alkalmazást használja ezzel az eszközzel, előfordulhat, hogy nem hallja meg a hívásokat, értesítéseket és riasztásokat."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"Engedélyezi a(z) <xliff:g id="APPLICATION">%1$s</xliff:g> számára, hogy hozzáférjen a következőhöz: <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"Megnyitja a(z) <xliff:g id="APPLICATION">%1$s</xliff:g> alkalmazást a(z) <xliff:g id="USB_DEVICE">%2$s</xliff:g> kezeléséhez?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"Megnyitja a(z) <xliff:g id="APPLICATION">%1$s</xliff:g> alkalmazást, hogy kezelje a következőt: <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nEz az alkalmazás nem rendelkezik rögzítési engedéllyel, de ezzel az USB-eszközzel képes a hangfelvételre."</string> diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml index 5e8b54c3528b..97e9ace19f37 100644 --- a/packages/SystemUI/res/values-hy/strings.xml +++ b/packages/SystemUI/res/values-hy/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Ինքնապտտվող էկրան"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"Թույլատրե՞լ <xliff:g id="APPLICATION">%1$s</xliff:g> հավելվածին օգտագործել <xliff:g id="USB_DEVICE">%2$s</xliff:g> լրասարքը։"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Թույլատրե՞լ <xliff:g id="APPLICATION">%1$s</xliff:g> հավելվածին օգտագործել <xliff:g id="USB_DEVICE">%2$s</xliff:g>ը։\nՀավելվածը ձայնագրելու թույլտվություն չունի, սակայն կկարողանա գրանցել ձայնն այս USB սարքի միջոցով։"</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"Հասանելի դարձնե՞լ <xliff:g id="APPLICATION">%1$s</xliff:g> հավելվածին <xliff:g id="USB_DEVICE">%2$s</xliff:g> սարքը"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"Բացե՞լ <xliff:g id="APPLICATION">%1$s</xliff:g>-ը՝ <xliff:g id="USB_DEVICE">%2$s</xliff:g>-ը կառավարելու համար"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"Հավելվածը ձայնագրելու թույլտվություն չունի, սակայն կկարողանա գրանցել ձայնն այս USB սարքի միջոցով։ <xliff:g id="APPLICATION">%1$s</xliff:g> հավելվածն այս սարքի հետ օգտագործելիս հնարավոր է, որ չլսեք զանգերի, ծանուցումների և զարթուցիչների ձայները։"</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"<xliff:g id="APPLICATION">%1$s</xliff:g> հավելվածն այս սարքի հետ օգտագործելիս հնարավոր է, որ չլսեք զանգերի, ծանուցումների և զարթուցիչների ձայները։"</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"Թույլատրե՞լ <xliff:g id="APPLICATION">%1$s</xliff:g> հավելվածին օգտագործել <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> լրասարքը։"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"Բացե՞լ <xliff:g id="APPLICATION">%1$s</xliff:g> հավելվածը <xliff:g id="USB_DEVICE">%2$s</xliff:g> լրասարքը մշակելու համար։"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"Բացե՞լ <xliff:g id="APPLICATION">%1$s</xliff:g> հավելվածը՝ <xliff:g id="USB_DEVICE">%2$s</xliff:g>ն օգտագործելու համար:\nՀավելվածը ձայնագրելու թույլտվություն չունի, սակայն կկարողանա գրանցել ձայնն այս USB սարքի միջոցով։"</string> diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml index efbdc5458c78..302e5fdf5eff 100644 --- a/packages/SystemUI/res/values-in/strings.xml +++ b/packages/SystemUI/res/values-in/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Putar layar otomatis"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"Izinkan <xliff:g id="APPLICATION">%1$s</xliff:g> mengakses <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Izinkan <xliff:g id="APPLICATION">%1$s</xliff:g> mengakses <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nAplikasi ini belum diberi izin merekam, tetapi dapat merekam audio melalui perangkat USB ini."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"Izinkan <xliff:g id="APPLICATION">%1$s</xliff:g> mengakses <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"Buka <xliff:g id="APPLICATION">%1$s</xliff:g> untuk menangani <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"Aplikasi ini tidak diberi izin merekam, tetapi dapat merekam audio melalui perangkat USB ini. Menggunakan <xliff:g id="APPLICATION">%1$s</xliff:g> dengan perangkat ini mungkin dapat mencegah Anda mendengar panggilan, notifikasi, dan alarm."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"Menggunakan <xliff:g id="APPLICATION">%1$s</xliff:g> dengan perangkat ini dapat mencegah Anda mendengar panggilan, notifikasi, dan alarm."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"Izinkan <xliff:g id="APPLICATION">%1$s</xliff:g> mengakses <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"Buka <xliff:g id="APPLICATION">%1$s</xliff:g> untuk menangani <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"Buka <xliff:g id="APPLICATION">%1$s</xliff:g> untuk menangani <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nAplikasi ini belum diberi izin merekam, tetapi dapat merekam audio melalui perangkat USB ini."</string> diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml index effb84dd2fe2..39e7c0ffd531 100644 --- a/packages/SystemUI/res/values-is/strings.xml +++ b/packages/SystemUI/res/values-is/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Snúa skjá sjálfkrafa"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"Viltu veita <xliff:g id="APPLICATION">%1$s</xliff:g> aðgang að <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Viltu veita <xliff:g id="APPLICATION">%1$s</xliff:g> aðgang að <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nÞetta forrit hefur ekki fengið heimild fyrir upptöku en gæti tekið upp hljóð í gegnum þetta USB-tæki."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"Viltu veita <xliff:g id="APPLICATION">%1$s</xliff:g> aðgang að <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"Viltu opna <xliff:g id="APPLICATION">%1$s</xliff:g> til að sjá um <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"Þetta forrit hefur ekki fengið heimild fyrir upptöku en gæti tekið upp hljóð í gegnum þetta USB-tæki. Notkun <xliff:g id="APPLICATION">%1$s</xliff:g> með þessu tæki getur komið í veg fyrir að símtöl, tilkynningar og viðvaranir heyrist."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"Notkun <xliff:g id="APPLICATION">%1$s</xliff:g> með þessu tæki getur komið í veg fyrir að símtöl, tilkynningar og viðvaranir heyrist."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"Viltu veita <xliff:g id="APPLICATION">%1$s</xliff:g> aðgang að <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"Viltu opna <xliff:g id="APPLICATION">%1$s</xliff:g> til að sjá um <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"Viltu opna <xliff:g id="APPLICATION">%1$s</xliff:g> til að vinna með <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nÞetta forrit hefur ekki fengið heimild fyrir upptöku en gæti tekið upp hljóð í gegnum þetta USB-tæki."</string> diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml index 84dcfed3b5e8..605532329c83 100644 --- a/packages/SystemUI/res/values-it/strings.xml +++ b/packages/SystemUI/res/values-it/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Rotazione automatica schermo"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"Consentire a <xliff:g id="APPLICATION">%1$s</xliff:g> di accedere a <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Vuoi consentire all\'app <xliff:g id="APPLICATION">%1$s</xliff:g> di accedere a <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nA questa app non è stata concessa l\'autorizzazione di registrazione, ma l\'app potrebbe acquisire l\'audio tramite questo dispositivo USB."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"Consentire all\'app <xliff:g id="APPLICATION">%1$s</xliff:g> di accedere a <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"Aprire l\'app <xliff:g id="APPLICATION">%1$s</xliff:g> per gestire <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"All\'app non è stata concessa l\'autorizzazione di registrazione, ma potrebbe comunque acquisire audio tramite questo dispositivo USB. Se usi l\'app <xliff:g id="APPLICATION">%1$s</xliff:g> con questo dispositivo, potresti non riuscire a sentire chiamate, notifiche e sveglie."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"Se usi l\'app <xliff:g id="APPLICATION">%1$s</xliff:g> con questo dispositivo, potresti non riuscire a sentire chiamate, notifiche e sveglie."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"Consentire a <xliff:g id="APPLICATION">%1$s</xliff:g> di accedere a <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"Vuoi aprire <xliff:g id="APPLICATION">%1$s</xliff:g> per gestire <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"Vuoi aprire <xliff:g id="APPLICATION">%1$s</xliff:g> per gestire <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nA questa app non è stata concessa l\'autorizzazione di registrazione, ma l\'app potrebbe acquisire l\'audio tramite questo dispositivo USB."</string> diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml index 93263ae4d224..a765f02b1851 100644 --- a/packages/SystemUI/res/values-iw/strings.xml +++ b/packages/SystemUI/res/values-iw/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"סיבוב אוטומטי של המסך"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"לתת לאפליקציה <xliff:g id="APPLICATION">%1$s</xliff:g> גישה אל <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"האם לאפשר לאפליקציה <xliff:g id="APPLICATION">%1$s</xliff:g> גישה אל <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nאפליקציה זו לא קיבלה הרשאה להקליט אך יכולה לתעד אודיו באמצעות מכשיר USB זה."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"האם לתת לאפליקציה <xliff:g id="APPLICATION">%1$s</xliff:g> גישה אל <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"האם לפתוח את <xliff:g id="APPLICATION">%1$s</xliff:g> כדי לעבוד עם <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"לאפליקציה הזו אין הרשאת הקלטה, אבל אפשר להקליט אודיו באמצעות מכשיר ה-USB הזה. השימוש באפליקציה <xliff:g id="APPLICATION">%1$s</xliff:g> עם המכשיר הזה יכול למנוע ממך לשמוע שיחות, התראות או שעונים מעוררים."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"השימוש באפליקציה <xliff:g id="APPLICATION">%1$s</xliff:g> עם המכשיר הזה יכול למנוע ממך לשמוע שיחות, התראות או שעונים מעוררים."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"האם לתת לאפליקציה <xliff:g id="APPLICATION">%1$s</xliff:g> גישה אל <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"האם לפתוח את <xliff:g id="APPLICATION">%1$s</xliff:g> כדי לעבוד עם <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"לפתוח את <xliff:g id="APPLICATION">%1$s</xliff:g> לטיפול בהתקן <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nהאפליקציה הזו לא קיבלה הרשאה להקליט אך היא יכולה לתעד אודיו באמצעות התקן ה-USB הזה."</string> diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml index 07fd9cc0aec3..6407a6c819fb 100644 --- a/packages/SystemUI/res/values-ja/strings.xml +++ b/packages/SystemUI/res/values-ja/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"自動回転画面"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"<xliff:g id="APPLICATION">%1$s</xliff:g> に <xliff:g id="USB_DEVICE">%2$s</xliff:g> へのアクセスを許可しますか?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"<xliff:g id="APPLICATION">%1$s</xliff:g> に <xliff:g id="USB_DEVICE">%2$s</xliff:g>へのアクセスを許可しますか?\nこのアプリに録音権限は付与されていませんが、アクセスを許可すると、この USB デバイスから音声を収集できるようになります。"</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"<xliff:g id="APPLICATION">%1$s</xliff:g> に <xliff:g id="USB_DEVICE">%2$s</xliff:g> へのアクセスを許可しますか?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"<xliff:g id="APPLICATION">%1$s</xliff:g> を起動して <xliff:g id="USB_DEVICE">%2$s</xliff:g> を処理しますか?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"このアプリに録音権限は付与されていませんが、この USB デバイスから音声を収集できるようになります。このデバイスで <xliff:g id="APPLICATION">%1$s</xliff:g> を使用すると、着信音、通知音、アラームが鳴らなくなる可能性があります。"</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"このデバイスで <xliff:g id="APPLICATION">%1$s</xliff:g> を使用すると、着信音、通知音、アラームが鳴らなくなる可能性があります。"</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"<xliff:g id="APPLICATION">%1$s</xliff:g> に <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> へのアクセスを許可しますか?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"<xliff:g id="APPLICATION">%1$s</xliff:g> を起動して <xliff:g id="USB_DEVICE">%2$s</xliff:g> を処理しますか?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"<xliff:g id="APPLICATION">%1$s</xliff:g> を開いて <xliff:g id="USB_DEVICE">%2$s</xliff:g>を利用しますか?\nこのアプリに録音権限は付与されていませんが、この USB デバイスから音声を収集できるようになります。"</string> diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml index 3f301d182a97..864af68b1b41 100644 --- a/packages/SystemUI/res/values-ka/strings.xml +++ b/packages/SystemUI/res/values-ka/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"ეკრანის ავტოროტაცია"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"მიეცეს <xliff:g id="APPLICATION">%1$s</xliff:g>-ს <xliff:g id="USB_DEVICE">%2$s</xliff:g>-ზე წვდომის უფლება?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"დართავთ <xliff:g id="APPLICATION">%1$s</xliff:g>-ს <xliff:g id="USB_DEVICE">%2$s</xliff:g>-ზე წვდომის ნებას?\nამ აპს არ აქვს მინიჭებული ჩაწერის ნებართვა, მაგრამ შეუძლია ჩაიწეროს აუდიო ამ USB მოწყობილობის მეშვეობით."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"მიენიჭოს <xliff:g id="APPLICATION">%1$s</xliff:g>-ს <xliff:g id="USB_DEVICE">%2$s</xliff:g>-ზე წვდომა?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"გაიხსნას <xliff:g id="APPLICATION">%1$s</xliff:g>, <xliff:g id="USB_DEVICE">%2$s</xliff:g>-ის გამოსაყენებლად?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"ამ აპს არ აქვს მინიჭებული ჩაწერის ნებართვა, მაგრამ შეუძლია ჩაიწეროს აუდიო ამ USB მოწყობილობის მეშვეობით. ამ მოწყობილობაზე <xliff:g id="APPLICATION">%1$s</xliff:g>-ის გამოყენებამ შეიძლება ზარების, შეტყობინებებისა და მაღვიძარის ხმა გამორთოს."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"ამ მოწყობილობაზე <xliff:g id="APPLICATION">%1$s</xliff:g>-ის გამოყენებამ შეიძლება ზარების, შეტყობინებებისა და მაღვიძარის ხმა გამორთოს."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"მიეცეს <xliff:g id="APPLICATION">%1$s</xliff:g>-ს <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>-ზე წვდომის უფლება?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"გსურთ, გახსნათ <xliff:g id="APPLICATION">%1$s</xliff:g>, <xliff:g id="USB_DEVICE">%2$s</xliff:g>-ის გამოსაყენებლად?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"გახსნით <xliff:g id="APPLICATION">%1$s</xliff:g>-ს <xliff:g id="USB_DEVICE">%2$s</xliff:g>-ის გამოსაყენებლად?\nამ აპს არ აქვს მინიჭებული ჩაწერის ნებართვა, მაგრამ შეუძლია ჩაიწეროს აუდიო ამ USB მოწყობილობის მეშვეობით."</string> diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml index 7ad4006efa7d..cf6fae661966 100644 --- a/packages/SystemUI/res/values-kk/strings.xml +++ b/packages/SystemUI/res/values-kk/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Авто айналатын экран"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"<xliff:g id="APPLICATION">%1$s</xliff:g> қолданбасына <xliff:g id="USB_DEVICE">%2$s</xliff:g> құрылғысына кіруге рұқсат берілсін бе?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"<xliff:g id="APPLICATION">%1$s</xliff:g> қолданбасына <xliff:g id="USB_DEVICE">%2$s</xliff:g> құрылғысын пайдалануға рұқсат етілсін бе?\nҚолданбаның жазу рұқсаты жоқ, бірақ осы USB құрылғысы арқылы аудио жаза алады."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> құрылғысын <xliff:g id="APPLICATION">%1$s</xliff:g> пайдалансын ба?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> басқару үшін <xliff:g id="APPLICATION">%1$s</xliff:g> ашылсын ба?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"Қолданбаға жазу рұқсаты берілмеді, бірақ ол осы USB құрылғысы арқылы дыбыс жаза алады. Осы құрылғыда <xliff:g id="APPLICATION">%1$s</xliff:g> қолданбасын пайдаланған кезде, қоңырау, хабарландыру және дабыл дыбыстары естілмей қалуы мүмкін."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"Осы құрылғыда <xliff:g id="APPLICATION">%1$s</xliff:g> қолданбасын пайдаланған кезде, қоңырау, хабарландыру және дабыл дыбыстары естілмей қалуы мүмкін."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"<xliff:g id="APPLICATION">%1$s</xliff:g> қолданбасына <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> жабдығына кіруге рұқсат берілсін бе?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> басқару үшін <xliff:g id="APPLICATION">%1$s</xliff:g> ашылсын ба?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> құрылғысын пайдалану үшін <xliff:g id="APPLICATION">%1$s</xliff:g> қолданбасын ашу керек пе?\nҚолданбаға жазу рұқсаты берілмеді, бірақ ол осы USB құрылғысы арқылы дыбыс жаза алады."</string> diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml index 5fa7ad107965..7e028d9079c0 100644 --- a/packages/SystemUI/res/values-km/strings.xml +++ b/packages/SystemUI/res/values-km/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"បង្វិលអេក្រង់ស្វ័យប្រវត្តិ"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"អនុញ្ញាត <xliff:g id="APPLICATION">%1$s</xliff:g> ឱ្យចូលប្រើ <xliff:g id="USB_DEVICE">%2$s</xliff:g> មែនទេ?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"អនុញ្ញាតឱ្យ <xliff:g id="APPLICATION">%1$s</xliff:g> ចូលប្រើ <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nកម្មវិធីនេះមិនទាន់បានទទួលសិទ្ធិថតសំឡេងនៅឡើយទេ ប៉ុន្តែអាចថតសំឡេងតាមរយៈឧបករណ៍ USB នេះបាន។"</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"អនុញ្ញាតឱ្យ <xliff:g id="APPLICATION">%1$s</xliff:g> ចូលប្រើ <xliff:g id="USB_DEVICE">%2$s</xliff:g> ឬ?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"បើក <xliff:g id="APPLICATION">%1$s</xliff:g> ដើម្បីគ្រប់គ្រង <xliff:g id="USB_DEVICE">%2$s</xliff:g> ឬ?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"កម្មវិធីនេះមិនទាន់បានទទួលសិទ្ធិថតសំឡេងនៅឡើយទេ ប៉ុន្តែអាចថតសំឡេងតាមរយៈឧបករណ៍ USB នេះបាន។ ការប្រើ <xliff:g id="APPLICATION">%1$s</xliff:g> ជាមួយឧបករណ៍នេះអាចនឹងបិទសំឡេងការហៅទូរសព្ទ ការជូនដំណឹង និងម៉ោងរោទ៍។"</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"ការប្រើ <xliff:g id="APPLICATION">%1$s</xliff:g> ជាមួយឧបករណ៍នេះអាចនឹងបិទសំឡេងការហៅទូរសព្ទ ការជូនដំណឹង និងម៉ោងរោទ៍។"</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"អនុញ្ញាត <xliff:g id="APPLICATION">%1$s</xliff:g> ឱ្យចូលប្រើ <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> មែនទេ?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"បើក <xliff:g id="APPLICATION">%1$s</xliff:g> ដើម្បីគ្រប់គ្រង <xliff:g id="USB_DEVICE">%2$s</xliff:g> មែនទេ?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"បើក <xliff:g id="APPLICATION">%1$s</xliff:g> ដើម្បីគ្រប់គ្រង <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nកម្មវិធីនេះមិនទាន់បានទទួលសិទ្ធិថតសំឡេងនៅឡើយទេ ប៉ុន្តែអាចថតសំឡេងតាមរយៈឧបករណ៍ USB នេះ។"</string> diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml index 12f3d51f56ed..ec1d5bbd9314 100644 --- a/packages/SystemUI/res/values-kn/strings.xml +++ b/packages/SystemUI/res/values-kn/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"ಪರದೆಯನ್ನು ಸ್ವಯಂ-ತಿರುಗಿಸಿ"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ಪ್ರವೇಶಿಸಲು <xliff:g id="APPLICATION">%1$s</xliff:g> ಅನ್ನು ಅನುಮತಿಸುವುದೇ?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ಅನ್ನು ಪ್ರವೇಶಿಸಲು <xliff:g id="APPLICATION">%1$s</xliff:g> ಅನ್ನು ಅನುಮತಿಸುವುದೇ?\nಈ ಆ್ಯಪ್ಗೆ ರೆಕಾರ್ಡ್ ಅನುಮತಿಯನ್ನು ನೀಡಲಾಗಿಲ್ಲ, ಆದರೆ ಈ USB ಸಾಧನದ ಮೂಲಕ ಆಡಿಯೊವನ್ನು ಸೆರೆಹಿಡಿಯಬಹುದು."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ಗೆ ಆ್ಯಕ್ಸೆಸ್ ಮಾಡಲು <xliff:g id="APPLICATION">%1$s</xliff:g> ಅನ್ನು ಅನುಮತಿಸುವುದೇ?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ಅನ್ನು ನಿರ್ವಹಿಸಲು <xliff:g id="APPLICATION">%1$s</xliff:g> ಅನ್ನು ತೆರೆಯುವುದೇ?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"ಈ ಆ್ಯಪ್ಗೆ ರೆಕಾರ್ಡ್ ಅನುಮತಿಯನ್ನು ನೀಡಲಾಗಿಲ್ಲ, ಆದರೆ ಈ USB ಸಾಧನದ ಮೂಲಕ ಆಡಿಯೊವನ್ನು ಸೆರೆಹಿಡಿಯಬಲ್ಲದು. ಈ ಸಾಧನದ ಮೂಲಕ <xliff:g id="APPLICATION">%1$s</xliff:g> ಅನ್ನು ಬಳಸುವುದರಿಂದ ಕರೆಗಳು, ಅಧಿಸೂಚನೆಗಳು ಮತ್ತು ಅಲಾರಾಂಗಳನ್ನು ಕೇಳುವುದನ್ನು ತಡೆಯಬಹುದು."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"ಈ ಸಾಧನದ ಮೂಲಕ <xliff:g id="APPLICATION">%1$s</xliff:g> ಅನ್ನು ಬಳಸುವುದರಿಂದ ಕರೆಗಳು, ಅಧಿಸೂಚನೆಗಳು ಮತ್ತು ಅಲಾರಾಂಗಳನ್ನು ಕೇಳುವುದನ್ನು ತಡೆಯಬಹುದು."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> ಗೆ ಪ್ರವೇಶಿಸಲು <xliff:g id="APPLICATION">%1$s</xliff:g> ಅನ್ನು ಅನುಮತಿಸುವುದೇ?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ಅನ್ನು ನಿರ್ವಹಿಸಲು <xliff:g id="APPLICATION">%1$s</xliff:g> ಅನ್ನು ತೆರೆಯುವುದೇ?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ಅನ್ನು ನಿಯಂತ್ರಿಸಲು <xliff:g id="APPLICATION">%1$s</xliff:g> ಅನ್ನು ತೆರೆಯುವುದೇ?\nಈ ಆ್ಯಪ್ಗೆ ರೆಕಾರ್ಡ್ ಅನುಮತಿಯನ್ನು ನೀಡಲಾಗಿಲ್ಲ, ಆದರೆ ಈ USB ಸಾಧನದ ಮೂಲಕ ಆಡಿಯೊವನ್ನು ಸೆರೆಹಿಡಿಯಬಹುದು."</string> diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml index bf6a095c7df7..fb60dfe627b1 100644 --- a/packages/SystemUI/res/values-ko/strings.xml +++ b/packages/SystemUI/res/values-ko/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"화면 자동 회전"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"<xliff:g id="APPLICATION">%1$s</xliff:g> 앱이 <xliff:g id="USB_DEVICE">%2$s</xliff:g>에 액세스하도록 허용하시겠습니까?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"<xliff:g id="APPLICATION">%1$s</xliff:g>에서 <xliff:g id="USB_DEVICE">%2$s</xliff:g>에 액세스하도록 허용하시겠습니까?\n이 앱에는 녹음 권한이 부여되지 않았지만, 이 USB 기기를 통해 오디오를 녹음할 수 있습니다."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"<xliff:g id="APPLICATION">%1$s</xliff:g> 앱이 <xliff:g id="USB_DEVICE">%2$s</xliff:g>에 액세스하도록 허용하시겠습니까?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"<xliff:g id="APPLICATION">%1$s</xliff:g> 앱을 열어 <xliff:g id="USB_DEVICE">%2$s</xliff:g>을(를) 처리하시겠습니까?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"이 앱에는 녹음 권한이 부여되지 않았지만, 이 USB 기기를 통해 오디오를 녹음할 수 있습니다. 이 기기와 함께 <xliff:g id="APPLICATION">%1$s</xliff:g> 앱을 사용하면 전화, 알림, 알람 소리가 들리지 않을 수 있습니다."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"이 기기와 함께 <xliff:g id="APPLICATION">%1$s</xliff:g> 앱을 사용하면 전화, 알림, 알람 소리가 들리지 않을 수 있습니다."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"<xliff:g id="APPLICATION">%1$s</xliff:g> 앱이 <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>에 액세스하도록 허용하시겠습니까?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"<xliff:g id="APPLICATION">%1$s</xliff:g> 앱을 열어 <xliff:g id="USB_DEVICE">%2$s</xliff:g>을(를) 처리하시겠습니까?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>을(를) 처리하기 위해 <xliff:g id="APPLICATION">%1$s</xliff:g>을(를) 여시겠습니까?\n이 앱에는 녹음 권한이 부여되지 않았지만, 이 USB 기기를 통해 오디오를 녹음할 수 있습니다."</string> diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml index 950f9d790fcf..51501b2d8e2e 100644 --- a/packages/SystemUI/res/values-ky/strings.xml +++ b/packages/SystemUI/res/values-ky/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Экранды авто буруу"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"<xliff:g id="APPLICATION">%1$s</xliff:g> колдонмосу <xliff:g id="USB_DEVICE">%2$s</xliff:g> түзмөгүн колдоно берсинби?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"<xliff:g id="APPLICATION">%1$s</xliff:g> колдонмосу <xliff:g id="USB_DEVICE">%2$s</xliff:g> түзмөгүн колдоно берсинби?\nБул колдонмого жаздырууга уруксат берилген эмес, бирок ушул USB түзмөгү аркылуу үндөрдү жаза алат."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"<xliff:g id="APPLICATION">%1$s</xliff:g> колдонмосу <xliff:g id="USB_DEVICE">%2$s</xliff:g> кабелин колдоно берсинби?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> түзмөгүн колдонуу үчүн <xliff:g id="APPLICATION">%1$s</xliff:g> колдонмосун ачасызбы?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"Колдонмо аудио жаздырууга уруксат алган эмес, бирок ушул USB түзмөк аркылуу жаза алат. \"<xliff:g id="APPLICATION">%1$s</xliff:g>\" колдонмосун ушул түзмөк менен колдонуп жатканда, билдирмелердин, чалуулардын жана ойготкучтардын үнүн укпай калышыңыз мүмкүн."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"<xliff:g id="APPLICATION">%1$s</xliff:g> колдонмосун бул түзмөктө иштетсеңиз, чалууларды, билдирмелерди жана ойготкучтарды уга албай калышыңыз мүмкүн."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"<xliff:g id="APPLICATION">%1$s</xliff:g> колдонмосу <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> кабелин колдоно берсинби?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> түзмөгүнө туташуу үчүн <xliff:g id="APPLICATION">%1$s</xliff:g> колдонмосу ачылсынбы?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> түзмөгүн колдонуу үчүн <xliff:g id="APPLICATION">%1$s</xliff:g> колдонмосун ачасызбы?\nБул колдонмого жаздырууга уруксат берилген эмес, бирок ушул USB түзмөгү аркылуу үндөрдү жаза алат."</string> diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml index e0a8476a1f11..3e70601245f1 100644 --- a/packages/SystemUI/res/values-lo/strings.xml +++ b/packages/SystemUI/res/values-lo/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"ໝຸນໜ້າຈໍອັດຕະໂນມັດ"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"ອະນຸຍາດໃຫ້ <xliff:g id="APPLICATION">%1$s</xliff:g> ເຂົ້າເຖິງ <xliff:g id="USB_DEVICE">%2$s</xliff:g> ໄດ້ບໍ?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"ອະນຸຍາດໃຫ້ <xliff:g id="APPLICATION">%1$s</xliff:g> ເຂົ້າເຖິງ <xliff:g id="USB_DEVICE">%2$s</xliff:g> ໄດ້ບໍ?\nແອັບນີ້ບໍ່ໄດ້ຮັບອະນຸາດໃຫ້ບັນທຶກໄດ້ແຕ່ສາມາດບັນທຶກສຽງໄດ້ຜ່ານອຸປະກອນ USB ນີ້."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"ອະນຸຍາດໃຫ້ <xliff:g id="APPLICATION">%1$s</xliff:g> ເຂົ້າເຖິງ <xliff:g id="USB_DEVICE">%2$s</xliff:g> ໄດ້ບໍ?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"ເປີດ <xliff:g id="APPLICATION">%1$s</xliff:g> ເພື່ອຈັດການ <xliff:g id="USB_DEVICE">%2$s</xliff:g> ບໍ?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"ແອັບນີ້ບໍ່ໄດ້ຮັບການອະນຸຍາດໃນການບັນທຶກ ແຕ່ສາມາດບັນທຶກສຽງໄດ້ຜ່ານອຸປະກອນ USB ນີ້ໄດ້. ການໃຊ້ <xliff:g id="APPLICATION">%1$s</xliff:g> ກັບອຸປະກອນນີ້ອາດປ້ອງກັນບໍ່ໃຫ້ໄດ້ຍິນສຽງໂທລະສັບ, ການແຈ້ງເຕືອນ ແລະ ໂມງປຸກ."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"ການໃຊ້ <xliff:g id="APPLICATION">%1$s</xliff:g> ກັບອຸປະກອນນີ້ອາດປ້ອງກັນບໍ່ໃຫ້ໄດ້ຍິນສຽງໂທລະສັບ, ການແຈ້ງເຕືອນ ແລະ ໂມງປຸກ."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"ອະນຸຍາດໃຫ້ <xliff:g id="APPLICATION">%1$s</xliff:g> ເຂົ້າເຖິງ <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> ໄດ້ບໍ?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"ເປີດ <xliff:g id="APPLICATION">%1$s</xliff:g> ເພື່ອໃຊ້ກັບ <xliff:g id="USB_DEVICE">%2$s</xliff:g> ບໍ?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"ເປີດ <xliff:g id="APPLICATION">%1$s</xliff:g> ເພື່ອໃຊ້ <xliff:g id="USB_DEVICE">%2$s</xliff:g> ບໍ?\nແອັບນີ້ຍັງບໍ່ໄດ້ຮັບອະນຸຍາດໃຫ້ບັນທຶກເທື່ອ ແຕ່ສາມາດບັນທຶກສຽງຜ່ານອຸປະກອນ USB ນີ້ໄດ້."</string> diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml index 18de354fa657..4ed6148097c6 100644 --- a/packages/SystemUI/res/values-lt/strings.xml +++ b/packages/SystemUI/res/values-lt/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Automatiškai sukti ekraną"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"Leisti „<xliff:g id="APPLICATION">%1$s</xliff:g>“ pasiekti įrenginį (<xliff:g id="USB_DEVICE">%2$s</xliff:g>)?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Leisti „<xliff:g id="APPLICATION">%1$s</xliff:g>“ pasiekti įrenginį (<xliff:g id="USB_DEVICE">%2$s</xliff:g>)?\nŠiai programai nebuvo suteiktas leidimas įrašyti, bet ji gali užfiksuoti garsą per šį USB įrenginį."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"Leisti „<xliff:g id="APPLICATION">%1$s</xliff:g>“ pasiekti įrenginį (<xliff:g id="USB_DEVICE">%2$s</xliff:g>)?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"Atidaryti „<xliff:g id="APPLICATION">%1$s</xliff:g>“, kad būtų galima tvarkyti įrenginį (<xliff:g id="USB_DEVICE">%2$s</xliff:g>)?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"Šiai programai nebuvo suteiktas leidimas įrašyti, bet ji gali užfiksuoti garsą per šį USB įrenginį. Naudodami „<xliff:g id="APPLICATION">%1$s</xliff:g>“ šiuo įrenginiu galite negirdėti skambučių, pranešimų ir signalų."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"Naudodami „<xliff:g id="APPLICATION">%1$s</xliff:g>“ šiuo įrenginiu galite negirdėti skambučių, pranešimų ir signalų."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"Leisti „<xliff:g id="APPLICATION">%1$s</xliff:g>“ pasiekti įrenginį (<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>)?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"Atidaryti „<xliff:g id="APPLICATION">%1$s</xliff:g>“, kad būtų galima tvarkyti įrenginį (<xliff:g id="USB_DEVICE">%2$s</xliff:g>)?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"Atidaryti programą „<xliff:g id="APPLICATION">%1$s</xliff:g>“, kad ji galėtų tvarkyti „<xliff:g id="USB_DEVICE">%2$s</xliff:g>“?\nŠiai programai nebuvo suteiktas leidimas įrašyti, bet ji gali užfiksuoti garsą per šį USB įrenginį."</string> diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml index c87ba4401c3a..fde5dba60ad8 100644 --- a/packages/SystemUI/res/values-lv/strings.xml +++ b/packages/SystemUI/res/values-lv/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Automātiska ekrāna pagriešana"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"Vai atļaut lietotnei <xliff:g id="APPLICATION">%1$s</xliff:g> piekļūt šai ierīcei: <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Vai atļaut lietotnei <xliff:g id="APPLICATION">%1$s</xliff:g> piekļūt ierīcei “<xliff:g id="USB_DEVICE">%2$s</xliff:g>”?\nŠai lietotnei nav piešķirta ierakstīšanas atļauja, taču tā varētu tvert audio, izmantojot šo USB ierīci."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"Vai atļaut lietotnei <xliff:g id="APPLICATION">%1$s</xliff:g> piekļūt šai ierīcei: <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"Vai atvērt lietotni <xliff:g id="APPLICATION">%1$s</xliff:g>, lai izmantotu šo ierīci: <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"Šai lietotnei nav piešķirta ierakstīšanas atļauja, taču tā varētu tvert audio, izmantojot šo USB ierīci. Ja izmantosiet lietotni <xliff:g id="APPLICATION">%1$s</xliff:g> kopā ar šo ierīci, varbūt nedzirdēsiet zvanus, paziņojumus un brīdinājumus."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"Ja izmantosiet lietotni <xliff:g id="APPLICATION">%1$s</xliff:g> kopā ar šo ierīci, varbūt nedzirdēsiet zvanus, paziņojumus un brīdinājumus."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"Vai atļaut lietotnei <xliff:g id="APPLICATION">%1$s</xliff:g> piekļūt šim piederumam: <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"Vai atvērt lietotni <xliff:g id="APPLICATION">%1$s</xliff:g>, lai izmantotu šo ierīci: <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"Vai vēlaties atvērt lietotni <xliff:g id="APPLICATION">%1$s</xliff:g>, lai pārvaldītu ierīci <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nŠai lietotnei nav piešķirta ierakstīšanas atļauja, taču tā varētu tvert audio, izmantojot šo USB ierīci."</string> diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml index 599988c736fe..ac08d07bd72f 100644 --- a/packages/SystemUI/res/values-mk/strings.xml +++ b/packages/SystemUI/res/values-mk/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Автоматско ротирање на екранот"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"Ќе дозволите <xliff:g id="APPLICATION">%1$s</xliff:g> да пристапува до <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Дали дозволувате <xliff:g id="APPLICATION">%1$s</xliff:g> да пристапи до <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nНа апликацијава не ѝ е доделена дозвола за снимање, но може да снима аудио преку овој USB-уред."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"Ќе дозволите <xliff:g id="APPLICATION">%1$s</xliff:g> да пристапува до <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"Да се отвори <xliff:g id="APPLICATION">%1$s</xliff:g> за да управува со <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"На апликацијава не ѝ е доделена дозвола за снимање, но може да снима аудио преку овој USB-уред. Ако ја користите <xliff:g id="APPLICATION">%1$s</xliff:g> со уредов, може да се спречи слушањето повици, известувања и аларми."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"Ако ја користите <xliff:g id="APPLICATION">%1$s</xliff:g> со уредов, може да се спречи слушањето повици, известувања и аларми."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"Ќе дозволите <xliff:g id="APPLICATION">%1$s</xliff:g> да пристапува до <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"Да се отвори <xliff:g id="APPLICATION">%1$s</xliff:g> за да управува со <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"Да се отвори ли <xliff:g id="APPLICATION">%1$s</xliff:g> за да се управува со <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nНа апликацијава не ѝ е доделена дозвола за снимање, но може да снима аудио преку овој USB-уред."</string> diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml index c285d77bf4d6..daa111dea7be 100644 --- a/packages/SystemUI/res/values-ml/strings.xml +++ b/packages/SystemUI/res/values-ml/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"സ്ക്രീൻ സ്വയമേ തിരിയുക"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ആക്സസ് ചെയ്യാൻ <xliff:g id="APPLICATION">%1$s</xliff:g>-നെ അനുവദിക്കണോ?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ആക്സസ് ചെയ്യാൻ <xliff:g id="APPLICATION">%1$s</xliff:g> എന്നതിനെ അനുവദിക്കണോ?\nഈ ആപ്പിന് റെക്കോർഡ് അനുമതി നൽകിയിട്ടില്ല, എന്നാൽ ഈ USB ഉപകരണത്തിലൂടെ ഓഡിയോ ക്യാപ്ചർ ചെയ്യാനാവും."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ആക്സസ് ചെയ്യാൻ <xliff:g id="APPLICATION">%1$s</xliff:g> എന്നതിനെ അനുവദിക്കണോ?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> കൈകാര്യം ചെയ്യാൻ <xliff:g id="APPLICATION">%1$s</xliff:g> തുറക്കണോ?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"ഈ ആപ്പിന് റെക്കോർഡ് അനുമതി നൽകിയിട്ടില്ല, എന്നാൽ ഈ USB ഉപകരണത്തിലൂടെ ഓഡിയോ ക്യാപ്ചർ ചെയ്യാനാവും. ഈ ഉപകരണത്തിൽ <xliff:g id="APPLICATION">%1$s</xliff:g> ഉപയോഗിക്കുന്നത് കോളുകളും അറിയിപ്പുകളും അലാറങ്ങളും കേൾക്കുന്നതിൽ നിന്ന് തടഞ്ഞേക്കാം."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"ഈ ഉപകരണത്തിൽ <xliff:g id="APPLICATION">%1$s</xliff:g> ഉപയോഗിക്കുന്നത് കോളുകളും അറിയിപ്പുകളും അലാറങ്ങളും കേൾക്കുന്നതിൽ നിന്ന് തടഞ്ഞേക്കാം."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> ആക്സസ് ചെയ്യാൻ <xliff:g id="APPLICATION">%1$s</xliff:g>-നെ അനുവദിക്കണോ?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> കൈകാര്യം ചെയ്യാൻ <xliff:g id="APPLICATION">%1$s</xliff:g> തുറക്കണോ?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"<xliff:g id="APPLICATION">%1$s</xliff:g> തുറന്ന് <xliff:g id="USB_DEVICE">%2$s</xliff:g> കൈകാര്യം ചെയ്യണോ?\nഈ ആപ്പിന് റെക്കോർഡ് അനുമതി നൽകിയിട്ടില്ല, എന്നാൽ ഈ USB ഉപകരണത്തിലൂടെ ഓഡിയോ ക്യാപ്ചർ ചെയ്യാനാവും."</string> diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml index b661341c213c..d2f098d9d2b3 100644 --- a/packages/SystemUI/res/values-mn/strings.xml +++ b/packages/SystemUI/res/values-mn/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Дэлгэцийг автоматаар эргүүлэх"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"<xliff:g id="APPLICATION">%1$s</xliff:g>-г <xliff:g id="USB_DEVICE">%2$s</xliff:g>-д хандахыг зөвшөөрөх үү?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"<xliff:g id="APPLICATION">%1$s</xliff:g>-д <xliff:g id="USB_DEVICE">%2$s</xliff:g>-д хандахыг зөвшөөрөх үү?\nЭнэ аппад бичих зөвшөөрөл олгогдоогүй ч USB төхөөрөмжөөр дамжуулан аудио бичиж чадсан."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"<xliff:g id="APPLICATION">%1$s</xliff:g>-д <xliff:g id="USB_DEVICE">%2$s</xliff:g>-д хандахыг зөвшөөрөх үү?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>-г зохицуулахын тулд <xliff:g id="APPLICATION">%1$s</xliff:g>-г нээх үү?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"Энэ аппад бичих зөвшөөрөл олгоогүй хэдий ч энэ USB төхөөрөмжөөр дамжуулан аудио бичиж болно. <xliff:g id="APPLICATION">%1$s</xliff:g>-г энэ төхөөрөмжтэй ашигласнаар дуудлага, мэдэгдэл болон сэрүүлэг сонсохоос сэргийлж магадгүй."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"<xliff:g id="APPLICATION">%1$s</xliff:g>-г энэ төхөөрөмжтэй ашигласнаар дуудлага, мэдэгдэл болон сэрүүлэг сонсохоос сэргийлж магадгүй."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"<xliff:g id="APPLICATION">%1$s</xliff:g>-г <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>-д хандахыг зөвшөөрөх үү?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>-г зохицуулахын тулд <xliff:g id="APPLICATION">%1$s</xliff:g>-г нээх үү?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>-г зохицуулахын тулд <xliff:g id="APPLICATION">%1$s</xliff:g>-г нээх үү?\nЭнэ апликейшнд бичих зөвшөөрөл олгогдоогүй ч энэ USB төхөөрөмжөөр дамжуулан аудио бичиж чадсан."</string> diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml index 8c0714c8d27f..edd0cde85f1d 100644 --- a/packages/SystemUI/res/values-mr/strings.xml +++ b/packages/SystemUI/res/values-mr/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"ऑटो-रोटेट स्क्रीन"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"<xliff:g id="APPLICATION">%1$s</xliff:g> ला <xliff:g id="USB_DEVICE">%2$s</xliff:g> अॅक्सेस करण्याची अनुमती द्यायची का?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"<xliff:g id="APPLICATION">%1$s</xliff:g> ला <xliff:g id="USB_DEVICE">%2$s</xliff:g> अॅक्सेस करण्याची अनुमती द्यायची का?\nया अॅपला रेकॉर्ड करण्याची परवानगी दिलेली नाही पण या USB डिव्हाइसद्वारे ऑडिओ कॅप्चर केला जाऊ शकतो."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"<xliff:g id="APPLICATION">%1$s</xliff:g> ला <xliff:g id="USB_DEVICE">%2$s</xliff:g> अॅक्सेस करण्याची अनुमती द्यायची आहे का?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> हाताळण्यासाठी <xliff:g id="APPLICATION">%1$s</xliff:g> उघडायचे आहे का?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"या अॅपला रेकॉर्ड करण्याची परवानगी दिलेली नाही, पण या USB डिव्हाइसद्वारे ऑडिओ कॅप्चर केला जाऊ शकतो. <xliff:g id="APPLICATION">%1$s</xliff:g> चा वापर या डिव्हाइससह केल्याने कॉल, सूचना आणि अलार्मचा आवाज कदाचित ऐकू येणार नाही."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"<xliff:g id="APPLICATION">%1$s</xliff:g> चा वापर या डिव्हाइससह केल्याने कॉल, सूचना आणि अलार्मचा आवाज कदाचित ऐकू येणार नाही."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"<xliff:g id="APPLICATION">%1$s</xliff:g> ला <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> अॅक्सेस करण्याची अनुमती द्यायची का?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> हाताळण्यासाठी <xliff:g id="APPLICATION">%1$s</xliff:g> उघडायचे का?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> हँडल करण्यासाठी <xliff:g id="APPLICATION">%1$s</xliff:g> उघडायचे आहे का? \n या अॅपला रेकॉर्ड करण्याची परवानगी दिलेली नाही पण या USB डिव्हाइसद्वारे ऑडिओ कॅप्चर केला जाऊ शकतो."</string> diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml index 5764807863d7..ff69cff4dd72 100644 --- a/packages/SystemUI/res/values-ms/strings.xml +++ b/packages/SystemUI/res/values-ms/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Autoputar skrin"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"Benarkan <xliff:g id="APPLICATION">%1$s</xliff:g> mengakses <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Benarkan <xliff:g id="APPLICATION">%1$s</xliff:g> mengakses <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nApl ini belum diberikan kebenaran merakam tetapi dapat merakam audio melalui peranti USB ini."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"Benarkan <xliff:g id="APPLICATION">%1$s</xliff:g> mengakses <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"Buka <xliff:g id="APPLICATION">%1$s</xliff:g> untuk mengendalikan <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"Apl ini belum diberi kebenaran merakam tetapi dapat merakam audio melalui peranti USB ini. Tindakan menggunakan <xliff:g id="APPLICATION">%1$s</xliff:g> dengan peranti ini mungkin menghalang anda daripada mendengar panggilan, pemberitahuan dan penggera."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"Tindakan menggunakan <xliff:g id="APPLICATION">%1$s</xliff:g> dengan peranti ini mungkin menghalang anda daripada mendengar panggilan, pemberitahuan dan penggera."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"Benarkan <xliff:g id="APPLICATION">%1$s</xliff:g> mengakses <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"Buka <xliff:g id="APPLICATION">%1$s</xliff:g> untuk mengendalikan <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"Buka <xliff:g id="APPLICATION">%1$s</xliff:g> untuk mengendalikan <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nApl ini belum diberikan kebenaran merakam tetapi dapat merakam audio melalui peranti USB ini."</string> diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml index 9d8ab46d6335..3f1541ca8042 100644 --- a/packages/SystemUI/res/values-my/strings.xml +++ b/packages/SystemUI/res/values-my/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"ဖန်သားပြင် အလိုအလျောက်လှည့်ရန်"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> အား ဝင်သုံးရန် <xliff:g id="APPLICATION">%1$s</xliff:g> ကို ခွင့်ပြုပါသလား။"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"<xliff:g id="APPLICATION">%1$s</xliff:g> အား <xliff:g id="USB_DEVICE">%2$s</xliff:g> ကို သုံးခွင့်ပြုမလား။\nဤအက်ပ်ကို အသံဖမ်းခွင့် ပေးမထားသော်လည်း ၎င်းသည် ဤ USB စက်ပစ္စည်းမှတစ်ဆင့် အသံများကို ဖမ်းယူနိုင်ပါသည်။"</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"<xliff:g id="APPLICATION">%1$s</xliff:g> ကို <xliff:g id="USB_DEVICE">%2$s</xliff:g> ဝင်သုံးခွင့်ပြုမလား။"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ဆောင်ရွက်ရန် <xliff:g id="APPLICATION">%1$s</xliff:g> ကို ဖွင့်လိုပါသလား။"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"ဤအက်ပ်ကို အသံဖမ်းခွင့် ပေးမထားသော်လည်း ၎င်းသည် ဤ USB စက်ပစ္စည်းမှတစ်ဆင့် အသံများကို ဖမ်းယူနိုင်ပါသည်။ ဤစက်ဖြင့် <xliff:g id="APPLICATION">%1$s</xliff:g> အသုံးပြုခြင်းက ဖုန်းအဝင်၊ အကြောင်းကြားချက်နှင့် နှိုးစက်သံ မကြားခြင်းများ ဖြစ်စေနိုင်သည်။"</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"ဤစက်ဖြင့် <xliff:g id="APPLICATION">%1$s</xliff:g> အသုံးပြုခြင်းက ဖုန်းအဝင်၊ အကြောင်းကြားချက်နှင့် နှိုးစက်သံ မကြားခြင်းများ ဖြစ်စေနိုင်သည်။"</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> အား ဝင်သုံးရန် <xliff:g id="APPLICATION">%1$s</xliff:g> ကို ခွင့်ပြုပါသလား။"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> စီမံရန် <xliff:g id="APPLICATION">%1$s</xliff:g> ကို ဖွင့်လိုပါသလား။"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ကို သုံးရန် <xliff:g id="APPLICATION">%1$s</xliff:g> ကို ဖွင့်မလား။\nဤအက်ပ်ကို အသံဖမ်းခွင့် ပေးမထားသော်လည်း ၎င်းသည် ဤ USB စက်ပစ္စည်းမှတစ်ဆင့် အသံများကို ဖမ်းယူနိုင်ပါသည်။"</string> diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml index 0311e310acc9..36297abfb47a 100644 --- a/packages/SystemUI/res/values-nb/strings.xml +++ b/packages/SystemUI/res/values-nb/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Rotér skjermen automatisk"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"Vil du gi <xliff:g id="APPLICATION">%1$s</xliff:g> tilgang til <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Vil du gi <xliff:g id="APPLICATION">%1$s</xliff:g> tilgang til <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nDenne appen har ikke fått tillatelse til å spille inn, men kan ta opp lyd med denne USB-enheten."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"Vil du gi <xliff:g id="APPLICATION">%1$s</xliff:g> tilgang til <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"Vil du åpne <xliff:g id="APPLICATION">%1$s</xliff:g> for å behandle <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"Denne appen har ikke fått tillatelse til å spille inn, men kan ta opp lyd med denne USB-enheten. Hvis du bruker <xliff:g id="APPLICATION">%1$s</xliff:g> med denne enheten, kan det føre til at du ikke hører anrop, varsler og alarmer."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"Hvis du bruker <xliff:g id="APPLICATION">%1$s</xliff:g> med denne enheten, kan det føre til at du ikke hører anrop, varsler og alarmer."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"Vil du gi <xliff:g id="APPLICATION">%1$s</xliff:g> tilgang til <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"Vil du åpne <xliff:g id="APPLICATION">%1$s</xliff:g> for å behandle <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"Vil du åpne <xliff:g id="APPLICATION">%1$s</xliff:g> for å håndtere <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nDenne appen har ikke fått tillatelse til å spille inn, men kan ta opp lyd med denne USB-enheten."</string> diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml index a2121ec7a84a..63760ccb15dd 100644 --- a/packages/SystemUI/res/values-ne/strings.xml +++ b/packages/SystemUI/res/values-ne/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"स्वत:घुम्ने स्क्रिन"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"<xliff:g id="APPLICATION">%1$s</xliff:g> लाई <xliff:g id="USB_DEVICE">%2$s</xliff:g> माथि पहुँच राख्ने अनुमति दिने हो?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"<xliff:g id="APPLICATION">%1$s</xliff:g> लाई <xliff:g id="USB_DEVICE">%2$s</xliff:g> माथि पहुँच राख्न अनुमति दिने हो?\nयो एपलाई रेकर्ड गर्ने अनुमति प्रदान गरिएको छैन तर यसले USB यन्त्रमार्फत अडियो क्याप्चर गर्न सक्छ।"</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"<xliff:g id="APPLICATION">%1$s</xliff:g> लाई <xliff:g id="USB_DEVICE">%2$s</xliff:g> प्रयोग गर्ने अनुमति दिने हो?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> को व्यवस्थापन गर्न <xliff:g id="APPLICATION">%1$s</xliff:g> खोल्ने हो?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"यो एपलाई रेकर्ड गर्ने अनुमति दिइएको छैन तर यसले यो USB डिभाइसमार्फत अडियो रेकर्ड गर्न सक्छ। तपाईंले यो डिभाइसमा <xliff:g id="APPLICATION">%1$s</xliff:g> प्रयोग गर्नुभयो भने तपाईंले कल, सूचना र अलार्मको आवाज नसुन्ने सम्भावना हुन्छ।"</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"तपाईंले यो डिभाइसमा <xliff:g id="APPLICATION">%1$s</xliff:g> प्रयोग गर्नुभयो भने तपाईंले कल, सूचना र अलार्मको आवाज नसुन्ने सम्भावना हुन्छ।"</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"<xliff:g id="APPLICATION">%1$s</xliff:g> लाई <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> माथि पहुँच राख्ने अनुमति दिने हो?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> को व्यवस्थापन गर्न <xliff:g id="APPLICATION">%1$s</xliff:g> खोल्ने हो?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"<xliff:g id="APPLICATION">%1$s</xliff:g> लाई <xliff:g id="USB_DEVICE">%2$s</xliff:g> सञ्चालन गर्न खोल्ने हो?\nयो एपलाई रेकर्ड गर्ने अनुमति प्रदान गरिएको छैन तर यसले USB यन्त्रमार्फत अडियो क्याप्चर गर्न सक्छ।"</string> diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml index 921f508c264c..76901da84f7e 100644 --- a/packages/SystemUI/res/values-nl/strings.xml +++ b/packages/SystemUI/res/values-nl/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Scherm automatisch draaien"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"<xliff:g id="APPLICATION">%1$s</xliff:g> toegang geven tot <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"<xliff:g id="APPLICATION">%1$s</xliff:g> toegang geven tot <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nDeze app heeft geen opnamerechten gekregen, maar zou audio kunnen vastleggen via dit USB-apparaat."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"<xliff:g id="APPLICATION">%1$s</xliff:g> toegang geven tot <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"<xliff:g id="APPLICATION">%1$s</xliff:g> openen om te werken met <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"Deze app heeft geen opnamerechten gekregen, maar zou audio kunnen vastleggen via dit USB-apparaat. Als je <xliff:g id="APPLICATION">%1$s</xliff:g> gebruikt met dit apparaat, hoor je misschien geen gesprekken, meldingen en wekkers."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"Als je <xliff:g id="APPLICATION">%1$s</xliff:g> gebruikt met dit apparaat, hoor je misschien geen gesprekken, meldingen en wekkers."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"<xliff:g id="APPLICATION">%1$s</xliff:g> toegang geven tot <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"<xliff:g id="APPLICATION">%1$s</xliff:g> openen om <xliff:g id="USB_DEVICE">%2$s</xliff:g> te verwerken?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"<xliff:g id="APPLICATION">%1$s</xliff:g> openen om <xliff:g id="USB_DEVICE">%2$s</xliff:g> te verwerken?\nDeze app heeft geen opnamerechten gekregen, maar zou audio kunnen vastleggen via dit USB-apparaat."</string> diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml index 3f3c7a84ef04..a6565be16eb4 100644 --- a/packages/SystemUI/res/values-or/strings.xml +++ b/packages/SystemUI/res/values-or/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"ଅଟୋ-ରୋଟେଟ୍ ସ୍କ୍ରିନ୍"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ଆକ୍ସେସ୍ କରିବାକୁ <xliff:g id="APPLICATION">%1$s</xliff:g>କୁ ଅନୁମତି ଦେବେ?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ଆକ୍ସେସ୍ କରିବାକୁ <xliff:g id="APPLICATION">%1$s</xliff:g>କୁ ଅନୁମତି ଦେବେ କି?\nଏହି ଆପ୍କୁ ରେକର୍ଡ କରିବାକୁ ଅନୁମତି ଦିଆଯାଇ ନାହିଁ କିନ୍ତୁ ଏହି USB ଡିଭାଇସ୍ ଜରିଆରେ ଅଡିଓ କ୍ୟାପ୍ଟର୍ କରିପାରିବ।"</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>କୁ ଆକ୍ସେସ କରିବା ପାଇଁ <xliff:g id="APPLICATION">%1$s</xliff:g>କୁ ଅନୁମତି ଦେବେ?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>କୁ ନିୟନ୍ତ୍ରଣ କରିବା ପାଇଁ <xliff:g id="APPLICATION">%1$s</xliff:g>କୁ ଖୋଲିବେ?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"ଏହି ଆପକୁ ରେକର୍ଡ କରିବା ପାଇଁ ଅନୁମତି ଦିଆଯାଇନାହିଁ, କିନ୍ତୁ ଏହି USB ଡିଭାଇସ ମାଧ୍ୟମରେ ଏହା ଅଡିଓକୁ କ୍ୟାପଚର କରିପାରିବ। ଏହି ଡିଭାଇସରେ <xliff:g id="APPLICATION">%1$s</xliff:g> ବ୍ୟବହାର କଲେ କଲ, ବିଜ୍ଞପ୍ତି ଏବଂ ଆଲାରାମଗୁଡ଼ିକୁ ଶୁଣିବାରୁ ପ୍ରତିରୋଧ କରାଯାଇପାରେ।"</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"ଏହି ଡିଭାଇସରେ <xliff:g id="APPLICATION">%1$s</xliff:g> ବ୍ୟବହାର କରିବା କଲ, ବିଜ୍ଞପ୍ତି ଏବଂ ଆଲାରାମଗୁଡ଼ିକୁ ଶୁଣିବାରୁ ପ୍ରତିରୋଧ କରିପାରେ।"</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g> ଆକ୍ସେସ୍ କରିବାକୁ <xliff:g id="APPLICATION">%1$s</xliff:g>କୁ ଅନୁମତି ଦେବେ?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ନିୟନ୍ତ୍ରଣ କରିବାକୁ <xliff:g id="APPLICATION">%1$s</xliff:g> ଖୋଲିବେ?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ପରିଚାଳନା କରିବାକୁ <xliff:g id="APPLICATION">%1$s</xliff:g>କୁ ଖୋଲିବେ?\nଏହି ଆପ୍କୁ ରେକର୍ଡ କରିବାକୁ ଅନୁମତି ଦିଆଯାଇ ନାହିଁ କିନ୍ତୁ ଏହି USB ଡିଭାଇସ୍ ଜରିଆରେ, ଏହା ଅଡିଓ କ୍ୟାପ୍ଟର୍ କରିପାରିବ।"</string> diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml index e17405f28948..9f46cf136116 100644 --- a/packages/SystemUI/res/values-pa/strings.xml +++ b/packages/SystemUI/res/values-pa/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"ਸਕ੍ਰੀਨ ਸਵੈ-ਘੁਮਾਓ"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"ਕੀ <xliff:g id="USB_DEVICE">%2$s</xliff:g> ਤੱਕ <xliff:g id="APPLICATION">%1$s</xliff:g> ਨੂੰ ਪਹੁੰਚ ਕਰਨ ਦੇਣੀ ਹੈ?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"ਕੀ <xliff:g id="APPLICATION">%1$s</xliff:g> ਨੂੰ <xliff:g id="USB_DEVICE">%2$s</xliff:g> ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੇਣੀ ਹੈ?\nਇਸ ਐਪ ਨੂੰ ਰਿਕਾਰਡ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਦਿੱਤੀ ਗਈ ਪਰ ਇਹ USB ਡੀਵਾਈਸ ਰਾਹੀਂ ਆਡੀਓ ਕੈਪਚਰ ਕਰ ਸਕਦੀ ਹੈ।"</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"ਕੀ <xliff:g id="APPLICATION">%1$s</xliff:g> ਨੂੰ <xliff:g id="USB_DEVICE">%2$s</xliff:g> ਤੱਕ ਪਹੁੰਚ ਕਰਨ ਦੇਣੀ ਹੈ?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"ਕੀ <xliff:g id="USB_DEVICE">%2$s</xliff:g> ਨੂੰ ਵਰਤਣ ਲਈ <xliff:g id="APPLICATION">%1$s</xliff:g> ਖੋਲ੍ਹਣੀ ਹੈ?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"ਇਸ ਐਪ ਨੂੰ ਰਿਕਾਰਡ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਦਿੱਤੀ ਗਈ ਪਰ ਇਹ USB ਡੀਵਾਈਸ ਰਾਹੀਂ ਆਡੀਓ ਕੈਪਚਰ ਕਰ ਸਕਦੀ ਹੈ। ਸ਼ਾਇਦ ਇਸ ਡੀਵਾਈਸ ਨਾਲ <xliff:g id="APPLICATION">%1$s</xliff:g> ਦੀ ਵਰਤੋਂ ਕਰਨ \'ਤੇ ਕਾਲਾਂ, ਸੂਚਨਾਵਾਂ ਅਤੇ ਅਲਾਰਮਾਂ ਦੀ ਅਵਾਜ਼ ਸੁਣਾਈ ਨਾ ਦੇਵੇ।"</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"ਸ਼ਾਇਦ ਇਸ ਡੀਵਾਈਸ ਨਾਲ <xliff:g id="APPLICATION">%1$s</xliff:g> ਦੀ ਵਰਤੋਂ ਕਰਨ \'ਤੇ ਕਾਲਾਂ, ਸੂਚਨਾਵਾਂ ਅਤੇ ਅਲਾਰਮਾਂ ਦੀ ਅਵਾਜ਼ ਸੁਣਾਈ ਨਾ ਦੇਵੇ।"</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"ਕੀ <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> ਤੱਕ <xliff:g id="APPLICATION">%1$s</xliff:g> ਨੂੰ ਪਹੁੰਚ ਕਰਨ ਦੇਣੀ ਹੈ?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"ਕੀ <xliff:g id="USB_DEVICE">%2$s</xliff:g> ਨੂੰ ਵਰਤਣ ਲਈ <xliff:g id="APPLICATION">%1$s</xliff:g> ਖੋਲ੍ਹਣੀ ਹੈ?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ਨੂੰ ਸੰਭਾਲਣ ਲਈ <xliff:g id="APPLICATION">%1$s</xliff:g> ਖੋਲ੍ਹੋ?\nਇਸ ਐਪ ਨੂੰ ਰਿਕਾਰਡ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਨਹੀਂ ਦਿੱਤੀ ਗਈ ਪਰ ਇਹ USB ਡੀਵਾਈਸ ਰਾਹੀਂ ਆਡੀਓ ਕੈਪਚਰ ਕਰ ਸਕਦੀ ਹੈ।"</string> diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml index cb1786b1955a..45b63cdf8c90 100644 --- a/packages/SystemUI/res/values-pl/strings.xml +++ b/packages/SystemUI/res/values-pl/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Autoobracanie ekranu"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"Zezwolić aplikacji <xliff:g id="APPLICATION">%1$s</xliff:g> na dostęp do: <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Zezwolić aplikacji <xliff:g id="APPLICATION">%1$s</xliff:g> na dostęp do urządzenia <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nTa aplikacja nie ma uprawnień do nagrywania, ale może rejestrować dźwięk za pomocą tego urządzenia USB."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"<xliff:g id="APPLICATION">%1$s</xliff:g> ma mieć dostęp do: <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"Otworzyć <xliff:g id="APPLICATION">%1$s</xliff:g> dla urządzenia <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"Ta aplikacja nie ma uprawnień do nagrywania, ale może rejestrować dźwięk za pomocą tego urządzenia USB. Używanie aplikacji <xliff:g id="APPLICATION">%1$s</xliff:g> na tym urządzeniu może zakłócać słyszenie połączeń, powiadomień i alertów."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"Używanie aplikacji <xliff:g id="APPLICATION">%1$s</xliff:g> na tym urządzeniu może zakłócać słyszenie połączeń, powiadomień i alertów."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"Zezwolić aplikacji <xliff:g id="APPLICATION">%1$s</xliff:g> na dostęp do: <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"Otworzyć aplikację <xliff:g id="APPLICATION">%1$s</xliff:g> do obsługi urządzenia <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"Zezwolić aplikacji <xliff:g id="APPLICATION">%1$s</xliff:g> na obsługę urządzenia <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nTa aplikacja nie ma uprawnień do nagrywania, ale może rejestrować dźwięk za pomocą tego urządzenia USB."</string> diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml index a09afa3b8410..c6cb44e60931 100644 --- a/packages/SystemUI/res/values-pt-rBR/strings.xml +++ b/packages/SystemUI/res/values-pt-rBR/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Giro automático da tela"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"Permitir que o app <xliff:g id="APPLICATION">%1$s</xliff:g> acesse <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Permitir que <xliff:g id="APPLICATION">%1$s</xliff:g> acesse <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nEsse app não tem permissão de gravação, mas pode capturar áudio pelo dispositivo USB."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"Permitir que o app <xliff:g id="APPLICATION">%1$s</xliff:g> acesse este dispositivo: <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"Abrir <xliff:g id="APPLICATION">%1$s</xliff:g> para controlar <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"Esse app não tem permissão de gravação, mas pode capturar áudio pelo dispositivo USB. O uso do app <xliff:g id="APPLICATION">%1$s</xliff:g> com esse dispositivo pode impedir que você ouça chamadas, notificações e alarmes."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"O uso do app <xliff:g id="APPLICATION">%1$s</xliff:g> com esse dispositivo pode impedir que você ouça chamadas, notificações e alarmes."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"Permitir que o app <xliff:g id="APPLICATION">%1$s</xliff:g> acesse <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"Abrir o app <xliff:g id="APPLICATION">%1$s</xliff:g> para lidar com o <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"Abrir o app <xliff:g id="APPLICATION">%1$s</xliff:g> para usar o <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nEsse app não tem permissão de gravação, mas pode capturar áudio pelo dispositivo USB."</string> diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml index 1beae35c9033..ed9febecaf94 100644 --- a/packages/SystemUI/res/values-pt-rPT/strings.xml +++ b/packages/SystemUI/res/values-pt-rPT/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Rodar ecrã automaticamente"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"Permitir que a app <xliff:g id="APPLICATION">%1$s</xliff:g> aceda ao dispositivo <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Permitir que <xliff:g id="APPLICATION">%1$s</xliff:g> aceda a <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nEsta app não recebeu autorização de gravação, mas pode capturar áudio através deste dispositivo USB."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"Permitir que a app <xliff:g id="APPLICATION">%1$s</xliff:g> aceda a <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"Abrir a app <xliff:g id="APPLICATION">%1$s</xliff:g> para controlar <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"Esta app não recebeu autorização de gravação, mas pode capturar áudio através deste dispositivo USB. A utilização da app <xliff:g id="APPLICATION">%1$s</xliff:g> neste dispositivo pode impedir a audição de chamadas, notificações e alarmes."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"A utilização da app <xliff:g id="APPLICATION">%1$s</xliff:g> neste dispositivo pode impedir a audição de chamadas, notificações e alarmes."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"Permitir que a app <xliff:g id="APPLICATION">%1$s</xliff:g> aceda ao acessório <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"Pretende abrir a app <xliff:g id="APPLICATION">%1$s</xliff:g> para controlar o acessório <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"Pretende abrir a app <xliff:g id="APPLICATION">%1$s</xliff:g> para controlar o acessório <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nEsta app não recebeu autorização de gravação, mas pode capturar áudio através deste dispositivo USB."</string> diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml index a09afa3b8410..c6cb44e60931 100644 --- a/packages/SystemUI/res/values-pt/strings.xml +++ b/packages/SystemUI/res/values-pt/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Giro automático da tela"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"Permitir que o app <xliff:g id="APPLICATION">%1$s</xliff:g> acesse <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Permitir que <xliff:g id="APPLICATION">%1$s</xliff:g> acesse <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nEsse app não tem permissão de gravação, mas pode capturar áudio pelo dispositivo USB."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"Permitir que o app <xliff:g id="APPLICATION">%1$s</xliff:g> acesse este dispositivo: <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"Abrir <xliff:g id="APPLICATION">%1$s</xliff:g> para controlar <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"Esse app não tem permissão de gravação, mas pode capturar áudio pelo dispositivo USB. O uso do app <xliff:g id="APPLICATION">%1$s</xliff:g> com esse dispositivo pode impedir que você ouça chamadas, notificações e alarmes."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"O uso do app <xliff:g id="APPLICATION">%1$s</xliff:g> com esse dispositivo pode impedir que você ouça chamadas, notificações e alarmes."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"Permitir que o app <xliff:g id="APPLICATION">%1$s</xliff:g> acesse <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"Abrir o app <xliff:g id="APPLICATION">%1$s</xliff:g> para lidar com o <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"Abrir o app <xliff:g id="APPLICATION">%1$s</xliff:g> para usar o <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nEsse app não tem permissão de gravação, mas pode capturar áudio pelo dispositivo USB."</string> diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml index 2b5a511c9faa..cd03b08f6fed 100644 --- a/packages/SystemUI/res/values-ro/strings.xml +++ b/packages/SystemUI/res/values-ro/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Rotire automată a ecranului"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"Permiteți <xliff:g id="APPLICATION">%1$s</xliff:g> să acceseze <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Permiteți accesul aplicației <xliff:g id="APPLICATION">%1$s</xliff:g> la <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nPermisiunea de înregistrare nu a fost acordată aplicației, dar aceasta poate să înregistreze conținut audio prin intermediul acestui dispozitiv USB."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"Permiteți ca <xliff:g id="APPLICATION">%1$s</xliff:g> să acceseze <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"Deschideți <xliff:g id="APPLICATION">%1$s</xliff:g> ca să gestioneze <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"Permisiunea de înregistrare nu a fost acordată aplicației, dar aceasta poate să înregistreze conținut audio prin intermediul acestui dispozitiv USB. Dacă folosiți <xliff:g id="APPLICATION">%1$s</xliff:g> cu acest dispozitiv, acest lucru vă poate împiedica să auziți apeluri, notificări și alarme."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"Dacă folosiți <xliff:g id="APPLICATION">%1$s</xliff:g> cu acest dispozitiv, acest lucru vă poate împiedica să auziți apeluri, notificări și alarme."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"Permiteți <xliff:g id="APPLICATION">%1$s</xliff:g> să acceseze <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"Deschideți <xliff:g id="APPLICATION">%1$s</xliff:g> ca să gestioneze <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"Deschideți <xliff:g id="APPLICATION">%1$s</xliff:g> pentru a gestiona <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nPermisiunea de înregistrare nu a fost acordată aplicației, dar aceasta poate să înregistreze conținut audio prin intermediul acestui dispozitiv USB."</string> diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml index 0da6787728f9..cdfcb1a741db 100644 --- a/packages/SystemUI/res/values-ru/strings.xml +++ b/packages/SystemUI/res/values-ru/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Автоповорот экрана"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"Предоставить приложению \"<xliff:g id="APPLICATION">%1$s</xliff:g>\" доступ к устройству \"<xliff:g id="USB_DEVICE">%2$s</xliff:g>\"?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Предоставить приложению \"<xliff:g id="APPLICATION">%1$s</xliff:g>\" доступ к устройству \"<xliff:g id="USB_DEVICE">%2$s</xliff:g>\"?\nПриложению не разрешено вести запись, однако с помощью этого USB-устройства оно может записывать звук."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"Разрешить приложению \"<xliff:g id="APPLICATION">%1$s</xliff:g>\" доступ к устройству \"<xliff:g id="USB_DEVICE">%2$s</xliff:g>\"?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"Открыть приложение \"<xliff:g id="APPLICATION">%1$s</xliff:g>\" для управления устройством \"<xliff:g id="USB_DEVICE">%2$s</xliff:g>\"?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"Приложению не разрешено вести запись, однако оно может записывать аудио с помощью этого USB-устройства. Во время использования приложения \"<xliff:g id="APPLICATION">%1$s</xliff:g>\" с этим устройством вы можете не услышать звуков уведомлений, звонков и будильников."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"Во время использования приложения \"<xliff:g id="APPLICATION">%1$s</xliff:g>\" с этим устройством вы можете не услышать звуков уведомлений, звонков и будильников."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"Предоставить приложению \"<xliff:g id="APPLICATION">%1$s</xliff:g>\" доступ к устройству \"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>\"?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"Открыть приложение \"<xliff:g id="APPLICATION">%1$s</xliff:g>\" для управления устройством \"<xliff:g id="USB_DEVICE">%2$s</xliff:g>\"?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"Открыть приложение \"<xliff:g id="APPLICATION">%1$s</xliff:g>\" для использования устройства \"<xliff:g id="USB_DEVICE">%2$s</xliff:g>\"?\nПриложению не разрешено вести запись, однако с помощью этого USB-устройства оно может записывать звук."</string> diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml index 211a254a76c4..be1448b6ff78 100644 --- a/packages/SystemUI/res/values-si/strings.xml +++ b/packages/SystemUI/res/values-si/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"ස්වයංක්රීයව-භ්රමණය වන තිරය"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"<xliff:g id="APPLICATION">%1$s</xliff:g> හට <xliff:g id="USB_DEVICE">%2$s</xliff:g> වෙත පිවිසීමට ඉඩ දෙන්නද?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"<xliff:g id="APPLICATION">%1$s</xliff:g> වෙත ප්රවේශ වීමට <xliff:g id="USB_DEVICE">%2$s</xliff:g> හට ඉඩ දෙන්නද?\n මෙම යෙදුමට පටිගත කිරීම් අවසරයක් ලබා දී නොමැති නමුත් මෙම USB උපාංගය හරහා ශ්රව්ය ග්රහණය කර ගත හැකිය."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"<xliff:g id="APPLICATION">%1$s</xliff:g> හට <xliff:g id="USB_DEVICE">%2$s</xliff:g> වෙත පිවිසීමට ඉඩ දෙන්නද?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> හැසිරවීමට <xliff:g id="APPLICATION">%1$s</xliff:g> විවෘත කරන්නද?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"මෙම යෙදුමට පටිගත කිරීම් අවසරයක් ලබා දී නොමැති නමුත් මෙම USB උපාංගය හරහා ශ්රව්ය ග්රහණය කර ගත හැකිය. මෙම උපාංගය සමග <xliff:g id="APPLICATION">%1$s</xliff:g> භාවිත කිරීම ඇමතුම්, දැනුම්දීම් සහ එලාම ඇසීම වැළැක්විය හැකිය."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"මෙම උපාංගය සමග <xliff:g id="APPLICATION">%1$s</xliff:g> භාවිත කිරීම ඇමතුම්, දැනුම්දීම් සහ එලාම ඇසීම වැළැක්විය හැකිය."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"<xliff:g id="APPLICATION">%1$s</xliff:g> හට <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> වෙත පිවිසීමට ඉඩ දෙන්නද?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> හැසිරවීමට <xliff:g id="APPLICATION">%1$s</xliff:g> විවෘත කරන්නද?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"<xliff:g id="APPLICATION">%1$s</xliff:g> <xliff:g id="USB_DEVICE">%2$s</xliff:g> හැසිරවීමට විවෘත කරන්නද?\n මෙම යෙදුමට පටිගත කිරීම් අවසරයක් ලබා දී නොමැති නමුත් මෙම USB උපාංගය හරහා ශ්රව්ය ග්රහණය කර ගත හැකිය."</string> diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml index 4f5b916b0998..50fcb811e547 100644 --- a/packages/SystemUI/res/values-sk/strings.xml +++ b/packages/SystemUI/res/values-sk/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Automatické otočenie obrazovky"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"Povoliť aplikácii <xliff:g id="APPLICATION">%1$s</xliff:g> prístup k zariadeniu <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Povoliť aplikácii <xliff:g id="APPLICATION">%1$s</xliff:g> pristupovať k zariadeniu <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nTejto aplikácii nebolo udelené povolenie na nahrávanie, môže však snímať zvuk cez toto zariadenie USB."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"Povoliť apl. <xliff:g id="APPLICATION">%1$s</xliff:g> prístup k zar. <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"Otvoriť aplikáciu <xliff:g id="APPLICATION">%1$s</xliff:g> na spravovanie zariadenia <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"Tejto aplikácii nebolo udelené povolenie na nahrávanie, ale môže nahrávať zvuk cez toto zariadenie USB. Ak budete s týmto zariadením používať aplikáciu <xliff:g id="APPLICATION">%1$s</xliff:g>, nemusíte počuť hovory, upozornenia ani budíky."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"Ak budete s týmto zariadením používať aplikáciu <xliff:g id="APPLICATION">%1$s</xliff:g>, nemusíte počuť hovory, upozornenia ani budíky."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"Povoliť aplikácii <xliff:g id="APPLICATION">%1$s</xliff:g> prístup k zariadeniu <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"Otvoriť aplikáciu <xliff:g id="APPLICATION">%1$s</xliff:g> na použitie zariadenia <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"Chcete otvoriť aplikáciu <xliff:g id="APPLICATION">%1$s</xliff:g> na správu zariadenia <xliff:g id="USB_DEVICE">%2$s</xliff:g> ?\nTejto aplikácii nebolo udelené povolenie na nahrávanie, ale môže nasnímať zvuk cez toto zariadenie USB."</string> diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml index 3efc6ad7cb0b..b3b7eccebbc1 100644 --- a/packages/SystemUI/res/values-sl/strings.xml +++ b/packages/SystemUI/res/values-sl/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Samodejno zasukaj zaslon"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"Ali aplikaciji <xliff:g id="APPLICATION">%1$s</xliff:g> dovolite dostop do dodatka USB <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Ali aplikaciji <xliff:g id="APPLICATION">%1$s</xliff:g> dovolite dostop do naprave <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nTa aplikacija sicer nima dovoljenja za snemanje, vendar bi lahko zajemala zvok prek te naprave USB."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"Dovolite aplikaciji <xliff:g id="APPLICATION">%1$s</xliff:g> dostop do naprave <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"Želite odpreti <xliff:g id="APPLICATION">%1$s</xliff:g> za upravljanje naprave <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"Ta aplikacija sicer nima dovoljenja za snemanje, vendar bi lahko zajemala zvok prek te naprave USB. Uporaba aplikacije <xliff:g id="APPLICATION">%1$s</xliff:g> s to napravo lahko povzroči, da boste preslišali klice, obvestila in alarme."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"Uporaba aplikacije <xliff:g id="APPLICATION">%1$s</xliff:g> s to napravo lahko povzroči, da boste preslišali klice, obvestila in alarme."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"Ali aplikaciji <xliff:g id="APPLICATION">%1$s</xliff:g> dovolite dostop do dodatka USB <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"Želite odpreti <xliff:g id="APPLICATION">%1$s</xliff:g> za upravljanje naprave <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"Želite odpreti aplikacijo <xliff:g id="APPLICATION">%1$s</xliff:g> za upravljanje naprave <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nTa aplikacija sicer nima dovoljenja za snemanje, vendar bi lahko zajemala zvok prek te naprave USB."</string> diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml index 9b77e3954341..a571c76d8cac 100644 --- a/packages/SystemUI/res/values-sq/strings.xml +++ b/packages/SystemUI/res/values-sq/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Rrotullimi automatik i ekranit"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"Të lejohet <xliff:g id="APPLICATION">%1$s</xliff:g> të ketë qasje te <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Dëshiron të lejosh që <xliff:g id="APPLICATION">%1$s</xliff:g> të ketë qasje te <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nKëtij aplikacioni nuk i është dhënë leje për regjistrim, por mund të regjistrojë audio përmes kësaj pajisjeje USB."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"Të lejohet \"<xliff:g id="APPLICATION">%1$s</xliff:g>\" të qaset te <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"Të hapet <xliff:g id="APPLICATION">%1$s</xliff:g> për të përdorur <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"Këtij aplikacioni nuk i është dhënë leje për regjistrim, por mund të regjistrojë audio përmes kësaj pajisjeje USB. Përdorimi i <xliff:g id="APPLICATION">%1$s</xliff:g> me këtë pajisje mund të ndalojë dëgjimin e telefonatave, njoftimeve dhe alarmeve."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"Përdorimi i <xliff:g id="APPLICATION">%1$s</xliff:g> me këtë pajisje mund të ndalojë dëgjimin e telefonatave, njoftimeve dhe alarmeve."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"Të lejohet <xliff:g id="APPLICATION">%1$s</xliff:g> të ketë qasje te <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"Të hapet <xliff:g id="APPLICATION">%1$s</xliff:g> për të përdorur <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"Dëshiron të hapësh <xliff:g id="APPLICATION">%1$s</xliff:g> që të përpunojë <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nKëtij aplikacioni nuk i është dhënë leje për regjistrim, por mund të regjistrojë audio përmes kësaj pajisjeje USB."</string> diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml index ef445c97c294..9712d1835e2d 100644 --- a/packages/SystemUI/res/values-sr/strings.xml +++ b/packages/SystemUI/res/values-sr/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Аутоматско ротирање екрана"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"Дозвољавате да <xliff:g id="APPLICATION">%1$s</xliff:g> приступа уређају <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Желите ли да дозволите да <xliff:g id="APPLICATION">%1$s</xliff:g> приступа уређају <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nОва апликација нема дозволу за снимање, али би могла да снима звук помоћу овог USB уређаја."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"Дозвољавате да <xliff:g id="APPLICATION">%1$s</xliff:g> приступа уређају <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"Желите ли да отворите апликацију <xliff:g id="APPLICATION">%1$s</xliff:g> да бисте користили уређај <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"Ова апликација нема дозволу за снимање, али би могла да снима звук помоћу овог USB уређаја. Ако користите апликацију <xliff:g id="APPLICATION">%1$s</xliff:g> са овим уређајем, можда нећете чути позиве, обавештења и аларме."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"Ако користите апликацију <xliff:g id="APPLICATION">%1$s</xliff:g> са овим уређајем, можда нећете чути позиве, обавештења и аларме."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"Дозвољавате да <xliff:g id="APPLICATION">%1$s</xliff:g> приступа уређају <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"Желите да отворите <xliff:g id="APPLICATION">%1$s</xliff:g> да бисте користили <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"Желите ли да отворите апликацију <xliff:g id="APPLICATION">%1$s</xliff:g> ради руковања уређајем <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nОва апликација нема дозволу за снимање, али би могла да снима звук помоћу овог USB уређаја."</string> diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml index eaf5c0056151..71814b2cf0e8 100644 --- a/packages/SystemUI/res/values-sv/strings.xml +++ b/packages/SystemUI/res/values-sv/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Rotera skärmen automatiskt"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"Vill du ge <xliff:g id="APPLICATION">%1$s</xliff:g> åtkomst till <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Vill du ge <xliff:g id="APPLICATION">%1$s</xliff:g> åtkomst till <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nAppen har inte fått inspelningsbehörighet men kan spela in ljud via denna USB-enhet."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"Vill du ge <xliff:g id="APPLICATION">%1$s</xliff:g> åtkomst till <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"Vill du öppna <xliff:g id="APPLICATION">%1$s</xliff:g> och hantera <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"Appen har inte fått inspelningsbehörighet men kan spela in ljud via denna USB-enhet. Om du använder <xliff:g id="APPLICATION">%1$s</xliff:g> med enheten kanske du inte hör samtal, aviseringar eller alarm."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"Om du använder <xliff:g id="APPLICATION">%1$s</xliff:g> med enheten kanske du inte hör samtal, aviseringar eller alarm."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"Vill du ge <xliff:g id="APPLICATION">%1$s</xliff:g> åtkomst till <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"Vill du öppna <xliff:g id="APPLICATION">%1$s</xliff:g> och hantera <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"Vill du öppna <xliff:g id="APPLICATION">%1$s</xliff:g> för att hantera <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nAppen har inte fått inspelningsbehörighet men kan spela in ljud via denna USB-enhet."</string> diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml index 79727839e8da..d30497d498c3 100644 --- a/packages/SystemUI/res/values-sw/strings.xml +++ b/packages/SystemUI/res/values-sw/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Skrini ijizungushe kiotomatiki"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"Ungependa kuruhusu <xliff:g id="APPLICATION">%1$s</xliff:g> ifikie <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Ungependa kuruhusu <xliff:g id="APPLICATION">%1$s</xliff:g> ifikie <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nProgramu hii haijapewa ruhusa ya kurekodi lakini inaweza kurekodi sauti kupitia kifaa hiki cha USB."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"Ungependa kuruhusu <xliff:g id="APPLICATION">%1$s</xliff:g> ifikie <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"Ungependa kufungua <xliff:g id="APPLICATION">%1$s</xliff:g> ishughulikie <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"Programu hii haijapewa ruhusa ya kurekodi lakini inaweza kurekodi sauti kupitia kifaa hiki cha USB. Ukitumia <xliff:g id="APPLICATION">%1$s</xliff:g> kwenye kifaa hiki huenda usisikie simu, arifa na kengele."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"Ukitumia <xliff:g id="APPLICATION">%1$s</xliff:g> kwenye kifaa hiki huenda usisikie simu, arifa na kengele."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"Ungependa kuruhusu <xliff:g id="APPLICATION">%1$s</xliff:g> ifikie <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"Ungependa kufungua <xliff:g id="APPLICATION">%1$s</xliff:g> ili itumie <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"Ungependa kufungua <xliff:g id="APPLICATION">%1$s</xliff:g> ishughulikie <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nProgramu hii haijapewa ruhusa ya kurekodi lakini inaweza kurekodi sauti kupitia kifaa hiki cha USB."</string> diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml index f937cd30af45..43abfdb4372f 100644 --- a/packages/SystemUI/res/values-ta/strings.xml +++ b/packages/SystemUI/res/values-ta/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"திரையைத் தானாகச் சுழற்று"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>ஐ அணுக, <xliff:g id="APPLICATION">%1$s</xliff:g> ஆப்ஸை அனுமதிக்கவா?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>ஐப் பயன்படுத்த <xliff:g id="APPLICATION">%1$s</xliff:g>ஐ அனுமதிக்கவா?\nஇந்த ஆப்ஸிற்கு ரெக்கார்டு செய்வதற்கான அனுமதி வழங்கப்படவில்லை, எனினும் இந்த USB சாதனம் மூலம் ஆடியோவைப் பதிவுசெய்யும்."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> சாதனத்தை அணுக <xliff:g id="APPLICATION">%1$s</xliff:g> ஆப்ஸை அனுமதிக்கவா?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> சாதனத்தைக் கையாள <xliff:g id="APPLICATION">%1$s</xliff:g> ஆப்ஸைத் திறக்கவா?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"இந்த ஆப்ஸில் ரெக்கார்டு செய்வதற்கு அனுமதி இல்லை, எனினும் இந்த USB சாதனம் மூலம் ஆடியோவைப் பதிவுசெய்யலாம். இந்தச் சாதனத்தில் <xliff:g id="APPLICATION">%1$s</xliff:g> ஆப்ஸைப் பயன்படுத்தினால் அழைப்புகள், அறிவிப்புகள், அலாரங்கள் ஆகியவற்றின் ஒலி கேட்பது தடுக்கப்படக்கூடும்."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"இந்தச் சாதனத்தில் <xliff:g id="APPLICATION">%1$s</xliff:g> ஆப்ஸைப் பயன்படுத்தினால் அழைப்புகள், அறிவிப்புகள், அலாரங்கள் ஆகியவற்றின் ஒலி கேட்பது தடுக்கப்படக்கூடும்."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>ஐ அணுக, <xliff:g id="APPLICATION">%1$s</xliff:g> ஆப்ஸை அனுமதிக்கவா?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>ஐக் கையாள, <xliff:g id="APPLICATION">%1$s</xliff:g> பயன்பாட்டைத் திறக்கவா?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>ஐக் கையாள <xliff:g id="APPLICATION">%1$s</xliff:g>ஐத் திறக்கவா?\nஇந்த ஆப்ஸிற்கு ரெக்கார்டு செய்வதற்கான அனுமதி வழங்கப்படவில்லை, எனினும் இந்த USB சாதனம் மூலம் ஆடியோவைப் பதிவுசெய்ய முடியும்."</string> diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml index 35be54c5fa3c..af8b2acb073f 100644 --- a/packages/SystemUI/res/values-te/strings.xml +++ b/packages/SystemUI/res/values-te/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"స్క్రీన్ ఆటో-రొటేట్"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>ని యాక్సెస్ చేయడానికి <xliff:g id="APPLICATION">%1$s</xliff:g>ని అనుమతించాలా?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>యాక్సెస్ చేయడానికి <xliff:g id="APPLICATION">%1$s</xliff:g>ను అనుమతించాలా?\nఈ యాప్నకు రికార్డ్ చేసే అనుమతి మంజూరు చేయబడలేదు, కానీ ఈ USB పరికరం ద్వారా ఆడియోను క్యాప్చర్ చేయగలదు."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>ను యాక్సెస్ చేయడానికి <xliff:g id="APPLICATION">%1$s</xliff:g>ను అనుమతించాలా?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>ను హ్యాండిల్ చేయడానికి <xliff:g id="APPLICATION">%1$s</xliff:g>ను తెరవాలా?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"ఈ యాప్నకు రికార్డ్ చేసే అనుమతి మంజూరు కాలేదు, అయినా ఈ USB పరికరం ద్వారా ఆడియోను క్యాప్చర్ చేయగలదు. ఈ పరికరంలో <xliff:g id="APPLICATION">%1$s</xliff:g>ను ఉపయోగించడం వలన కాల్స్, నోటిఫికేషన్లు, అలారాలను వినబడనీయకుండా నివారించవచ్చు."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"ఈ పరికరంలో <xliff:g id="APPLICATION">%1$s</xliff:g>ను ఉపయోగించడం వలన కాల్స్, నోటిఫికేషన్లు, అలారంలను వినబడనీయకుండా నివారించవచ్చు."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>ని యాక్సెస్ చేయడానికి <xliff:g id="APPLICATION">%1$s</xliff:g>ని అనుమతించాలా?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>ని హ్యాండిల్ చేయడానికి <xliff:g id="APPLICATION">%1$s</xliff:g>ని తెరవాలా?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"<xliff:g id="USB_DEVICE">%2$s</xliff:g>ని హ్యాండిల్ చేయడానికి <xliff:g id="APPLICATION">%1$s</xliff:g>ను తెరవాలా?\nఈ యాప్కు రికార్డ్ చేసే అనుమతి మంజూరు కాలేదు, అయినా ఈ USB పరికరం ద్వారా ఆడియోను క్యాప్చర్ చేయగలదు."</string> diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml index 8dcb3a50d409..e182736a3e46 100644 --- a/packages/SystemUI/res/values-th/strings.xml +++ b/packages/SystemUI/res/values-th/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"หมุนหน้าจออัตโนมัติ"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"อนุญาตให้ <xliff:g id="APPLICATION">%1$s</xliff:g> เข้าถึง <xliff:g id="USB_DEVICE">%2$s</xliff:g> ไหม"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"อนุญาตให้ <xliff:g id="APPLICATION">%1$s</xliff:g> เข้าถึง <xliff:g id="USB_DEVICE">%2$s</xliff:g> ไหม\nแอปนี้ไม่ได้รับอนุญาตให้อัดเสียงแต่อาจเก็บเสียงผ่านอุปกรณ์ USB นี้ได้"</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"อนุญาตให้ <xliff:g id="APPLICATION">%1$s</xliff:g> เข้าถึง <xliff:g id="USB_DEVICE">%2$s</xliff:g> ใช่ไหม"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"เปิด <xliff:g id="APPLICATION">%1$s</xliff:g> เพื่อจัดการ <xliff:g id="USB_DEVICE">%2$s</xliff:g> ไหม"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"แอปนี้ไม่ได้รับอนุญาตให้อัดเสียงแต่อาจเก็บเสียงเสียงผ่านอุปกรณ์ USB นี้ได้ การใช้ <xliff:g id="APPLICATION">%1$s</xliff:g> กับอุปกรณ์นี้อาจทำให้คุณไม่ได้ยินเสียงสายเรียกเข้า การแจ้งเตือน และการปลุก"</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"การใช้ <xliff:g id="APPLICATION">%1$s</xliff:g> กับอุปกรณ์นี้อาจทำให้คุณไม่ได้ยินเสียงสายเรียกเข้า การแจ้งเตือน และการปลุก"</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"อนุญาตให้ <xliff:g id="APPLICATION">%1$s</xliff:g> เข้าถึง <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> ไหม"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"เปิด <xliff:g id="APPLICATION">%1$s</xliff:g> เพื่อจัดการ <xliff:g id="USB_DEVICE">%2$s</xliff:g> ไหม"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"เปิด <xliff:g id="APPLICATION">%1$s</xliff:g> เพื่อจัดการ <xliff:g id="USB_DEVICE">%2$s</xliff:g> ไหม\nแอปนี้ไม่ได้รับอนุญาตให้อัดเสียงแต่อาจเก็บเสียงผ่านอุปกรณ์ USB นี้ได้"</string> diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml index cb84913335f3..458b069c1229 100644 --- a/packages/SystemUI/res/values-tl/strings.xml +++ b/packages/SystemUI/res/values-tl/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"I-auto rotate ang screen"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"Payagan ang <xliff:g id="APPLICATION">%1$s</xliff:g> na ma-access ang <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Payagan ang <xliff:g id="APPLICATION">%1$s</xliff:g> na i-access ang <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nHindi nabigyan ng pahintulot ang app na ito para mag-record pero nakakapag-capture ito ng audio sa pamamagitan ng USB device na ito."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"Payagan ang <xliff:g id="APPLICATION">%1$s</xliff:g> na i-access ang <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"Buksan ang <xliff:g id="APPLICATION">%1$s</xliff:g> para pangasiwaan ang <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"Hindi nabigyan ng pahintulot ang app na ito na mag-record pero puwede itong mag-capture ng audio sa pamamagitan ng USB device na ito. Kapag ginamit ang <xliff:g id="APPLICATION">%1$s</xliff:g> sa device na ito, posibleng hindi marinig ang mga tawag, notification, at alarm."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"Kapag ginamit ang <xliff:g id="APPLICATION">%1$s</xliff:g> sa device na ito, posibleng hindi marinig ang mga tawag, notification, at alarm."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"Payagan ang <xliff:g id="APPLICATION">%1$s</xliff:g> na ma-access ang <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"Buksan ang <xliff:g id="APPLICATION">%1$s</xliff:g> upang pamahalaan ang <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"Buksan ang <xliff:g id="APPLICATION">%1$s</xliff:g> para pangasiwaan ang <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nHindi nabigyan ng pahintulot ang app na ito para mag-record pero nakakapag-capture ito ng audio sa pamamagitan ng USB device na ito."</string> diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml index d522a19f2bf7..b895b0bea0f8 100644 --- a/packages/SystemUI/res/values-tr/strings.xml +++ b/packages/SystemUI/res/values-tr/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Ekranı otomatik döndür"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"<xliff:g id="APPLICATION">%1$s</xliff:g> uygulamasının <xliff:g id="USB_DEVICE">%2$s</xliff:g> cihazına erişmesine izin verilsin mi?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"<xliff:g id="APPLICATION">%1$s</xliff:g> uygulamasının <xliff:g id="USB_DEVICE">%2$s</xliff:g> cihazına erişmesine izin verilsin mi?\nBu uygulamaya kayıt izni verilmemiş ancak bu USB cihazı aracılığıyla sesleri yakalayabilir."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"<xliff:g id="APPLICATION">%1$s</xliff:g> uygulamasının <xliff:g id="USB_DEVICE">%2$s</xliff:g> cihazına erişmesine izin verilsin mi?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> aksesuarını işlemek için <xliff:g id="APPLICATION">%1$s</xliff:g> uygulaması açılsın mı?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"Bu uygulamaya ses kaydetme izni verilmedi ancak bu USB cihazı üzerinden sesleri yakalayabilir. <xliff:g id="APPLICATION">%1$s</xliff:g> uygulamasının bu cihazla kullanılması aramaları, bildirimleri ve alarmları duymayı engelleyebilir."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"<xliff:g id="APPLICATION">%1$s</xliff:g> uygulamasının bu cihazla kullanılması aramaları, bildirimleri ve alarmları duymayı engelleyebilir."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"<xliff:g id="APPLICATION">%1$s</xliff:g> uygulamasının <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> aksesuarına erişmesine izin verilsin mi?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> cihazını işlemek için <xliff:g id="APPLICATION">%1$s</xliff:g> uygulaması açılsın mı?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> için <xliff:g id="APPLICATION">%1$s</xliff:g> uygulaması açılsın mı?\n Bu uygulamaya kayıt izni verilmemiş, ancak bu USB cihazı aracılığıyla sesleri yakalabilir."</string> diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml index 1b9f362febf5..cbc1def4e63e 100644 --- a/packages/SystemUI/res/values-uk/strings.xml +++ b/packages/SystemUI/res/values-uk/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Автообертання екрана"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"Надати додатку <xliff:g id="APPLICATION">%1$s</xliff:g> доступ до такого аксесуара: <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Надати додатку <xliff:g id="APPLICATION">%1$s</xliff:g> доступ до <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nЦей додаток не має дозволу на записування звуку, але може фіксувати його через цей USB-пристрій."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"Надати додатку <xliff:g id="APPLICATION">%1$s</xliff:g> доступ до пристрою (<xliff:g id="USB_DEVICE">%2$s</xliff:g>)?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"Відкрити <xliff:g id="APPLICATION">%1$s</xliff:g>, щоб керувати пристроєм <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"Додаток не має дозволу на запис, але він може фіксувати звук через цей USB-пристрій. Якщо додаток <xliff:g id="APPLICATION">%1$s</xliff:g> використовується з цим пристроєм, звук дзвінків, сповіщень і будильників може не відтворюватися."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"Якщо додаток <xliff:g id="APPLICATION">%1$s</xliff:g> використовується з цим пристроєм, звук дзвінків, сповіщень і будильників може не відтворюватися."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"Надати додатку <xliff:g id="APPLICATION">%1$s</xliff:g> доступ до такого аксесуара: <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"Відкрити додаток <xliff:g id="APPLICATION">%1$s</xliff:g>, щоб використовувати такий аксесуар: <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"Працювати з пристроєм \"<xliff:g id="USB_DEVICE">%2$s</xliff:g>\" у додатку <xliff:g id="APPLICATION">%1$s</xliff:g>?\nУ цього додатка немає дозволів на запис, але він може передавати звук у USB-пристрій."</string> diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml index 0b4c561862e4..6e333aaf2b80 100644 --- a/packages/SystemUI/res/values-ur/strings.xml +++ b/packages/SystemUI/res/values-ur/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"سکرین کو خودکار طور پر گھمائیں"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"<xliff:g id="APPLICATION">%1$s</xliff:g> کو <xliff:g id="USB_DEVICE">%2$s</xliff:g> تک رسائی حاصل کرنے کی اجازت دیں؟"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"<xliff:g id="APPLICATION">%1$s</xliff:g> کو <xliff:g id="USB_DEVICE">%2$s</xliff:g> تک رسائی دیں؟\nاس ایپ کو ریکارڈ کی اجازت عطا نہیں کی گئی ہے مگر اس USB آلہ سے کیپچر کر سکتے ہیں۔"</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"<xliff:g id="APPLICATION">%1$s</xliff:g> کو <xliff:g id="USB_DEVICE">%2$s</xliff:g> تک رسائی حاصل کرنے کی اجازت دیں؟"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ہینڈل کرنے کیلئے <xliff:g id="APPLICATION">%1$s</xliff:g> کھولیں؟"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"اس ایپ کو ریکارڈ کرنے کی اجازت عطا نہیں کی گئی ہے مگر اس USB آلہ کے ذریعے آڈیو کیپچر کر سکتی ہے۔ اس آلہ پر <xliff:g id="APPLICATION">%1$s</xliff:g> کا استعمال آپ کو کالز، اطلاعات اور الارمز سننے سے روک سکتا ہے۔"</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"اس آلہ پر <xliff:g id="APPLICATION">%1$s</xliff:g> کا استعمال آپ کو کالز، اطلاعات اور الارمز سننے سے روک سکتا ہے۔"</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"<xliff:g id="APPLICATION">%1$s</xliff:g> کو <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> تک رسائی حاصل کرنے کی اجازت دیں؟"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> ہینڈل کرنے کیلئے <xliff:g id="APPLICATION">%1$s</xliff:g> کھولیں؟"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> کو ہینڈل کرنے کے ليے <xliff:g id="APPLICATION">%1$s</xliff:g> کھولیں؟ \nاس ایپ کو ریکارڈ کی اجازت عطا نہیں کی گئی ہے مگر اس USB آلہ سے کیپچر کر سکتے ہیں۔"</string> diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml index 4e4f79c9f568..c0b280c64fda 100644 --- a/packages/SystemUI/res/values-uz/strings.xml +++ b/packages/SystemUI/res/values-uz/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Ekranning avtomatik burilishi"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"<xliff:g id="APPLICATION">%1$s</xliff:g> ilovasiga <xliff:g id="USB_DEVICE">%2$s</xliff:g> qurilmasidan foydalanishga ruxsat berilsinmi?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"<xliff:g id="APPLICATION">%1$s</xliff:g> ilovasiga <xliff:g id="USB_DEVICE">%2$s</xliff:g> qurilmasidan foydalanish uchun ruxsat berilsinmi?\nBu ilovaga yozib olish ruxsati berilmagan, lekin shu USB orqali ovozlarni yozib olishi mumkin."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"<xliff:g id="APPLICATION">%1$s</xliff:g> uchun <xliff:g id="USB_DEVICE">%2$s</xliff:g> ishlatish ruxsati berilsinmi?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> bilan ishlash uchun <xliff:g id="APPLICATION">%1$s</xliff:g> ochilsinmi?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"Bu ilovaga yozib olish ruxsati berilmagan, lekin shu USB orqali ovozlarni yozib olishi mumkin. Bu qurilma <xliff:g id="APPLICATION">%1$s</xliff:g> orqali boshqarilsa, chaqiruv, bildirishnoma va signallar eshitilmay qolishi mumkin."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"Bu qurilma <xliff:g id="APPLICATION">%1$s</xliff:g> orqali boshqarilsa, chaqiruv, bildirishnoma va signallar eshitilmay qolishi mumkin."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"<xliff:g id="APPLICATION">%1$s</xliff:g> ilovasiga <xliff:g id="USB_ACCESSORY">%2$s</xliff:g> qurilmasidan foydalanishga ruxsat berilsinmi?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"<xliff:g id="USB_DEVICE">%2$s</xliff:g> bilan ishlash uchun <xliff:g id="APPLICATION">%1$s</xliff:g> ochilsinmi?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"<xliff:g id="APPLICATION">%1$s</xliff:g> ilovasiga <xliff:g id="USB_DEVICE">%2$s</xliff:g> qurilmasidan foydalanish uchun ruxsat berilsinmi?\nBu ilovaga yozib olish ruxsati berilmagan, lekin shu USB orqali ovozlarni yozib olishi mumkin."</string> diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml index 9e3bfb925107..5f1bfdbfbfe7 100644 --- a/packages/SystemUI/res/values-vi/strings.xml +++ b/packages/SystemUI/res/values-vi/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Tự động xoay màn hình"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"Cho phép <xliff:g id="APPLICATION">%1$s</xliff:g> truy cập <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Cho phép <xliff:g id="APPLICATION">%1$s</xliff:g> truy cập vào <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nỨng dụng này chưa được cấp quyền ghi âm nhưng vẫn có thể ghi âm thông qua thiết bị USB này."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"Cho phép <xliff:g id="APPLICATION">%1$s</xliff:g> truy cập vào <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"Mở <xliff:g id="APPLICATION">%1$s</xliff:g> để điều khiển <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"Ứng dụng này chưa được cấp quyền ghi âm nhưng vẫn có thể ghi âm thông qua thiết bị USB này. Việc sử dụng <xliff:g id="APPLICATION">%1$s</xliff:g> cùng với thiết bị này có thể giúp bạn tránh phải nghe cuộc gọi, thông báo và chuông báo."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"Việc sử dụng <xliff:g id="APPLICATION">%1$s</xliff:g> cùng với thiết bị này có thể giúp bạn tránh phải nghe cuộc gọi, thông báo và chuông báo."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"Cho phép <xliff:g id="APPLICATION">%1$s</xliff:g> truy cập <xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"Mở <xliff:g id="APPLICATION">%1$s</xliff:g> để điều khiển <xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"Mở <xliff:g id="APPLICATION">%1$s</xliff:g> để điều khiển <xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nDù chưa được cấp quyền ghi âm, nhưng ứng dụng có thể ghi âm thông qua thiết bị USB này."</string> diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml index 6133ef2e4d1f..5640e93044ad 100644 --- a/packages/SystemUI/res/values-zh-rCN/strings.xml +++ b/packages/SystemUI/res/values-zh-rCN/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"自动旋转屏幕"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"要允许<xliff:g id="APPLICATION">%1$s</xliff:g>访问<xliff:g id="USB_DEVICE">%2$s</xliff:g>吗?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"是否允许<xliff:g id="APPLICATION">%1$s</xliff:g>访问<xliff:g id="USB_DEVICE">%2$s</xliff:g>?\n此应用未获得录音权限,但能通过此 USB 设备录制音频。"</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"允许“<xliff:g id="APPLICATION">%1$s</xliff:g>”访问<xliff:g id="USB_DEVICE">%2$s</xliff:g>吗?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"打开“<xliff:g id="APPLICATION">%1$s</xliff:g>”来处理<xliff:g id="USB_DEVICE">%2$s</xliff:g>吗?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"此应用未获得录音权限,但能通过此 USB 设备录制音频。如果在此设备上使用“<xliff:g id="APPLICATION">%1$s</xliff:g>”,您可能无法听见来电、通知和闹钟的音效。"</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"如果在此设备上使用“<xliff:g id="APPLICATION">%1$s</xliff:g>”,您可能无法听见来电、通知和闹钟的音效。"</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"要允许<xliff:g id="APPLICATION">%1$s</xliff:g>访问<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>吗?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"要打开<xliff:g id="APPLICATION">%1$s</xliff:g>来处理<xliff:g id="USB_DEVICE">%2$s</xliff:g>吗?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"要打开<xliff:g id="APPLICATION">%1$s</xliff:g>来使用<xliff:g id="USB_DEVICE">%2$s</xliff:g>吗?\n此应用未获得录音权限,但能通过此 USB 设备录制音频。"</string> diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml index b2dd9ccdeae8..eb9527e8533c 100644 --- a/packages/SystemUI/res/values-zh-rHK/strings.xml +++ b/packages/SystemUI/res/values-zh-rHK/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"自動旋轉螢幕"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"要允許「<xliff:g id="APPLICATION">%1$s</xliff:g>」存取「<xliff:g id="USB_DEVICE">%2$s</xliff:g>」嗎?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"要允許「<xliff:g id="APPLICATION">%1$s</xliff:g>」存取「<xliff:g id="USB_DEVICE">%2$s</xliff:g>」嗎?\n此應用程式尚未獲授予錄音權限,但可透過此 USB 裝置記錄音訊。"</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"要允許「<xliff:g id="APPLICATION">%1$s</xliff:g>」存取「<xliff:g id="USB_DEVICE">%2$s</xliff:g>」嗎?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"要開啟「<xliff:g id="APPLICATION">%1$s</xliff:g>」處理「<xliff:g id="USB_DEVICE">%2$s</xliff:g>」嗎?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"此應用程式尚未獲授予錄音權限,但可透過此 USB 裝置記錄音訊。如將「<xliff:g id="APPLICATION">%1$s</xliff:g>」與此裝置配合使用,您可能無法聽見來電、通知及鬧鐘的音效。"</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"如將「<xliff:g id="APPLICATION">%1$s</xliff:g>」與此裝置配合使用,您可能無法聽見來電、通知及鬧鐘的音效。"</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"要允許「<xliff:g id="APPLICATION">%1$s</xliff:g>」存取「<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>」嗎?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"要開啟「<xliff:g id="APPLICATION">%1$s</xliff:g>」處理「<xliff:g id="USB_DEVICE">%2$s</xliff:g>」嗎?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"要開啟「<xliff:g id="APPLICATION">%1$s</xliff:g>」應用程式來控制「<xliff:g id="USB_DEVICE">%2$s</xliff:g>」嗎?\n此應用程式尚未獲授予錄音權限,但可透過此 USB 裝置記錄音訊。"</string> diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml index 7fa08f46760a..75f78d1f6e5c 100644 --- a/packages/SystemUI/res/values-zh-rTW/strings.xml +++ b/packages/SystemUI/res/values-zh-rTW/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"自動旋轉螢幕"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"要允許「<xliff:g id="APPLICATION">%1$s</xliff:g>」存取「<xliff:g id="USB_DEVICE">%2$s</xliff:g>」嗎?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"要允許「<xliff:g id="APPLICATION">%1$s</xliff:g>」存取「<xliff:g id="USB_DEVICE">%2$s</xliff:g>」嗎?\n這個應用程式未取得錄製權限,但可以透過這部 USB 裝置錄製音訊。"</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"要允許「<xliff:g id="APPLICATION">%1$s</xliff:g>」存取「<xliff:g id="USB_DEVICE">%2$s</xliff:g>」嗎?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"要開啟「<xliff:g id="APPLICATION">%1$s</xliff:g>」以控制「<xliff:g id="USB_DEVICE">%2$s</xliff:g>」嗎?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"這個應用程式未取得錄音的權限,但可以透過這部 USB 裝置錄製音訊。如果將「<xliff:g id="APPLICATION">%1$s</xliff:g>」應用程式與這部裝置搭配使用,可能不會聽見來電、通知和鬧鐘的音效。"</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"如果將「<xliff:g id="APPLICATION">%1$s</xliff:g>」應用程式與這部裝置搭配使用,可能不會聽見來電、通知和鬧鐘的音效。"</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"要允許「<xliff:g id="APPLICATION">%1$s</xliff:g>」存取「<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>」嗎?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"要開啟「<xliff:g id="APPLICATION">%1$s</xliff:g>」處理「<xliff:g id="USB_DEVICE">%2$s</xliff:g>」嗎?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"要開啟「<xliff:g id="APPLICATION">%1$s</xliff:g>」來使用「<xliff:g id="USB_DEVICE">%2$s</xliff:g>」嗎?\n這個應用程式未取得錄製內容的權限,但可以透過這部 USB 裝置錄製音訊。"</string> diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml index 59c58daac4ba..eac3f58b012f 100644 --- a/packages/SystemUI/res/values-zu/strings.xml +++ b/packages/SystemUI/res/values-zu/strings.xml @@ -31,6 +31,10 @@ <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"Ukuzulazula kweskrini okuzenzakalelayo"</string> <string name="usb_device_permission_prompt" msgid="4414719028369181772">"Vumela i-<xliff:g id="APPLICATION">%1$s</xliff:g> ukufinyelela i-<xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_permission_prompt_warn" msgid="2309129784984063656">"Vumela i-<xliff:g id="APPLICATION">%1$s</xliff:g> ukuthi ifinyelele ku-<xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nLolu hlelo lokusebenza alunikeziwe imvume yokurekhoda kodwa lingathatha umsindo ngale divayisi ye-USB."</string> + <string name="usb_audio_device_permission_prompt_title" msgid="4221351137250093451">"Vumela i-<xliff:g id="APPLICATION">%1$s</xliff:g> ukuze ufinyelele i-<xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_confirm_prompt_title" msgid="8828406516732985696">"Vula i-<xliff:g id="APPLICATION">%1$s</xliff:g> ukuze ibambe i-<xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> + <string name="usb_audio_device_prompt_warn" msgid="2504972133361130335">"Le app ayinikezwanga imvume yokurekhoda kodwa ingathwebula umsindo ngale divayisi ye-USB. Ukusebenzisa i-<xliff:g id="APPLICATION">%1$s</xliff:g> ngale divayisi kungase kuvimbele ukuzwa amakholi, izaziso nama-alamu."</string> + <string name="usb_audio_device_prompt" msgid="7944987408206252949">"Ukusebenzisa i-<xliff:g id="APPLICATION">%1$s</xliff:g> ngale divayisi kungase kuvimbele ukuzwa amakholi, izaziso nama-alamu."</string> <string name="usb_accessory_permission_prompt" msgid="717963550388312123">"Vumela i-<xliff:g id="APPLICATION">%1$s</xliff:g> ukufinyelela i-<xliff:g id="USB_ACCESSORY">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt" msgid="4091711472439910809">"Vula i-<xliff:g id="APPLICATION">%1$s</xliff:g> ukuze uphath i-<xliff:g id="USB_DEVICE">%2$s</xliff:g>?"</string> <string name="usb_device_confirm_prompt_warn" msgid="990208659736311769">"Vula i-<xliff:g id="APPLICATION">%1$s</xliff:g> ukuze uphathe i-<xliff:g id="USB_DEVICE">%2$s</xliff:g>?\nLolu hlelo lokusebenza alinikeziwe imvume yokurekhoda kodwa lingathatha umsindo ngale divayisi ye-USB."</string> diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index e1afd3fe6a30..4a7d7089d712 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -78,6 +78,18 @@ <!-- Checkbox label for USB device dialogs with warning text for USB device dialogs. [CHAR LIMIT=200]--> <string name="usb_device_permission_prompt_warn">Allow <xliff:g id="application" example= "Usb Mega Player">%1$s</xliff:g> to access <xliff:g id="usb_device" example="USB Headphones">%2$s</xliff:g>?\nThis app has not been granted record permission but could capture audio through this USB device.</string> + <!-- USB audio device permission dialog title. [CHAR LIMIT=200]--> + <string name="usb_audio_device_permission_prompt_title">Allow <xliff:g id="application" example= "Usb Mega Player">%1$s</xliff:g> to access <xliff:g id="usb_device" example="USB Headphones">%2$s</xliff:g>?</string> + + <!-- USB audio device confirm dialog title. [CHAR LIMIT=200]--> + <string name="usb_audio_device_confirm_prompt_title">Open <xliff:g id="application" example= "Usb Mega Player">%1$s</xliff:g> to handle <xliff:g id="usb_device" example="USB Headphones">%2$s</xliff:g>?</string> + + <!-- Checkbox label for USB audio device dialogs with warning text for USB audio device dialogs. [CHAR LIMIT=NONE]--> + <string name="usb_audio_device_prompt_warn">This app has not been granted record permission but could capture audio through this USB device. Using <xliff:g id="application" example= "Usb Mega Player">%1$s</xliff:g> with this device might prevent hearing calls, notifications and alarms.</string> + + <!-- Prompt for the USB audio device permission dialog [CHAR LIMIT=NONE] --> + <string name="usb_audio_device_prompt">Using <xliff:g id="application" example= "Usb Mega Player">%1$s</xliff:g> with this device might prevent hearing calls, notifications and alarms.</string> + <!-- Prompt for the USB accessory permission dialog [CHAR LIMIT=80] --> <string name="usb_accessory_permission_prompt">Allow <xliff:g id="application" example= "Usb Mega Player">%1$s</xliff:g> to access <xliff:g id="usb_accessory" example="USB Dock">%2$s</xliff:g>?</string> diff --git a/packages/SystemUI/shared/src/com/android/systemui/unfold/util/ScopedUnfoldTransitionProgressProvider.java b/packages/SystemUI/shared/src/com/android/systemui/unfold/util/ScopedUnfoldTransitionProgressProvider.java index 543232da303e..9e59acb6b5b9 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/unfold/util/ScopedUnfoldTransitionProgressProvider.java +++ b/packages/SystemUI/shared/src/com/android/systemui/unfold/util/ScopedUnfoldTransitionProgressProvider.java @@ -111,6 +111,7 @@ public final class ScopedUnfoldTransitionProgressProvider implements @Override public void destroy() { mSource.removeCallback(this); + mSource.destroy(); } @Override diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardMessageArea.java b/packages/SystemUI/src/com/android/keyguard/KeyguardMessageArea.java index 099dd5d82a10..87e853cf64d7 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardMessageArea.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardMessageArea.java @@ -18,6 +18,7 @@ package com.android.keyguard; import android.content.Context; import android.content.res.ColorStateList; +import android.content.res.Configuration; import android.content.res.TypedArray; import android.graphics.Color; import android.os.Handler; @@ -30,6 +31,8 @@ import android.view.View; import android.view.ViewGroup; import android.widget.TextView; +import androidx.annotation.Nullable; + import com.android.internal.policy.SystemBarUtils; import com.android.settingslib.Utils; import com.android.systemui.R; @@ -57,8 +60,14 @@ public class KeyguardMessageArea extends TextView implements SecurityMessageDisp private ColorStateList mNextMessageColorState = ColorStateList.valueOf(DEFAULT_COLOR); private boolean mBouncerVisible; private boolean mAltBouncerShowing; + /** + * Container that wraps the KeyguardMessageArea - may be null if current view hierarchy doesn't + * contain {@link R.id.keyguard_message_area_container}. + */ + @Nullable private ViewGroup mContainer; - private int mTopMargin; + private int mContainerTopMargin; + private int mLastOrientation = -1; public KeyguardMessageArea(Context context, AttributeSet attrs) { super(context, attrs); @@ -74,16 +83,31 @@ public class KeyguardMessageArea extends TextView implements SecurityMessageDisp mContainer = getRootView().findViewById(R.id.keyguard_message_area_container); } - void onConfigChanged() { - final int newTopMargin = SystemBarUtils.getStatusBarHeight(getContext()); - if (mTopMargin == newTopMargin) { + void onConfigChanged(Configuration newConfig) { + if (mContainer == null) { return; } - mTopMargin = newTopMargin; - ViewGroup.MarginLayoutParams lp = + final int newTopMargin = SystemBarUtils.getStatusBarHeight(getContext()); + if (mContainerTopMargin != newTopMargin) { + mContainerTopMargin = newTopMargin; + ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) mContainer.getLayoutParams(); - lp.topMargin = mTopMargin; - mContainer.setLayoutParams(lp); + lp.topMargin = mContainerTopMargin; + mContainer.setLayoutParams(lp); + } + + if (mLastOrientation != newConfig.orientation) { + mLastOrientation = newConfig.orientation; + int messageAreaTopMargin = 0; + if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) { + messageAreaTopMargin = mContext.getResources().getDimensionPixelSize( + R.dimen.keyguard_lock_padding); + } + + ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) getLayoutParams(); + lp.topMargin = messageAreaTopMargin; + setLayoutParams(lp); + } } @Override diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardMessageAreaController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardMessageAreaController.java index 05318bb0df78..659aadd69614 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardMessageAreaController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardMessageAreaController.java @@ -50,7 +50,7 @@ public class KeyguardMessageAreaController extends ViewController<KeyguardMessag private ConfigurationListener mConfigurationListener = new ConfigurationListener() { @Override public void onConfigChanged(Configuration newConfig) { - mView.onConfigChanged(); + mView.onConfigChanged(newConfig); } @Override diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java index 1efda7edee2f..5b4f7a21f8d0 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java @@ -21,10 +21,13 @@ import static com.android.systemui.statusbar.policy.DevicePostureController.DEVI import android.content.Context; import android.content.res.Configuration; +import android.content.res.Resources; import android.util.AttributeSet; import android.view.View; +import android.view.ViewGroup; import android.view.animation.AnimationUtils; +import androidx.constraintlayout.helper.widget.Flow; import androidx.constraintlayout.widget.ConstraintLayout; import androidx.constraintlayout.widget.ConstraintSet; @@ -87,48 +90,45 @@ public class KeyguardPINView extends KeyguardPinBasedInputView { } private void updateMargins() { + Resources res = mContext.getResources(); + // Re-apply everything to the keys... - int bottomMargin = mContext.getResources().getDimensionPixelSize( - R.dimen.num_pad_entry_row_margin_bottom); - int rightMargin = mContext.getResources().getDimensionPixelSize( - R.dimen.num_pad_key_margin_end); - String ratio = mContext.getResources().getString(R.string.num_pad_key_ratio); - - // mView contains all Views that make up the PIN pad; row0 = the entry test field, then - // rows 1-4 contain the buttons. Iterate over all views that make up the buttons in the pad, - // and re-set all the margins. - for (int row = 1; row < 5; row++) { - for (int column = 0; column < 3; column++) { - View key = mViews[row][column]; - - ConstraintLayout.LayoutParams lp = - (ConstraintLayout.LayoutParams) key.getLayoutParams(); - - lp.dimensionRatio = ratio; - - // Don't set any margins on the last row of buttons. - if (row != 4) { - lp.bottomMargin = bottomMargin; - } - - // Don't set margins on the rightmost buttons. - if (column != 2) { - lp.rightMargin = rightMargin; - } - - key.setLayoutParams(lp); - } - } + int verticalMargin = res.getDimensionPixelSize(R.dimen.num_pad_entry_row_margin_bottom); + int horizontalMargin = res.getDimensionPixelSize(R.dimen.num_pad_key_margin_end); + String ratio = res.getString(R.string.num_pad_key_ratio); + + Flow flow = (Flow) mContainer.findViewById(R.id.flow1); + flow.setHorizontalGap(horizontalMargin); + flow.setVerticalGap(verticalMargin); // Update the guideline based on the device posture... - float halfOpenPercentage = - mContext.getResources().getFloat(R.dimen.half_opened_bouncer_height_ratio); + float halfOpenPercentage = res.getFloat(R.dimen.half_opened_bouncer_height_ratio); ConstraintSet cs = new ConstraintSet(); cs.clone(mContainer); cs.setGuidelinePercent(R.id.pin_pad_top_guideline, mLastDevicePosture == DEVICE_POSTURE_HALF_OPENED ? halfOpenPercentage : 0.0f); cs.applyTo(mContainer); + + // Password entry area + int passwordHeight = res.getDimensionPixelSize(R.dimen.keyguard_password_height); + View pinEntry = findViewById(getPasswordTextViewId()); + ViewGroup.LayoutParams lp = pinEntry.getLayoutParams(); + lp.height = passwordHeight; + pinEntry.setLayoutParams(lp); + + // Below row0 + View row0 = findViewById(R.id.row0); + row0.setPadding(0, 0, 0, verticalMargin); + + // Above the emergency contact area + int marginTop = res.getDimensionPixelSize(R.dimen.keyguard_eca_top_margin); + View eca = findViewById(R.id.keyguard_selector_fade_container); + if (eca != null) { + ViewGroup.MarginLayoutParams mLp = (ViewGroup.MarginLayoutParams) eca.getLayoutParams(); + mLp.topMargin = marginTop; + eca.setLayoutParams(mLp); + } } @Override diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index 2789e27178cc..42f0fccd61b0 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -1186,6 +1186,21 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab return fingerprintAllowed || faceAllowed; } + /** + * Returns whether the user is unlocked with a biometric that is currently bypassing + * the lock screen. + */ + public boolean getUserUnlockedWithBiometricAndIsBypassing(int userId) { + BiometricAuthenticated fingerprint = mUserFingerprintAuthenticated.get(userId); + BiometricAuthenticated face = mUserFaceAuthenticated.get(userId); + // fingerprint always bypasses + boolean fingerprintAllowed = fingerprint != null && fingerprint.mAuthenticated + && isUnlockingWithBiometricAllowed(fingerprint.mIsStrongBiometric); + boolean faceAllowed = face != null && face.mAuthenticated + && isUnlockingWithBiometricAllowed(face.mIsStrongBiometric); + return fingerprintAllowed || faceAllowed && mKeyguardBypassController.canBypass(); + } + public boolean getUserTrustIsManaged(int userId) { return mUserTrustIsManaged.get(userId) && !isTrustDisabled(userId); } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDisplayListener.kt b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDisplayListener.kt index b7404dfeb1cc..dfbe348c6ede 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDisplayListener.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/BiometricDisplayListener.kt @@ -37,7 +37,7 @@ class BiometricDisplayListener( private val onChanged: () -> Unit ) : DisplayManager.DisplayListener { - private var lastRotation = context.display?.rotation ?: Surface.ROTATION_0 + private var lastRotation = Surface.ROTATION_0 override fun onDisplayAdded(displayId: Int) {} override fun onDisplayRemoved(displayId: Int) {} @@ -63,6 +63,7 @@ class BiometricDisplayListener( /** Listen for changes. */ fun enable() { + lastRotation = context.display?.rotation ?: Surface.ROTATION_0 displayManager.registerDisplayListener(this, handler) } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java index 7c9a6342f8f2..22293692c774 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java @@ -480,8 +480,33 @@ public class UdfpsController implements DozeReceiver { final long sinceLastLog = mSystemClock.elapsedRealtime() - mTouchLogTime; if (!isIlluminationRequested && !mGoodCaptureReceived && !exceedsVelocityThreshold) { - onFingerDown((int) event.getRawX(), (int) event.getRawY(), minor, - major); + final int rawX = (int) event.getRawX(); + final int rawY = (int) event.getRawY(); + // Default coordinates assume portrait mode. + int x = rawX; + int y = rawY; + + // Gets the size based on the current rotation of the display. + Point p = new Point(); + mContext.getDisplay().getRealSize(p); + + // Transform x, y to portrait mode if the device is in landscape mode. + switch (mContext.getDisplay().getRotation()) { + case Surface.ROTATION_90: + x = p.y - rawY; + y = rawX; + break; + + case Surface.ROTATION_270: + x = rawY; + y = p.x - rawX; + break; + + default: + // Do nothing to stay in portrait mode. + } + + onFingerDown(x, y, minor, major); Log.v(TAG, "onTouch | finger down: " + touchInfo); mTouchLogTime = mSystemClock.elapsedRealtime(); mPowerManager.userActivity(mSystemClock.uptimeMillis(), diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollDrawable.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollDrawable.java index ac38b13cc4dd..9137dca6cc71 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollDrawable.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollDrawable.java @@ -97,6 +97,8 @@ public class UdfpsEnrollDrawable extends UdfpsDrawable { @NonNull private final ValueAnimator.AnimatorUpdateListener mEdgeHintWidthUpdateListener; @NonNull private final Animator.AnimatorListener mEdgeHintPulseListener; + private boolean mShowingNewUdfpsEnroll = false; + UdfpsEnrollDrawable(@NonNull Context context) { super(context); @@ -211,6 +213,8 @@ public class UdfpsEnrollDrawable extends UdfpsDrawable { @Override public void onAnimationRepeat(Animator animation) {} }; + mShowingNewUdfpsEnroll = context.getResources().getBoolean( + com.android.internal.R.bool.config_udfpsSupportsNewUi); } void setEnrollHelper(@NonNull UdfpsEnrollHelper helper) { @@ -292,6 +296,10 @@ public class UdfpsEnrollDrawable extends UdfpsDrawable { } mShouldShowTipHint = shouldShow; + if (mShowingNewUdfpsEnroll) { + return; + } + if (mTipHintWidthAnimator != null && mTipHintWidthAnimator.isRunning()) { mTipHintWidthAnimator.cancel(); } @@ -306,6 +314,7 @@ public class UdfpsEnrollDrawable extends UdfpsDrawable { } else { mTipHintWidthAnimator.start(); } + } private void updateEdgeHintVisibility() { @@ -315,6 +324,10 @@ public class UdfpsEnrollDrawable extends UdfpsDrawable { } mShouldShowEdgeHint = shouldShow; + if (mShowingNewUdfpsEnroll) { + return; + } + if (mEdgeHintWidthAnimator != null && mEdgeHintWidthAnimator.isRunning()) { mEdgeHintWidthAnimator.cancel(); } @@ -333,6 +346,10 @@ public class UdfpsEnrollDrawable extends UdfpsDrawable { } private void startTipHintPulseAnimation() { + if (mShowingNewUdfpsEnroll) { + return; + } + mHandler.removeCallbacksAndMessages(null); if (mTipHintAnimatorSet != null && mTipHintAnimatorSet.isRunning()) { mTipHintAnimatorSet.cancel(); @@ -353,6 +370,10 @@ public class UdfpsEnrollDrawable extends UdfpsDrawable { } private void startEdgeHintPulseAnimation() { + if (mShowingNewUdfpsEnroll) { + return; + } + mHandler.removeCallbacksAndMessages(null); if (mEdgeHintAnimatorSet != null && mEdgeHintAnimatorSet.isRunning()) { mEdgeHintAnimatorSet.cancel(); @@ -409,6 +430,10 @@ public class UdfpsEnrollDrawable extends UdfpsDrawable { mSensorOutlinePaint.setAlpha(mAlpha); } + if (mShowingNewUdfpsEnroll) { + return; + } + // Draw the finger tip or edges hint. if (isTipHintVisible() || isEdgeHintVisible()) { canvas.save(); diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java index befb648152d4..789ad6223e79 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java @@ -118,9 +118,11 @@ public class DozeMachine { switch (this) { case UNINITIALIZED: case INITIALIZED: - case DOZE_REQUEST_PULSE: return parameters.shouldControlScreenOff() ? Display.STATE_ON : Display.STATE_OFF; + case DOZE_REQUEST_PULSE: + return parameters.getDisplayNeedsBlanking() ? Display.STATE_OFF + : Display.STATE_ON; case DOZE_AOD_PAUSED: case DOZE: return Display.STATE_OFF; diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java index 36319380ad50..52db1bd00c8e 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenState.java @@ -105,17 +105,7 @@ public class DozeScreenState implements DozeMachine.Part { updateUdfpsController(); if (mUdfpsController == null) { - mAuthController.addCallback(new AuthController.Callback() { - @Override - public void onAllAuthenticatorsRegistered() { - updateUdfpsController(); - } - - @Override - public void onEnrollmentsChanged() { - updateUdfpsController(); - } - }); + mAuthController.addCallback(mAuthControllerCallback); } } @@ -128,6 +118,11 @@ public class DozeScreenState implements DozeMachine.Part { } @Override + public void destroy() { + mAuthController.removeCallback(mAuthControllerCallback); + } + + @Override public void transitionTo(DozeMachine.State oldState, DozeMachine.State newState) { int screenState = newState.screenState(mParameters); mDozeHost.cancelGentleSleep(); @@ -222,4 +217,16 @@ public class DozeScreenState implements DozeMachine.Part { mWakeLock.setAcquired(false); } } + + private final AuthController.Callback mAuthControllerCallback = new AuthController.Callback() { + @Override + public void onAllAuthenticatorsRegistered() { + updateUdfpsController(); + } + + @Override + public void onEnrollmentsChanged() { + updateUdfpsController(); + } + }; } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt index fabe92d2532d..94d5ee2b923c 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt @@ -21,6 +21,7 @@ import android.animation.AnimatorListenerAdapter import android.animation.ValueAnimator import android.content.Context import android.graphics.Matrix +import android.util.Log import android.view.RemoteAnimationTarget import android.view.SyncRtSurfaceTransactionApplier import android.view.View @@ -38,6 +39,8 @@ import com.android.systemui.statusbar.policy.KeyguardStateController import dagger.Lazy import javax.inject.Inject +const val TAG = "KeyguardUnlock" + /** * Starting scale factor for the app/launcher surface behind the keyguard, when it's animating * in during keyguard exit. @@ -254,7 +257,12 @@ class KeyguardUnlockAnimationController @Inject constructor( } fun hideKeyguardViewAfterRemoteAnimation() { - keyguardViewController.hide(surfaceBehindRemoteAnimationStartTime, 350) + if (keyguardViewController.isShowing) { + keyguardViewController.hide(surfaceBehindRemoteAnimationStartTime, 350) + } else { + Log.e(TAG, "#hideKeyguardViewAfterRemoteAnimation called when keyguard view is not " + + "showing. Ignoring...") + } } /** diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index bff56b83c3af..9bfa37a72e91 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -112,6 +112,7 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.shared.system.QuickStepContract; import com.android.systemui.statusbar.CommandQueue; import com.android.systemui.statusbar.NotificationShadeDepthController; +import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.phone.BiometricUnlockController; import com.android.systemui.statusbar.phone.DozeParameters; @@ -209,7 +210,6 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable, private static final int KEYGUARD_DONE_PENDING_TIMEOUT = 13; private static final int NOTIFY_STARTED_WAKING_UP = 14; private static final int NOTIFY_SCREEN_TURNED_ON = 15; - private static final int NOTIFY_SCREEN_TURNED_OFF = 16; private static final int NOTIFY_STARTED_GOING_TO_SLEEP = 17; private static final int SYSTEM_READY = 18; private static final int CANCEL_KEYGUARD_EXIT_ANIM = 19; @@ -324,6 +324,7 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable, // the properties of the keyguard private final KeyguardUpdateMonitor mUpdateMonitor; + private final Lazy<NotificationShadeWindowController> mNotificationShadeWindowControllerLazy; /** * Last SIM state reported by the telephony system. @@ -439,7 +440,6 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable, private boolean mInGestureNavigationMode; private boolean mWakeAndUnlocking; - private IKeyguardDrawnCallback mDrawnCallback; private CharSequence mCustomMessage; /** @@ -846,7 +846,8 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable, KeyguardStateController keyguardStateController, Lazy<KeyguardUnlockAnimationController> keyguardUnlockAnimationControllerLazy, UnlockedScreenOffAnimationController unlockedScreenOffAnimationController, - Lazy<NotificationShadeDepthController> notificationShadeDepthController) { + Lazy<NotificationShadeDepthController> notificationShadeDepthController, + Lazy<NotificationShadeWindowController> notificationShadeWindowControllerLazy) { super(context); mFalsingCollector = falsingCollector; mLockPatternUtils = lockPatternUtils; @@ -862,6 +863,7 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable, mKeyguardDisplayManager = keyguardDisplayManager; dumpManager.registerDumpable(getClass().getName(), this); mDeviceConfig = deviceConfig; + mNotificationShadeWindowControllerLazy = notificationShadeWindowControllerLazy; mShowHomeOverLockscreen = mDeviceConfig.getBoolean( DeviceConfig.NAMESPACE_SYSTEMUI, NAV_BAR_HANDLE_SHOW_OVER_LOCKSCREEN, @@ -1260,7 +1262,6 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable, } public void onScreenTurnedOff() { - notifyScreenTurnedOff(); mUpdateMonitor.dispatchScreenTurnedOff(); } @@ -1484,9 +1485,7 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable, public void doKeyguardTimeout(Bundle options) { mHandler.removeMessages(KEYGUARD_TIMEOUT); Message msg = mHandler.obtainMessage(KEYGUARD_TIMEOUT, options); - // Treat these messages with priority - A call to timeout means the device should lock - // as soon as possible and not wait for other messages on the thread to process first. - mHandler.sendMessageAtFrontOfQueue(msg); + mHandler.sendMessage(msg); } /** @@ -1656,26 +1655,17 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable, mHandler.sendMessage(msg); } - private void notifyScreenTurnedOff() { - if (DEBUG) Log.d(TAG, "notifyScreenTurnedOff"); - Message msg = mHandler.obtainMessage(NOTIFY_SCREEN_TURNED_OFF); - mHandler.sendMessage(msg); - } - /** * Send message to keyguard telling it to show itself * @see #handleShow */ private void showLocked(Bundle options) { - Trace.beginSection("KeyguardViewMediator#showLocked acquiring mShowKeyguardWakeLock"); + Trace.beginSection("KeyguardViewMediator#showLocked aqcuiring mShowKeyguardWakeLock"); if (DEBUG) Log.d(TAG, "showLocked"); // ensure we stay awake until we are finished displaying the keyguard mShowKeyguardWakeLock.acquire(); Message msg = mHandler.obtainMessage(SHOW, options); - // Treat these messages with priority - This call can originate from #doKeyguardTimeout, - // meaning the device should lock as soon as possible and not wait for other messages on - // the thread to process first. - mHandler.sendMessageAtFrontOfQueue(msg); + mHandler.sendMessage(msg); Trace.endSection(); } @@ -1849,9 +1839,6 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable, handleNotifyScreenTurnedOn(); Trace.endSection(); break; - case NOTIFY_SCREEN_TURNED_OFF: - handleNotifyScreenTurnedOff(); - break; case NOTIFY_STARTED_WAKING_UP: Trace.beginSection( "KeyguardViewMediator#handleMessage NOTIFY_STARTED_WAKING_UP"); @@ -1876,7 +1863,6 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable, case KEYGUARD_TIMEOUT: synchronized (KeyguardViewMediator.this) { doKeyguardLocked((Bundle) msg.obj); - notifyDefaultDisplayCallbacks(mShowing); } break; case DISMISS: @@ -1887,10 +1873,13 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable, Trace.beginSection( "KeyguardViewMediator#handleMessage START_KEYGUARD_EXIT_ANIM"); StartKeyguardExitAnimParams params = (StartKeyguardExitAnimParams) msg.obj; - handleStartKeyguardExitAnimation(params.startTime, params.fadeoutDuration, - params.mApps, params.mWallpapers, params.mNonApps, - params.mFinishedCallback); - mFalsingCollector.onSuccessfulUnlock(); + mNotificationShadeWindowControllerLazy.get().batchApplyWindowLayoutParams( + () -> { + handleStartKeyguardExitAnimation(params.startTime, + params.fadeoutDuration, params.mApps, params.mWallpapers, + params.mNonApps, params.mFinishedCallback); + mFalsingCollector.onSuccessfulUnlock(); + }); Trace.endSection(); break; case CANCEL_KEYGUARD_EXIT_ANIM: @@ -2188,10 +2177,12 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable, mKeyguardGoingAwayRunnable.run(); } else { // TODO(bc-unlock): Fill parameters - handleStartKeyguardExitAnimation( - SystemClock.uptimeMillis() + mHideAnimation.getStartOffset(), - mHideAnimation.getDuration(), null /* apps */, null /* wallpapers */, - null /* nonApps */, null /* finishedCallback */); + mNotificationShadeWindowControllerLazy.get().batchApplyWindowLayoutParams(() -> { + handleStartKeyguardExitAnimation( + SystemClock.uptimeMillis() + mHideAnimation.getStartOffset(), + mHideAnimation.getDuration(), null /* apps */, null /* wallpapers */, + null /* nonApps */, null /* finishedCallback */); + }); } } Trace.endSection(); @@ -2228,16 +2219,6 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable, IRemoteAnimationRunner runner = mKeyguardExitAnimationRunner; mKeyguardExitAnimationRunner = null; - if (mWakeAndUnlocking && mDrawnCallback != null) { - - // Hack level over 9000: To speed up wake-and-unlock sequence, force it to report - // the next draw from here so we don't have to wait for window manager to signal - // this to our ViewRootImpl. - mKeyguardViewControllerLazy.get().getViewRootImpl().setReportNextDraw(); - notifyDrawn(mDrawnCallback); - mDrawnCallback = null; - } - LatencyTracker.getInstance(mContext) .onActionEnd(LatencyTracker.ACTION_LOCKSCREEN_UNLOCK); @@ -2593,11 +2574,7 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable, mKeyguardViewControllerLazy.get().onScreenTurningOn(); if (callback != null) { - if (mWakeAndUnlocking) { - mDrawnCallback = callback; - } else { - notifyDrawn(callback); - } + notifyDrawn(callback); } } Trace.endSection(); @@ -2612,13 +2589,6 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable, Trace.endSection(); } - private void handleNotifyScreenTurnedOff() { - synchronized (this) { - if (DEBUG) Log.d(TAG, "handleNotifyScreenTurnedOff"); - mDrawnCallback = null; - } - } - private void notifyDrawn(final IKeyguardDrawnCallback callback) { Trace.beginSection("KeyguardViewMediator#notifyDrawn"); if (mPendingDrawnTasks.decrementAndGet() == 0) { @@ -2787,7 +2757,6 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable, pw.print(" mPendingLock: "); pw.println(mPendingLock); pw.print(" mPendingDrawnTasks: "); pw.println(mPendingDrawnTasks.get()); pw.print(" mWakeAndUnlocking: "); pw.println(mWakeAndUnlocking); - pw.print(" mDrawnCallback: "); pw.println(mDrawnCallback); } /** @@ -2886,7 +2855,7 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable, for (int i = size - 1; i >= 0; i--) { IKeyguardStateCallback callback = mKeyguardStateCallbacks.get(i); try { - callback.onShowingStateChanged(showing, KeyguardUpdateMonitor.getCurrentUser()); + callback.onShowingStateChanged(showing); } catch (RemoteException e) { Slog.w(TAG, "Failed to call onShowingStateChanged", e); if (e instanceof DeadObjectException) { @@ -2920,7 +2889,7 @@ public class KeyguardViewMediator extends SystemUI implements Dumpable, mKeyguardStateCallbacks.add(callback); try { callback.onSimSecureStateChanged(mUpdateMonitor.isSimPinSecure()); - callback.onShowingStateChanged(mShowing, KeyguardUpdateMonitor.getCurrentUser()); + callback.onShowingStateChanged(mShowing); callback.onInputRestrictedStateChanged(mInputRestricted); callback.onTrustedChanged(mUpdateMonitor.getUserHasTrust( KeyguardUpdateMonitor.getCurrentUser())); diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java index cae9feeb62eb..88dcf6d35075 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java @@ -42,6 +42,7 @@ import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.navigationbar.NavigationModeController; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.NotificationShadeDepthController; +import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.phone.DozeParameters; import com.android.systemui.statusbar.phone.KeyguardLiftController; @@ -97,7 +98,8 @@ public class KeyguardModule { KeyguardStateController keyguardStateController, Lazy<KeyguardUnlockAnimationController> keyguardUnlockAnimationController, UnlockedScreenOffAnimationController unlockedScreenOffAnimationController, - Lazy<NotificationShadeDepthController> notificationShadeDepthController) { + Lazy<NotificationShadeDepthController> notificationShadeDepthController, + Lazy<NotificationShadeWindowController> notificationShadeWindowController) { return new KeyguardViewMediator( context, falsingCollector, @@ -120,7 +122,8 @@ public class KeyguardModule { keyguardStateController, keyguardUnlockAnimationController, unlockedScreenOffAnimationController, - notificationShadeDepthController + notificationShadeDepthController, + notificationShadeWindowController ); } diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt index b85f10726040..70f89e499ed5 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt @@ -209,17 +209,17 @@ class MediaCarouselController @Inject constructor( oldKey: String?, data: MediaData, immediately: Boolean, - receivedSmartspaceCardLatency: Int + receivedSmartspaceCardLatency: Int, + isSsReactivated: Boolean ) { - if (addOrUpdatePlayer(key, oldKey, data)) { + if (addOrUpdatePlayer(key, oldKey, data, isSsReactivated)) { // Log card received if a new resumable media card is added MediaPlayerData.getMediaPlayer(key)?.let { /* ktlint-disable max-line-length */ logSmartspaceCardReported(759, // SMARTSPACE_CARD_RECEIVED it.mInstanceId, it.mUid, - /* isRecommendationCard */ false, - intArrayOf( + surfaces = intArrayOf( SysUiStatsLog.SMART_SPACE_CARD_REPORTED__DISPLAY_SURFACE__SHADE, SysUiStatsLog.SMART_SPACE_CARD_REPORTED__DISPLAY_SURFACE__LOCKSCREEN), rank = MediaPlayerData.getMediaPlayerIndex(key)) @@ -242,8 +242,7 @@ class MediaCarouselController @Inject constructor( logSmartspaceCardReported(759, // SMARTSPACE_CARD_RECEIVED it.mInstanceId, it.mUid, - /* isRecommendationCard */ false, - intArrayOf( + surfaces = intArrayOf( SysUiStatsLog.SMART_SPACE_CARD_REPORTED__DISPLAY_SURFACE__SHADE, SysUiStatsLog.SMART_SPACE_CARD_REPORTED__DISPLAY_SURFACE__LOCKSCREEN), rank = index, @@ -277,12 +276,17 @@ class MediaCarouselController @Inject constructor( override fun onSmartspaceMediaDataLoaded( key: String, data: SmartspaceMediaData, - shouldPrioritize: Boolean, - isSsReactivated: Boolean + shouldPrioritize: Boolean ) { if (DEBUG) Log.d(TAG, "Loading Smartspace media update") + // Log the case where the hidden media carousel with the existed inactive resume + // media is shown by the Smartspace signal. if (data.isActive) { - if (isSsReactivated && shouldPrioritize) { + val hasActivatedExistedResumeMedia = + !mediaManager.hasActiveMedia() && + mediaManager.hasAnyMedia() && + shouldPrioritize + if (hasActivatedExistedResumeMedia) { // Log resume card received if resumable media card is reactivated and // recommendation card is valid and ranked first MediaPlayerData.players().forEachIndexed { index, it -> @@ -294,8 +298,7 @@ class MediaCarouselController @Inject constructor( logSmartspaceCardReported(759, // SMARTSPACE_CARD_RECEIVED it.mInstanceId, it.mUid, - /* isRecommendationCard */ false, - intArrayOf( + surfaces = intArrayOf( SysUiStatsLog.SMART_SPACE_CARD_REPORTED__DISPLAY_SURFACE__SHADE, SysUiStatsLog.SMART_SPACE_CARD_REPORTED__DISPLAY_SURFACE__LOCKSCREEN), rank = index, @@ -310,8 +313,7 @@ class MediaCarouselController @Inject constructor( logSmartspaceCardReported(759, // SMARTSPACE_CARD_RECEIVED it.mInstanceId, it.mUid, - /* isRecommendationCard */ true, - intArrayOf( + surfaces = intArrayOf( SysUiStatsLog.SMART_SPACE_CARD_REPORTED__DISPLAY_SURFACE__SHADE, SysUiStatsLog.SMART_SPACE_CARD_REPORTED__DISPLAY_SURFACE__LOCKSCREEN), rank = MediaPlayerData.getMediaPlayerIndex(key), @@ -408,7 +410,12 @@ class MediaCarouselController @Inject constructor( } // Returns true if new player is added - private fun addOrUpdatePlayer(key: String, oldKey: String?, data: MediaData): Boolean { + private fun addOrUpdatePlayer( + key: String, + oldKey: String?, + data: MediaData, + isSsReactivated: Boolean + ): Boolean { val dataCopy = data.copy(backgroundColor = bgColor) MediaPlayerData.moveIfExists(oldKey, key) val existingPlayer = MediaPlayerData.getMediaPlayer(key) @@ -424,12 +431,13 @@ class MediaCarouselController @Inject constructor( newPlayer.playerViewHolder?.player?.setLayoutParams(lp) newPlayer.bindPlayer(dataCopy, key) newPlayer.setListening(currentlyExpanded) - MediaPlayerData.addMediaPlayer(key, dataCopy, newPlayer, systemClock) + MediaPlayerData.addMediaPlayer(key, dataCopy, newPlayer, systemClock, isSsReactivated) updatePlayerToState(newPlayer, noAnimation = true) reorderAllPlayers(curVisibleMediaKey) } else { existingPlayer.bindPlayer(dataCopy, key) - MediaPlayerData.addMediaPlayer(key, dataCopy, existingPlayer, systemClock) + MediaPlayerData.addMediaPlayer(key, dataCopy, existingPlayer, systemClock, + isSsReactivated) if (visualStabilityManager.isReorderingAllowed || shouldScrollToActivePlayer) { reorderAllPlayers(curVisibleMediaKey) } else { @@ -523,8 +531,10 @@ class MediaCarouselController @Inject constructor( it.targetId, it, MediaPlayerData.shouldPrioritizeSs) } } else { + val isSsReactivated = MediaPlayerData.isSsReactivated(key) removePlayer(key, dismissMediaData = false, dismissRecommendation = false) - addOrUpdatePlayer(key = key, oldKey = null, data = data) + addOrUpdatePlayer( + key = key, oldKey = null, data = data, isSsReactivated = isSsReactivated) } } } @@ -682,7 +692,8 @@ class MediaCarouselController @Inject constructor( this.desiredHostState = it currentlyExpanded = it.expansion > 0 - val shouldCloseGuts = !currentlyExpanded && !mediaManager.hasActiveMedia() && + val shouldCloseGuts = !currentlyExpanded && + !mediaManager.hasActiveMediaOrRecommendation() && desiredHostState.showsOnlyActiveMedia for (mediaPlayer in MediaPlayerData.players()) { @@ -747,7 +758,6 @@ class MediaCarouselController @Inject constructor( val mediaControlPanel = MediaPlayerData.players().elementAt(visibleMediaIndex) val hasActiveMediaOrRecommendationCard = MediaPlayerData.hasActiveMediaOrRecommendationCard() - val isRecommendationCard = mediaControlPanel.recommendationViewHolder != null if (!hasActiveMediaOrRecommendationCard && !qsExpanded) { // Skip logging if on LS or QQS, and there is no active media card return @@ -755,7 +765,6 @@ class MediaCarouselController @Inject constructor( logSmartspaceCardReported(800, // SMARTSPACE_CARD_SEEN mediaControlPanel.mInstanceId, mediaControlPanel.mUid, - isRecommendationCard, intArrayOf(mediaControlPanel.surfaceForSmartspaceLogging)) mediaControlPanel.mIsImpressed = true } @@ -769,7 +778,6 @@ class MediaCarouselController @Inject constructor( * @param instanceId id to uniquely identify a card, e.g. each headphone generates a new * instanceId * @param uid uid for the application that media comes from - * @param isRecommendationCard whether the card is media recommendation * @param surfaces list of display surfaces the media card is on (e.g. lockscreen, shade) when * the event happened * @param interactedSubcardRank the rank for interacted media item for recommendation card, -1 @@ -779,21 +787,27 @@ class MediaCarouselController @Inject constructor( * @param rank the rank for media card in the media carousel, starting from 0 * @param receivedLatencyMillis latency in milliseconds for card received events. E.g. latency * between headphone connection to sysUI displays media recommendation card + * @param isSwipeToDismiss whether is to log swipe-to-dismiss event * */ fun logSmartspaceCardReported( eventId: Int, instanceId: Int, uid: Int, - isRecommendationCard: Boolean, surfaces: IntArray, interactedSubcardRank: Int = 0, interactedSubcardCardinality: Int = 0, rank: Int = mediaCarouselScrollHandler.visibleMediaIndex, - receivedLatencyMillis: Int = 0 + receivedLatencyMillis: Int = 0, + isSwipeToDismiss: Boolean = false ) { + if (MediaPlayerData.players().size <= rank) { + return + } + + val mediaControlKey = MediaPlayerData.playerKeys().elementAt(rank) // Only log media resume card when Smartspace data is available - if (!isRecommendationCard && + if (!mediaControlKey.isSsMediaRec && !mediaManager.smartspaceMediaData.isActive && MediaPlayerData.smartspaceMediaData == null) { return @@ -809,22 +823,28 @@ class MediaCarouselController @Inject constructor( // card type for each new feature. SysUiStatsLog.SMART_SPACE_CARD_REPORTED__CARD_TYPE__UNKNOWN_CARD, surface, - rank, + // Use -1 as rank value to indicate user swipe to dismiss the card + if (isSwipeToDismiss) -1 else rank, cardinality, - if (isRecommendationCard) + if (mediaControlKey.isSsMediaRec) 15 // MEDIA_RECOMMENDATION + else if (mediaControlKey.isSsReactivated) + 43 // MEDIA_RESUME_SS_ACTIVATED else 31, // MEDIA_RESUME uid, interactedSubcardRank, interactedSubcardCardinality, - receivedLatencyMillis + receivedLatencyMillis, + null // Media cards cannot have subcards. ) /* ktlint-disable max-line-length */ if (DEBUG) { Log.d(TAG, "Log Smartspace card event id: $eventId instance id: $instanceId" + " surface: $surface rank: $rank cardinality: $cardinality " + - "isRecommendationCard: $isRecommendationCard uid: $uid " + + "isRecommendationCard: ${mediaControlKey.isSsMediaRec} " + + "isSsReactivated: ${mediaControlKey.isSsReactivated}" + + "uid: $uid " + "interactedSubcardRank: $interactedSubcardRank " + "interactedSubcardCardinality: $interactedSubcardCardinality " + "received_latency_millis: $receivedLatencyMillis") @@ -839,10 +859,9 @@ class MediaCarouselController @Inject constructor( logSmartspaceCardReported(761, // SMARTSPACE_CARD_DISMISS it.mInstanceId, it.mUid, - it.recommendationViewHolder != null, intArrayOf(it.surfaceForSmartspaceLogging), - // Use -1 as rank value to indicate user swipe to dismiss the card - rank = -1) + rank = index, + isSwipeToDismiss = true) // Reset card impressed state when swipe to dismissed it.mIsImpressed = false } @@ -871,29 +890,37 @@ internal object MediaPlayerData { private set data class MediaSortKey( - // Whether the item represents a Smartspace media recommendation. - val isSsMediaRec: Boolean, + val isSsMediaRec: Boolean, // Whether the item represents a Smartspace media recommendation. val data: MediaData, - val updateTime: Long = 0 + val updateTime: Long = 0, + val isSsReactivated: Boolean = false ) private val comparator = compareByDescending<MediaSortKey> { it.data.isPlaying == true && it.data.playbackLocation == MediaData.PLAYBACK_LOCAL } - .thenByDescending { it.data.isPlaying == true && - it.data.playbackLocation == MediaData.PLAYBACK_CAST_LOCAL } - .thenByDescending { if (shouldPrioritizeSs) it.isSsMediaRec else !it.isSsMediaRec } - .thenByDescending { !it.data.resumption } - .thenByDescending { it.data.playbackLocation != MediaData.PLAYBACK_CAST_REMOTE } - .thenByDescending { it.updateTime } - .thenByDescending { it.data.notificationKey } + .thenByDescending { it.data.isPlaying == true && + it.data.playbackLocation == MediaData.PLAYBACK_CAST_LOCAL + } + .thenByDescending { if (shouldPrioritizeSs) it.isSsMediaRec else !it.isSsMediaRec } + .thenByDescending { !it.data.resumption } + .thenByDescending { it.data.playbackLocation != MediaData.PLAYBACK_CAST_REMOTE } + .thenByDescending { it.updateTime } + .thenByDescending { it.data.notificationKey } private val mediaPlayers = TreeMap<MediaSortKey, MediaControlPanel>(comparator) private val mediaData: MutableMap<String, MediaSortKey> = mutableMapOf() - fun addMediaPlayer(key: String, data: MediaData, player: MediaControlPanel, clock: SystemClock) { + fun addMediaPlayer( + key: String, + data: MediaData, + player: MediaControlPanel, + clock: SystemClock, + isSsReactivated: Boolean + ) { removeMediaPlayer(key) - val sortKey = MediaSortKey(isSsMediaRec = false, data, clock.currentTimeMillis()) + val sortKey = MediaSortKey(isSsMediaRec = false, + data, clock.currentTimeMillis(), isSsReactivated = isSsReactivated) mediaData.put(key, sortKey) mediaPlayers.put(sortKey, player) } @@ -907,8 +934,8 @@ internal object MediaPlayerData { ) { shouldPrioritizeSs = shouldPrioritize removeMediaPlayer(key) - val sortKey = MediaSortKey(/* isSsMediaRec= */ true, - EMPTY.copy(isPlaying = false), clock.currentTimeMillis()) + val sortKey = MediaSortKey(isSsMediaRec = true, + EMPTY.copy(isPlaying = false), clock.currentTimeMillis(), isSsReactivated = true) mediaData.put(key, sortKey) mediaPlayers.put(sortKey, player) smartspaceMediaData = data @@ -988,4 +1015,8 @@ internal object MediaPlayerData { } return false } + + fun isSsReactivated(key: String): Boolean = mediaData.get(key)?.let { + it.isSsReactivated + } ?: false }
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java index f66eb5ba008a..65b06946d3e7 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java +++ b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java @@ -22,6 +22,7 @@ import android.app.PendingIntent; import android.app.smartspace.SmartspaceAction; import android.content.Context; import android.content.Intent; +import android.content.pm.ActivityInfo; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.content.res.ColorStateList; @@ -35,6 +36,7 @@ import android.media.session.MediaSession; import android.media.session.PlaybackState; import android.os.Process; import android.text.Layout; +import android.text.TextUtils; import android.util.Log; import android.view.View; import android.view.ViewGroup; @@ -85,6 +87,7 @@ public class MediaControlPanel { private static final int MEDIA_RECOMMENDATION_MAX_NUM = 6; private static final String KEY_SMARTSPACE_ARTIST_NAME = "artist_name"; private static final String KEY_SMARTSPACE_OPEN_IN_FOREGROUND = "KEY_OPEN_IN_FOREGROUND"; + private static final String KEY_SMARTSPACE_APP_NAME = "KEY_SMARTSPACE_APP_NAME"; private static final Intent SETTINGS_INTENT = new Intent(ACTION_MEDIA_CONTROLS_SETTINGS); @@ -155,8 +158,8 @@ public class MediaControlPanel { mSeekBarViewModel.setLogSmartspaceClick(() -> { logSmartspaceCardReported( - 760, // SMARTSPACE_CARD_CLICK - /* isRecommendationCard */ false); + 760 // SMARTSPACE_CARD_CLICK + ); return Unit.INSTANCE; }); } @@ -323,8 +326,9 @@ public class MediaControlPanel { if (mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) return; if (mMediaViewController.isGutsVisible()) return; - logSmartspaceCardReported(760, // SMARTSPACE_CARD_CLICK - /* isRecommendationCard */ false); + logSmartspaceCardReported( + 760 // SMARTSPACE_CARD_CLICK + ); mActivityStarter.postStartActivityDismissingKeyguard(clickIntent, buildLaunchAnimatorController(mPlayerViewHolder.getPlayer())); }); @@ -444,8 +448,9 @@ public class MediaControlPanel { button.setEnabled(true); button.setOnClickListener(v -> { if (!mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) { - logSmartspaceCardReported(760, // SMARTSPACE_CARD_CLICK - /* isRecommendationCard */ false); + logSmartspaceCardReported( + 760 // SMARTSPACE_CARD_CLICK + ); action.run(); } }); @@ -481,8 +486,9 @@ public class MediaControlPanel { mPlayerViewHolder.getDismiss().setOnClickListener(v -> { if (mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) return; - logSmartspaceCardReported(761, // SMARTSPACE_CARD_DISMISS - /* isRecommendationCard */ false); + logSmartspaceCardReported( + 761 // SMARTSPACE_CARD_DISMISS + ); if (mKey != null) { closeGuts(); @@ -578,18 +584,33 @@ public class MediaControlPanel { icon.setColorFilter(getGrayscaleFilter()); ImageView headerLogoImageView = mRecommendationViewHolder.getCardIcon(); headerLogoImageView.setImageDrawable(icon); + // Set up media source app's label text. - CharSequence appLabel = packageManager.getApplicationLabel(applicationInfo); - if (appLabel.length() != 0) { + CharSequence appName = getAppName(data.getCardAction()); + if (TextUtils.isEmpty(appName)) { + Intent launchIntent = + packageManager.getLaunchIntentForPackage(data.getPackageName()); + if (launchIntent != null) { + ActivityInfo launchActivity = launchIntent.resolveActivityInfo(packageManager, 0); + appName = launchActivity.loadLabel(packageManager); + } else { + Log.w(TAG, "Package " + data.getPackageName() + + " does not have a main launcher activity. Fallback to full app name"); + appName = packageManager.getApplicationLabel(applicationInfo); + } + } + // Set the app name as card's title. + if (!TextUtils.isEmpty(appName)) { TextView headerTitleText = mRecommendationViewHolder.getCardText(); - headerTitleText.setText(appLabel); + headerTitleText.setText(appName); } + // Set up media rec card's tap action if applicable. setSmartspaceRecItemOnClickListener(recommendationCard, data.getCardAction(), /* interactedSubcardRank */ -1); // Set up media rec card's accessibility label. recommendationCard.setContentDescription( - mContext.getString(R.string.controls_media_smartspace_rec_description, appLabel)); + mContext.getString(R.string.controls_media_smartspace_rec_description, appName)); List<ImageView> mediaCoverItems = mRecommendationViewHolder.getMediaCoverItems(); List<ViewGroup> mediaCoverContainers = mRecommendationViewHolder.getMediaCoverContainers(); @@ -634,12 +655,12 @@ public class MediaControlPanel { mediaCoverImageView.setContentDescription( mContext.getString( R.string.controls_media_smartspace_rec_item_no_artist_description, - recommendation.getTitle(), appLabel)); + recommendation.getTitle(), appName)); } else { mediaCoverImageView.setContentDescription( mContext.getString( R.string.controls_media_smartspace_rec_item_description, - recommendation.getTitle(), artistName, appLabel)); + recommendation.getTitle(), artistName, appName)); } if (uiComponentIndex < MEDIA_RECOMMENDATION_ITEMS_PER_ROW) { @@ -665,8 +686,9 @@ public class MediaControlPanel { mRecommendationViewHolder.getDismiss().setOnClickListener(v -> { if (mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) return; - logSmartspaceCardReported(761, // SMARTSPACE_CARD_DISMISS - /* isRecommendationCard */ true); + logSmartspaceCardReported( + 761 // SMARTSPACE_CARD_DISMISS + ); closeGuts(); mMediaDataManagerLazy.get().dismissSmartspaceRecommendation( data.getTargetId(), MediaViewController.GUTS_ANIMATION_DURATION + 100L); @@ -823,7 +845,6 @@ public class MediaControlPanel { if (mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) return; logSmartspaceCardReported(760, // SMARTSPACE_CARD_CLICK - /* isRecommendationCard */ true, interactedSubcardRank, getSmartspaceSubCardCardinality()); @@ -844,6 +865,17 @@ public class MediaControlPanel { }); } + /** Returns the upstream app name if available. */ + @Nullable + private String getAppName(SmartspaceAction action) { + if (action == null || action.getIntent() == null + || action.getIntent().getExtras() == null) { + return null; + } + + return action.getIntent().getExtras().getString(KEY_SMARTSPACE_APP_NAME); + } + /** Returns if the Smartspace action will open the activity in foreground. */ private boolean shouldSmartspaceRecItemOpenInForeground(SmartspaceAction action) { if (action == null || action.getIntent() == null @@ -882,18 +914,17 @@ public class MediaControlPanel { return SysUiStatsLog.SMART_SPACE_CARD_REPORTED__DISPLAY_SURFACE__DEFAULT_SURFACE; } - private void logSmartspaceCardReported(int eventId, boolean isRecommendationCard) { - logSmartspaceCardReported(eventId, isRecommendationCard, + private void logSmartspaceCardReported(int eventId) { + logSmartspaceCardReported(eventId, /* interactedSubcardRank */ 0, /* interactedSubcardCardinality */ 0); } - private void logSmartspaceCardReported(int eventId, boolean isRecommendationCard, + private void logSmartspaceCardReported(int eventId, int interactedSubcardRank, int interactedSubcardCardinality) { mMediaCarouselController.logSmartspaceCardReported(eventId, mInstanceId, mUid, - isRecommendationCard, new int[]{getSurfaceForSmartspaceLogging()}, interactedSubcardRank, interactedSubcardCardinality); diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataCombineLatest.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataCombineLatest.kt index b68f2a7654f0..311973ad5af0 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaDataCombineLatest.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataCombineLatest.kt @@ -32,7 +32,8 @@ class MediaDataCombineLatest @Inject constructor() : MediaDataManager.Listener, oldKey: String?, data: MediaData, immediately: Boolean, - receivedSmartspaceCardLatency: Int + receivedSmartspaceCardLatency: Int, + isSsReactivated: Boolean ) { if (oldKey != null && oldKey != key && entries.contains(oldKey)) { entries[key] = data to entries.remove(oldKey)?.second @@ -46,8 +47,7 @@ class MediaDataCombineLatest @Inject constructor() : MediaDataManager.Listener, override fun onSmartspaceMediaDataLoaded( key: String, data: SmartspaceMediaData, - shouldPrioritize: Boolean, - isSsReactivated: Boolean + shouldPrioritize: Boolean ) { listeners.toSet().forEach { it.onSmartspaceMediaDataLoaded(key, data) } } diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt index ae5c1f2b19a9..919bce2cb360 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataFilter.kt @@ -87,7 +87,8 @@ class MediaDataFilter @Inject constructor( oldKey: String?, data: MediaData, immediately: Boolean, - receivedSmartspaceCardLatency: Int + receivedSmartspaceCardLatency: Int, + isSsReactivated: Boolean ) { if (oldKey != null && oldKey != key) { allEntries.remove(oldKey) @@ -112,8 +113,7 @@ class MediaDataFilter @Inject constructor( override fun onSmartspaceMediaDataLoaded( key: String, data: SmartspaceMediaData, - shouldPrioritize: Boolean, - isSsReactivated: Boolean + shouldPrioritize: Boolean ) { if (!data.isActive) { Log.d(TAG, "Inactive recommendation data. Skip triggering.") @@ -138,13 +138,12 @@ class MediaDataFilter @Inject constructor( } } - val activeMedia = userEntries.filter { (key, value) -> value.active } - var isSsReactivatedMutable = activeMedia.isEmpty() && userEntries.isNotEmpty() + val shouldReactivate = !hasActiveMedia() && hasAnyMedia() if (timeSinceActive < smartspaceMaxAgeMillis) { // It could happen there are existing active media resume cards, then we don't need to // reactivate. - if (isSsReactivatedMutable) { + if (shouldReactivate) { val lastActiveKey = sorted.lastKey() // most recently active // Notify listeners to consider this media active Log.d(TAG, "reactivating $lastActiveKey instead of smartspace") @@ -154,7 +153,7 @@ class MediaDataFilter @Inject constructor( it.onMediaDataLoaded(lastActiveKey, lastActiveKey, mediaData, receivedSmartspaceCardLatency = (systemClock.currentTimeMillis() - data.headphoneConnectionTimeMillis) - .toInt()) + .toInt(), isSsReactivated = true) } } } else { @@ -166,8 +165,7 @@ class MediaDataFilter @Inject constructor( Log.d(TAG, "Invalid recommendation data. Skip showing the rec card") return } - listeners.forEach { it.onSmartspaceMediaDataLoaded(key, data, shouldPrioritizeMutable, - isSsReactivatedMutable) } + listeners.forEach { it.onSmartspaceMediaDataLoaded(key, data, shouldPrioritizeMutable) } } override fun onMediaDataRemoved(key: String) { @@ -258,14 +256,27 @@ class MediaDataFilter @Inject constructor( } /** - * Are there any media notifications active? + * Are there any media notifications active, including the recommendation? */ - fun hasActiveMedia() = userEntries.any { it.value.active } || smartspaceMediaData.isActive + fun hasActiveMediaOrRecommendation() = + userEntries.any { it.value.active } || + (smartspaceMediaData.isActive && smartspaceMediaData.isValid) /** * Are there any media entries we should display? */ - fun hasAnyMedia() = userEntries.isNotEmpty() || smartspaceMediaData.isActive + fun hasAnyMediaOrRecommendation() = userEntries.isNotEmpty() || + (smartspaceMediaData.isActive && smartspaceMediaData.isValid) + + /** + * Are there any media notifications active (excluding the recommendation)? + */ + fun hasActiveMedia() = userEntries.any { it.value.active } + + /** + * Are there any media entries we should display (excluding the recommendation)? + */ + fun hasAnyMedia() = userEntries.isNotEmpty() /** * Add a listener for filtered [MediaData] changes diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt index 7c0f7fc2967e..5d2d556a5773 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt @@ -828,15 +828,27 @@ class MediaDataManager( fun onSwipeToDismiss() = mediaDataFilter.onSwipeToDismiss() /** - * Are there any media notifications active? + * Are there any media notifications active, including the recommendations? */ - fun hasActiveMedia() = mediaDataFilter.hasActiveMedia() + fun hasActiveMediaOrRecommendation() = mediaDataFilter.hasActiveMediaOrRecommendation() /** - * Are there any media entries we should display? + * Are there any media entries we should display, including the recommendations? * If resumption is enabled, this will include inactive players * If resumption is disabled, we only want to show active players */ + fun hasAnyMediaOrRecommendation() = mediaDataFilter.hasAnyMediaOrRecommendation() + + /** + * Are there any resume media notifications active, excluding the recommendations? + */ + fun hasActiveMedia() = mediaDataFilter.hasActiveMedia() + + /** + * Are there any resume media notifications active, excluding the recommendations? + * If resumption is enabled, this will include inactive players + * If resumption is disabled, we only want to show active players + */ fun hasAnyMedia() = mediaDataFilter.hasAnyMedia() interface Listener { @@ -855,13 +867,17 @@ class MediaDataManager( * @param receivedSmartspaceCardLatency is the latency between headphone connects and sysUI * displays Smartspace media targets. Will be 0 if the data is not activated by Smartspace * signal. + * + * @param isSsReactivated indicates resume media card is reactivated by Smartspace + * recommendation signal */ fun onMediaDataLoaded( key: String, oldKey: String?, data: MediaData, immediately: Boolean = true, - receivedSmartspaceCardLatency: Int = 0 + receivedSmartspaceCardLatency: Int = 0, + isSsReactivated: Boolean = false ) {} /** @@ -870,15 +886,11 @@ class MediaDataManager( * @param shouldPrioritize indicates the sorting priority of the Smartspace card. If true, * it will be prioritized as the first card. Otherwise, it will show up as the last card as * default. - * - * @param isSsReactivated indicates resume media card is reactivated by Smartspace - * recommendation signal */ fun onSmartspaceMediaDataLoaded( key: String, data: SmartspaceMediaData, - shouldPrioritize: Boolean = false, - isSsReactivated: Boolean = false + shouldPrioritize: Boolean = false ) {} /** Called whenever a previously existing Media notification was removed. */ diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt index bed254fe8249..085bae8bc25d 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaDeviceManager.kt @@ -68,7 +68,8 @@ class MediaDeviceManager @Inject constructor( oldKey: String?, data: MediaData, immediately: Boolean, - receivedSmartspaceCardLatency: Int + receivedSmartspaceCardLatency: Int, + isSsReactivated: Boolean ) { if (oldKey != null && oldKey != key) { val oldEntry = entries.remove(oldKey) diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt index c8cd43287c99..a7640ff951c8 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt @@ -28,6 +28,7 @@ import android.view.View import android.view.ViewGroup import android.view.ViewGroupOverlay import androidx.annotation.VisibleForTesting +import com.android.keyguard.KeyguardViewController import com.android.systemui.R import com.android.systemui.animation.Interpolators import com.android.systemui.dagger.SysUISingleton @@ -39,7 +40,6 @@ import com.android.systemui.statusbar.StatusBarState import com.android.systemui.statusbar.SysuiStatusBarStateController import com.android.systemui.statusbar.notification.stack.StackStateAnimator import com.android.systemui.statusbar.phone.KeyguardBypassController -import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.util.Utils @@ -82,7 +82,7 @@ class MediaHierarchyManager @Inject constructor( private val notifLockscreenUserManager: NotificationLockscreenUserManager, configurationController: ConfigurationController, wakefulnessLifecycle: WakefulnessLifecycle, - private val statusBarKeyguardViewManager: StatusBarKeyguardViewManager + private val keyguardViewController: KeyguardViewController ) { /** @@ -998,7 +998,7 @@ class MediaHierarchyManager @Inject constructor( private fun isLockScreenVisibleToUser(): Boolean { return !statusBarStateController.isDozing && - !statusBarKeyguardViewManager.isBouncerShowing && + !keyguardViewController.isBouncerShowing && statusBarStateController.state == StatusBarState.KEYGUARD && notifLockscreenUserManager.shouldShowLockscreenNotifications() && statusBarStateController.isExpanded && @@ -1007,7 +1007,7 @@ class MediaHierarchyManager @Inject constructor( private fun isLockScreenShadeVisibleToUser(): Boolean { return !statusBarStateController.isDozing && - !statusBarKeyguardViewManager.isBouncerShowing && + !keyguardViewController.isBouncerShowing && (statusBarStateController.state == StatusBarState.SHADE_LOCKED || (statusBarStateController.state == StatusBarState.KEYGUARD && qsExpanded)) } diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaHost.kt b/packages/SystemUI/src/com/android/systemui/media/MediaHost.kt index 0a4b68b501f7..3ed90fd0c58c 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaHost.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaHost.kt @@ -61,7 +61,8 @@ class MediaHost constructor( oldKey: String?, data: MediaData, immediately: Boolean, - receivedSmartspaceCardLatency: Int + receivedSmartspaceCardLatency: Int, + isSsReactivated: Boolean ) { if (immediately) { updateViewVisibility() @@ -71,8 +72,7 @@ class MediaHost constructor( override fun onSmartspaceMediaDataLoaded( key: String, data: SmartspaceMediaData, - shouldPrioritize: Boolean, - isSsReactivated: Boolean + shouldPrioritize: Boolean ) { updateViewVisibility() } @@ -162,9 +162,9 @@ class MediaHost constructor( private fun updateViewVisibility() { state.visible = if (showsOnlyActiveMedia) { - mediaDataManager.hasActiveMedia() + mediaDataManager.hasActiveMediaOrRecommendation() } else { - mediaDataManager.hasAnyMedia() + mediaDataManager.hasAnyMediaOrRecommendation() } val newVisibility = if (visible) View.VISIBLE else View.GONE if (newVisibility != hostView.visibility) { diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt b/packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt index 35f95dd27c1f..61d0b41e9bb6 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaResumeListener.kt @@ -184,7 +184,8 @@ class MediaResumeListener @Inject constructor( oldKey: String?, data: MediaData, immediately: Boolean, - receivedSmartspaceCardLatency: Int + receivedSmartspaceCardLatency: Int, + isSsReactivated: Boolean ) { if (useMediaResumption) { // If this had been started from a resume state, disconnect now that it's live diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaSessionBasedFilter.kt b/packages/SystemUI/src/com/android/systemui/media/MediaSessionBasedFilter.kt index 1c448a2ff8c4..31792967899d 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaSessionBasedFilter.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaSessionBasedFilter.kt @@ -96,7 +96,8 @@ class MediaSessionBasedFilter @Inject constructor( oldKey: String?, data: MediaData, immediately: Boolean, - receivedSmartspaceCardLatency: Int + receivedSmartspaceCardLatency: Int, + isSsReactivated: Boolean ) { backgroundExecutor.execute { data.token?.let { @@ -143,8 +144,7 @@ class MediaSessionBasedFilter @Inject constructor( override fun onSmartspaceMediaDataLoaded( key: String, data: SmartspaceMediaData, - shouldPrioritize: Boolean, - isSsReactivated: Boolean + shouldPrioritize: Boolean ) { backgroundExecutor.execute { dispatchSmartspaceMediaDataLoaded(key, data) diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaTimeoutListener.kt b/packages/SystemUI/src/com/android/systemui/media/MediaTimeoutListener.kt index 9581a633a8c5..51755065d4b6 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaTimeoutListener.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaTimeoutListener.kt @@ -63,7 +63,8 @@ class MediaTimeoutListener @Inject constructor( oldKey: String?, data: MediaData, immediately: Boolean, - receivedSmartspaceCardLatency: Int + receivedSmartspaceCardLatency: Int, + isSsReactivated: Boolean ) { var reusedListener: PlaybackStateListener? = null diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java index 113ba59cd514..e01916f0abe8 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java @@ -177,13 +177,9 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter { mConnectedItem = mContainerLayout; mBottomDivider.setVisibility(View.GONE); mCheckBox.setVisibility(View.GONE); - if (mController.getSelectableMediaDevice().size() > 0) { - mAddIcon.setVisibility(View.VISIBLE); - mAddIcon.setTransitionAlpha(1); - mAddIcon.setOnClickListener(this::onEndItemClick); - } else { - mAddIcon.setVisibility(View.GONE); - } + mAddIcon.setVisibility(View.VISIBLE); + mAddIcon.setTransitionAlpha(1); + mAddIcon.setOnClickListener(this::onEndItemClick); mTitleIcon.setImageDrawable(getSpeakerDrawable()); final CharSequence sessionName = mController.getSessionName(); final CharSequence title = TextUtils.isEmpty(sessionName) @@ -198,7 +194,10 @@ public class MediaOutputAdapter extends MediaOutputBaseAdapter { if (mController.isTransferring()) { return; } - + if (isCurrentlyConnected(device)) { + Log.d(TAG, "This device is already connected! : " + device.getName()); + return; + } mCurrentActivePosition = -1; playSwitchingAnim(mConnectedItem, view); mController.connectDevice(device); diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java index f2cb254c3b97..b309c1bb67b9 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java @@ -150,6 +150,10 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements } void refresh() { + refresh(false); + } + + void refresh(boolean deviceSetChanged) { // Update header icon final int iconRes = getHeaderIconRes(); final IconCompat iconCompat = getHeaderIcon(); @@ -175,7 +179,8 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements } if (!mAdapter.isDragging() && !mAdapter.isAnimating()) { int currentActivePosition = mAdapter.getCurrentActivePosition(); - if (currentActivePosition >= 0 && currentActivePosition < mAdapter.getItemCount()) { + if (!deviceSetChanged && currentActivePosition >= 0 + && currentActivePosition < mAdapter.getItemCount()) { mAdapter.notifyItemChanged(currentActivePosition); } else { mAdapter.notifyDataSetChanged(); @@ -215,6 +220,11 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements } @Override + public void onDeviceListChanged() { + mMainThreadHandler.post(() -> refresh(true)); + } + + @Override public void dismissDialog() { dismiss(); } diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java index a1e2c57c5c37..0d368fa5fb7f 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java @@ -84,7 +84,6 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback { private final SystemUIDialogManager mDialogManager; private final List<MediaDevice> mGroupMediaDevices = new CopyOnWriteArrayList<>(); private final boolean mAboveStatusbar; - private final boolean mVolumeAdjustmentForRemoteGroupSessions; private final NotificationEntryManager mNotificationEntryManager; @VisibleForTesting final List<MediaDevice> mMediaDevices = new CopyOnWriteArrayList<>(); @@ -117,8 +116,6 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback { mMetricLogger = new MediaOutputMetricLogger(mContext, mPackageName); mUiEventLogger = uiEventLogger; mDialogLaunchAnimator = dialogLaunchAnimator; - mVolumeAdjustmentForRemoteGroupSessions = mContext.getResources().getBoolean( - com.android.internal.R.bool.config_volumeAdjustmentForRemoteGroupSessions); mDialogManager = dialogManager; } @@ -166,7 +163,7 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback { @Override public void onDeviceListUpdate(List<MediaDevice> devices) { buildMediaDevices(devices); - mCallback.onRouteChanged(); + mCallback.onDeviceListChanged(); } @Override @@ -496,10 +493,15 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback { || features.contains(MediaRoute2Info.FEATURE_REMOTE_GROUP_PLAYBACK)); } + private boolean isPlayBackInfoLocal() { + return mMediaController.getPlaybackInfo() != null + && mMediaController.getPlaybackInfo().getPlaybackType() + == MediaController.PlaybackInfo.PLAYBACK_TYPE_LOCAL; + } + boolean isVolumeControlEnabled(@NonNull MediaDevice device) { - // TODO(b/202500642): Also enable volume control for remote non-group sessions. - return !isActiveRemoteDevice(device) - || mVolumeAdjustmentForRemoteGroupSessions; + return isPlayBackInfoLocal() + || mLocalMediaManager.isMediaSessionAvailableForVolumeControl(); } private final MediaController.Callback mCb = new MediaController.Callback() { @@ -529,11 +531,16 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback { void onMediaStoppedOrPaused(); /** - * Override to handle the device updating. + * Override to handle the device status or attributes updating. */ void onRouteChanged(); /** + * Override to handle the devices set updating. + */ + void onDeviceListChanged(); + + /** * Override to dismiss dialog. */ void dismissDialog(); diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupAdapter.java index a201c071bbbe..6c95cc661e7f 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupAdapter.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupAdapter.java @@ -107,6 +107,8 @@ public class MediaOutputGroupAdapter extends MediaOutputBaseAdapter { initSeekbar(device); final List<MediaDevice> selectedDevices = mController.getSelectedMediaDevice(); if (isDeviceIncluded(mController.getSelectableMediaDevice(), device)) { + mSeekBar.setEnabled(false); + mSeekBar.setOnTouchListener((v, event) -> true); mCheckBox.setButtonDrawable(R.drawable.ic_check_box); mCheckBox.setChecked(false); mCheckBox.setEnabled(true); diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java index 38cefe65dfda..f1e5b56c1fc7 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java @@ -429,7 +429,6 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca public void setBrightnessMirrorController( BrightnessMirrorController brightnessMirrorController) { mQSPanelController.setBrightnessMirror(brightnessMirrorController); - mQuickQSPanelController.setBrightnessMirror(brightnessMirrorController); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java index 001c740e310a..1837b5bf2044 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java @@ -182,7 +182,9 @@ public class QSPanelController extends QSPanelControllerBase<QSPanel> { /** */ public void setListening(boolean listening, boolean expanded) { - setListening(listening && expanded); + // TODO(218268829): checking for split shade is workaround but when proper fix lands + // "|| mShouldUseSplitNotificationShade" should be removed + setListening(listening && (expanded || mShouldUseSplitNotificationShade)); if (mView.isListening()) { refreshAllTiles(); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSBrightnessController.kt b/packages/SystemUI/src/com/android/systemui/qs/QuickQSBrightnessController.kt deleted file mode 100644 index 65889d792769..000000000000 --- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSBrightnessController.kt +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (C) 2021 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.systemui.qs - -import androidx.annotation.VisibleForTesting -import com.android.systemui.settings.brightness.BrightnessController -import com.android.systemui.settings.brightness.BrightnessSliderController -import com.android.systemui.settings.brightness.MirroredBrightnessController -import com.android.systemui.statusbar.policy.BrightnessMirrorController -import javax.inject.Inject - -/** - * Controls brightness slider in QQS, which is visible only in split shade. It's responsible for - * showing/hiding it when appropriate and (un)registering listeners - */ -class QuickQSBrightnessController @VisibleForTesting constructor( - private val brightnessControllerFactory: () -> BrightnessController -) : MirroredBrightnessController { - - @Inject constructor( - brightnessControllerFactory: BrightnessController.Factory, - brightnessSliderControllerFactory: BrightnessSliderController.Factory, - quickQSPanel: QuickQSPanel - ) : this(brightnessControllerFactory = { - val slider = brightnessSliderControllerFactory.create(quickQSPanel.context, - quickQSPanel) - slider.init() - quickQSPanel.setBrightnessView(slider.rootView) - brightnessControllerFactory.create(slider) - }) - - private var isListening = false - private var brightnessController: BrightnessController? = null - private var mirrorController: BrightnessMirrorController? = null - - fun init(shouldUseSplitNotificationShade: Boolean) { - refreshVisibility(shouldUseSplitNotificationShade) - } - - /** - * Starts/Stops listening for brightness changing events. - * It's fine to call this function even if slider is not visible (which would be the case for - * all small screen devices), it will just do nothing in that case - */ - fun setListening(listening: Boolean) { - if (listening) { - // controller can be null when slider was never shown - if (!isListening && brightnessController != null) { - brightnessController?.registerCallbacks() - isListening = true - } - } else { - brightnessController?.unregisterCallbacks() - isListening = false - } - } - - fun checkRestrictionAndSetEnabled() { - brightnessController?.checkRestrictionAndSetEnabled() - } - - fun refreshVisibility(shouldUseSplitNotificationShade: Boolean) { - if (shouldUseSplitNotificationShade) { - showBrightnessSlider() - } else { - hideBrightnessSlider() - } - } - - override fun setMirror(controller: BrightnessMirrorController) { - mirrorController = controller - mirrorController?.let { brightnessController?.setMirror(it) } - } - - private fun hideBrightnessSlider() { - brightnessController?.hideSlider() - } - - private fun showBrightnessSlider() { - if (brightnessController == null) { - brightnessController = brightnessControllerFactory() - mirrorController?.also { brightnessController?.setMirror(it) } - brightnessController?.registerCallbacks() - isListening = true - } - brightnessController?.showSlider() - } -} diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java index 92690c7d1202..fdd764ce7127 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java @@ -30,8 +30,6 @@ import com.android.systemui.plugins.qs.QSTile; import com.android.systemui.qs.customize.QSCustomizerController; import com.android.systemui.qs.dagger.QSScope; import com.android.systemui.qs.logging.QSLogger; -import com.android.systemui.settings.brightness.BrightnessMirrorHandler; -import com.android.systemui.statusbar.policy.BrightnessMirrorController; import java.util.ArrayList; import java.util.List; @@ -51,9 +49,6 @@ public class QuickQSPanelController extends QSPanelControllerBase<QuickQSPanel> } }; - // brightness is visible only in split shade - private final QuickQSBrightnessController mBrightnessController; - private final BrightnessMirrorHandler mBrightnessMirrorHandler; private final FooterActionsController mFooterActionsController; @Inject @@ -63,13 +58,10 @@ public class QuickQSPanelController extends QSPanelControllerBase<QuickQSPanel> @Named(QUICK_QS_PANEL) MediaHost mediaHost, MetricsLogger metricsLogger, UiEventLogger uiEventLogger, QSLogger qsLogger, DumpManager dumpManager, - QuickQSBrightnessController quickQSBrightnessController, @Named(QQS_FOOTER) FooterActionsController footerActionsController ) { super(view, qsTileHost, qsCustomizerController, usingMediaPlayer, mediaHost, metricsLogger, uiEventLogger, qsLogger, dumpManager); - mBrightnessController = quickQSBrightnessController; - mBrightnessMirrorHandler = new BrightnessMirrorHandler(mBrightnessController); mFooterActionsController = footerActionsController; } @@ -79,7 +71,6 @@ public class QuickQSPanelController extends QSPanelControllerBase<QuickQSPanel> mMediaHost.setExpansion(0.0f); mMediaHost.setShowsOnlyActiveMedia(true); mMediaHost.init(MediaHierarchyManager.LOCATION_QQS); - mBrightnessController.init(mShouldUseSplitNotificationShade); mFooterActionsController.init(); mFooterActionsController.refreshVisibility(mShouldUseSplitNotificationShade); } @@ -88,20 +79,17 @@ public class QuickQSPanelController extends QSPanelControllerBase<QuickQSPanel> protected void onViewAttached() { super.onViewAttached(); mView.addOnConfigurationChangedListener(mOnConfigurationChangedListener); - mBrightnessMirrorHandler.onQsPanelAttached(); } @Override protected void onViewDetached() { super.onViewDetached(); mView.removeOnConfigurationChangedListener(mOnConfigurationChangedListener); - mBrightnessMirrorHandler.onQsPanelDettached(); } @Override void setListening(boolean listening) { super.setListening(listening); - mBrightnessController.setListening(listening); mFooterActionsController.setListening(listening); } @@ -115,14 +103,7 @@ public class QuickQSPanelController extends QSPanelControllerBase<QuickQSPanel> } @Override - public void refreshAllTiles() { - mBrightnessController.checkRestrictionAndSetEnabled(); - super.refreshAllTiles(); - } - - @Override protected void onConfigurationChanged() { - mBrightnessController.refreshVisibility(mShouldUseSplitNotificationShade); mFooterActionsController.refreshVisibility(mShouldUseSplitNotificationShade); } @@ -146,8 +127,4 @@ public class QuickQSPanelController extends QSPanelControllerBase<QuickQSPanel> public int getNumQuickTiles() { return mView.getNumQuickTiles(); } - - public void setBrightnessMirror(BrightnessMirrorController brightnessMirrorController) { - mBrightnessMirrorHandler.setController(brightnessMirrorController); - } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java index 0e3b5b5c882b..5b378007d570 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java @@ -242,13 +242,12 @@ public class NotificationMediaManager implements Dumpable { @Override public void onMediaDataLoaded(@NonNull String key, @Nullable String oldKey, @NonNull MediaData data, boolean immediately, - int receivedSmartspaceCardLatency) { + int receivedSmartspaceCardLatency, boolean isSsReactivated) { } @Override public void onSmartspaceMediaDataLoaded(@NonNull String key, - @NonNull SmartspaceMediaData data, boolean shouldPrioritize, - boolean isSsReactivated) { + @NonNull SmartspaceMediaData data, boolean shouldPrioritize) { } @Override @@ -317,13 +316,12 @@ public class NotificationMediaManager implements Dumpable { @Override public void onMediaDataLoaded(@NonNull String key, @Nullable String oldKey, @NonNull MediaData data, boolean immediately, - int receivedSmartspaceCardLatency) { + int receivedSmartspaceCardLatency, boolean isSsReactivated) { } @Override public void onSmartspaceMediaDataLoaded(@NonNull String key, - @NonNull SmartspaceMediaData data, boolean shouldPrioritize, - boolean isSsReactivated) { + @NonNull SmartspaceMediaData data, boolean shouldPrioritize) { } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeWindowController.java index 6ea79af8b9ad..65ff5583e7d4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeWindowController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeWindowController.java @@ -18,6 +18,7 @@ package com.android.systemui.statusbar; import android.view.ViewGroup; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.android.systemui.statusbar.phone.StatusBarWindowCallback; @@ -188,6 +189,14 @@ public interface NotificationShadeWindowController extends RemoteInputController default void setLightRevealScrimOpaque(boolean opaque) {} /** + * Defer any application of window {@link WindowManager.LayoutParams} until {@code scope} is + * fully applied. + */ + default void batchApplyWindowLayoutParams(@NonNull Runnable scope) { + scope.run(); + } + + /** * Custom listener to pipe data back to plugins about whether or not the status bar would be * collapsed if not for the plugin. * TODO: Find cleaner way to do this. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java index 464b2b69c58e..e0e928073336 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java @@ -25,6 +25,7 @@ import android.util.Log; import android.view.View; import android.view.ViewGroup; +import com.android.keyguard.KeyguardUpdateMonitor; import com.android.systemui.R; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.flags.FeatureFlags; @@ -42,6 +43,7 @@ import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow import com.android.systemui.statusbar.notification.stack.ForegroundServiceSectionController; import com.android.systemui.statusbar.notification.stack.NotificationListContainer; import com.android.systemui.statusbar.phone.KeyguardBypassController; +import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.util.Assert; import com.android.wm.shell.bubbles.Bubbles; @@ -92,6 +94,8 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle private final KeyguardBypassController mBypassController; private final ForegroundServiceSectionController mFgsSectionController; private AssistantFeedbackController mAssistantFeedbackController; + private final KeyguardStateController mKeyguardStateController; + private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; private final Context mContext; private NotificationPresenter mPresenter; @@ -121,7 +125,9 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle ForegroundServiceSectionController fgsSectionController, DynamicChildBindController dynamicChildBindController, LowPriorityInflationHelper lowPriorityInflationHelper, - AssistantFeedbackController assistantFeedbackController) { + AssistantFeedbackController assistantFeedbackController, + KeyguardUpdateMonitor keyguardUpdateMonitor, + KeyguardStateController keyguardStateController) { mContext = context; mHandler = mainHandler; mFeatureFlags = featureFlags; @@ -140,6 +146,8 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle mDynamicChildBindController = dynamicChildBindController; mLowPriorityInflationHelper = lowPriorityInflationHelper; mAssistantFeedbackController = assistantFeedbackController; + mKeyguardUpdateMonitor = keyguardUpdateMonitor; + mKeyguardStateController = keyguardStateController; } public void setUpWithPresenter(NotificationPresenter presenter, @@ -163,6 +171,11 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle beginUpdate(); + boolean dynamicallyUnlocked = mDynamicPrivacyController.isDynamicallyUnlocked() + && !(mStatusBarStateController.getState() == StatusBarState.KEYGUARD + && mKeyguardUpdateMonitor.getUserUnlockedWithBiometricAndIsBypassing( + KeyguardUpdateMonitor.getCurrentUser())) + && !mKeyguardStateController.isKeyguardGoingAway(); List<NotificationEntry> activeNotifications = mEntryManager.getVisibleNotifications(); ArrayList<ExpandableNotificationRow> toShow = new ArrayList<>(activeNotifications.size()); final int N = activeNotifications.size(); @@ -181,7 +194,7 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle boolean devicePublic = mLockscreenUserManager.isLockscreenPublicMode(currentUserId); boolean userPublic = devicePublic || mLockscreenUserManager.isLockscreenPublicMode(userId); - if (userPublic && mDynamicPrivacyController.isDynamicallyUnlocked() + if (userPublic && dynamicallyUnlocked && (userId == currentUserId || userId == UserHandle.USER_ALL || !mLockscreenUserManager.needsSeparateWorkChallenge(userId))) { userPublic = false; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java index da2b85ee0b61..af503a9360ff 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java @@ -28,6 +28,7 @@ import android.animation.AnimatorListenerAdapter; import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.os.SystemProperties; +import android.os.Trace; import android.text.format.DateFormat; import android.util.FloatProperty; import android.util.Log; @@ -507,6 +508,7 @@ public class StatusBarStateControllerImpl implements } private void recordHistoricalState(int newState, int lastState, boolean upcoming) { + Trace.traceCounter(Trace.TRACE_TAG_APP, "statusBarState", newState); mHistoryIndex = (mHistoryIndex + 1) % HISTORY_SIZE; HistoricalState state = mHistoricalRecords[mHistoryIndex]; state.mNewState = newState; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java index f2d926d97108..4c5522fc66c8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java @@ -23,6 +23,7 @@ import android.os.Handler; import android.service.dreams.IDreamManager; import com.android.internal.statusbar.IStatusBarService; +import com.android.keyguard.KeyguardUpdateMonitor; import com.android.systemui.animation.ActivityLaunchAnimator; import com.android.systemui.animation.DialogLaunchAnimator; import com.android.systemui.dagger.SysUISingleton; @@ -69,6 +70,7 @@ import com.android.systemui.statusbar.phone.StatusBarIconControllerImpl; import com.android.systemui.statusbar.phone.StatusBarRemoteInputCallback; import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController; import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallLogger; +import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.statusbar.policy.RemoteInputUriController; import com.android.systemui.statusbar.window.StatusBarWindowController; import com.android.systemui.tracing.ProtoTracer; @@ -201,7 +203,9 @@ public interface StatusBarDependenciesModule { ForegroundServiceSectionController fgsSectionController, DynamicChildBindController dynamicChildBindController, LowPriorityInflationHelper lowPriorityInflationHelper, - AssistantFeedbackController assistantFeedbackController) { + AssistantFeedbackController assistantFeedbackController, + KeyguardUpdateMonitor keyguardUpdateMonitor, + KeyguardStateController keyguardStateController) { return new NotificationViewHierarchyManager( context, mainHandler, @@ -217,7 +221,9 @@ public interface StatusBarDependenciesModule { fgsSectionController, dynamicChildBindController, lowPriorityInflationHelper, - assistantFeedbackController); + assistantFeedbackController, + keyguardUpdateMonitor, + keyguardStateController); } /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java index fe1cd7b98cf9..43710916628a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/KeyguardCoordinator.java @@ -157,6 +157,8 @@ public class KeyguardCoordinator implements Coordinator { } } + // TODO(b/206118999): merge this class with SensitiveContentCoordinator which also depends on + // these same updates private void setupInvalidateNotifListCallbacks() { // register onKeyguardShowing callback mKeyguardStateController.addCallback(mKeyguardCallback); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinator.kt index a115e0400de3..9c82cb64a0d7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinator.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinator.kt @@ -17,7 +17,10 @@ package com.android.systemui.statusbar.notification.collection.coordinator import android.os.UserHandle +import com.android.keyguard.KeyguardUpdateMonitor +import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.statusbar.NotificationLockscreenUserManager +import com.android.systemui.statusbar.StatusBarState import com.android.systemui.statusbar.notification.DynamicPrivacyController import com.android.systemui.statusbar.notification.collection.GroupEntry import com.android.systemui.statusbar.notification.collection.ListEntry @@ -26,6 +29,7 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Invalidator +import com.android.systemui.statusbar.policy.KeyguardStateController import dagger.Module import dagger.Provides @@ -36,9 +40,13 @@ object SensitiveContentCoordinatorModule { @CoordinatorScope fun provideCoordinator( dynamicPrivacyController: DynamicPrivacyController, - lockscreenUserManager: NotificationLockscreenUserManager + lockscreenUserManager: NotificationLockscreenUserManager, + keyguardUpdateMonitor: KeyguardUpdateMonitor, + statusBarStateController: StatusBarStateController, + keyguardStateController: KeyguardStateController ): SensitiveContentCoordinator = - SensitiveContentCoordinatorImpl(dynamicPrivacyController, lockscreenUserManager) + SensitiveContentCoordinatorImpl(dynamicPrivacyController, lockscreenUserManager, + keyguardUpdateMonitor, statusBarStateController, keyguardStateController) } /** Coordinates re-inflation and post-processing of sensitive notification content. */ @@ -46,7 +54,10 @@ interface SensitiveContentCoordinator : Coordinator private class SensitiveContentCoordinatorImpl( private val dynamicPrivacyController: DynamicPrivacyController, - private val lockscreenUserManager: NotificationLockscreenUserManager + private val lockscreenUserManager: NotificationLockscreenUserManager, + private val keyguardUpdateMonitor: KeyguardUpdateMonitor, + private val statusBarStateController: StatusBarStateController, + private val keyguardStateController: KeyguardStateController ) : Invalidator("SensitiveContentInvalidator"), SensitiveContentCoordinator, DynamicPrivacyController.Listener, @@ -61,6 +72,19 @@ private class SensitiveContentCoordinatorImpl( override fun onDynamicPrivacyChanged(): Unit = invalidateList() override fun onBeforeRenderList(entries: List<ListEntry>) { + if (keyguardStateController.isKeyguardGoingAway() || + statusBarStateController.getState() == StatusBarState.KEYGUARD && + keyguardUpdateMonitor.getUserUnlockedWithBiometricAndIsBypassing( + KeyguardUpdateMonitor.getCurrentUser())) { + // don't update yet if: + // - the keyguard is currently going away + // - LS is about to be dismissed by a biometric that bypasses LS (avoid notif flash) + + // TODO(b/206118999): merge this class with KeyguardCoordinator which ensures the + // dependent state changes invalidate the pipeline + return + } + val currentUserId = lockscreenUserManager.currentUserId val devicePublic = lockscreenUserManager.isLockscreenPublicMode(currentUserId) val deviceSensitive = devicePublic && diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java index 98b5dcc25730..2df56bfa3909 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java @@ -405,7 +405,6 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp // During wake and unlock, we need to draw black before waking up to avoid abrupt // brightness changes due to display state transitions. boolean alwaysOnEnabled = mDozeParameters.getAlwaysOn(); - boolean delayWakeUp = mode == MODE_WAKE_AND_UNLOCK && alwaysOnEnabled && mWakeUpDelay > 0; Runnable wakeUp = ()-> { if (!wasDeviceInteractive) { if (DEBUG_BIO_WAKELOCK) { @@ -414,15 +413,12 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp mPowerManager.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE, "android.policy:BIOMETRIC"); } - if (delayWakeUp) { - mKeyguardViewMediator.onWakeAndUnlocking(); - } Trace.beginSection("release wake-and-unlock"); releaseBiometricWakeLock(); Trace.endSection(); }; - if (!delayWakeUp && mMode != MODE_NONE) { + if (mMode != MODE_NONE) { wakeUp.run(); } switch (mMode) { @@ -472,11 +468,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp mUpdateMonitor.awakenFromDream(); } mNotificationShadeWindowController.setNotificationShadeFocusable(false); - if (delayWakeUp) { - mHandler.postDelayed(wakeUp, mWakeUpDelay); - } else { - mKeyguardViewMediator.onWakeAndUnlocking(); - } + mKeyguardViewMediator.onWakeAndUnlocking(); Trace.endSection(); break; case MODE_ONLY_WAKE: diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java index 810b95b231e5..32aa899eff23 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarViewController.java @@ -54,7 +54,6 @@ import com.android.systemui.util.ViewController; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.Arrays; -import java.util.Collections; import java.util.List; import javax.inject.Inject; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java index 33c4109b3426..7432fa98051d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java @@ -145,6 +145,7 @@ import com.android.systemui.statusbar.LockscreenShadeTransitionController; import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.NotificationRemoteInputManager; import com.android.systemui.statusbar.NotificationShadeDepthController; +import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.NotificationShelfController; import com.android.systemui.statusbar.PulseExpansionHandler; import com.android.systemui.statusbar.RemoteInputController; @@ -664,7 +665,9 @@ public class NotificationPanelViewController extends PanelViewController { NotificationLockscreenUserManager notificationLockscreenUserManager, NotificationEntryManager notificationEntryManager, KeyguardStateController keyguardStateController, - StatusBarStateController statusBarStateController, DozeLog dozeLog, + StatusBarStateController statusBarStateController, + NotificationShadeWindowController notificationShadeWindowController, + DozeLog dozeLog, DozeParameters dozeParameters, CommandQueue commandQueue, VibratorHelper vibratorHelper, LatencyTracker latencyTracker, PowerManager powerManager, AccessibilityManager accessibilityManager, @DisplayId int displayId, @@ -716,6 +719,7 @@ public class NotificationPanelViewController extends PanelViewController { dozeLog, keyguardStateController, (SysuiStatusBarStateController) statusBarStateController, + notificationShadeWindowController, vibratorHelper, statusBarKeyguardViewManager, latencyTracker, @@ -1293,9 +1297,11 @@ public class NotificationPanelViewController extends PanelViewController { int userSwitcherPreferredY = mStatusBarHeaderHeightKeyguard; boolean bypassEnabled = mKeyguardBypassController.getBypassEnabled(); final boolean hasVisibleNotifications = mNotificationStackScrollLayoutController - .getVisibleNotificationCount() != 0 || mMediaDataManager.hasActiveMedia(); + .getVisibleNotificationCount() != 0 + || mMediaDataManager.hasActiveMediaOrRecommendation(); boolean splitShadeWithActiveMedia = - mShouldUseSplitNotificationShade && mMediaDataManager.hasActiveMedia(); + mShouldUseSplitNotificationShade + && mMediaDataManager.hasActiveMediaOrRecommendation(); if ((hasVisibleNotifications && !mShouldUseSplitNotificationShade) || (splitShadeWithActiveMedia && !mDozing)) { mKeyguardStatusViewController.displayClock(SMALL); @@ -1361,7 +1367,8 @@ public class NotificationPanelViewController extends PanelViewController { private void updateKeyguardStatusViewAlignment(boolean animate) { boolean hasVisibleNotifications = mNotificationStackScrollLayoutController - .getVisibleNotificationCount() != 0 || mMediaDataManager.hasActiveMedia(); + .getVisibleNotificationCount() != 0 + || mMediaDataManager.hasActiveMediaOrRecommendation(); boolean shouldBeCentered = !mShouldUseSplitNotificationShade || !hasVisibleNotifications || mDozing; if (mStatusViewCentered != shouldBeCentered) { @@ -2576,7 +2583,7 @@ public class NotificationPanelViewController extends PanelViewController { float endPosition = 0; if (pxAmount > 0.0f) { if (mNotificationStackScrollLayoutController.getVisibleNotificationCount() == 0 - && !mMediaDataManager.hasActiveMedia()) { + && !mMediaDataManager.hasActiveMediaOrRecommendation()) { // No notifications are visible, let's animate to the height of qs instead if (mQs != null) { // Let's interpolate to the header height instead of the top padding, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java index 030a8951943d..8c76a1bf4f83 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImpl.java @@ -107,6 +107,12 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW private final SysuiColorExtractor mColorExtractor; private final UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController; private float mFaceAuthDisplayBrightness = LayoutParams.BRIGHTNESS_OVERRIDE_NONE; + /** + * Layout params would be aggregated and dispatched all at once if this is > 0. + * + * @see #batchApplyWindowLayoutParams(Runnable) + */ + private int mDeferWindowLayoutParams; @Inject public NotificationShadeWindowControllerImpl(Context context, WindowManager windowManager, @@ -433,6 +439,20 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW } } + private void applyWindowLayoutParams() { + if (mDeferWindowLayoutParams == 0 && mLp != null && mLp.copyFrom(mLpChanged) != 0) { + mWindowManager.updateViewLayout(mNotificationShadeView, mLp); + } + } + + @Override + public void batchApplyWindowLayoutParams(Runnable scope) { + mDeferWindowLayoutParams++; + scope.run(); + mDeferWindowLayoutParams--; + applyWindowLayoutParams(); + } + private void apply(State state) { applyKeyguardFlags(state); applyFocusableFlag(state); @@ -447,9 +467,8 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW applyHasTopUi(state); applyNotTouchable(state); applyStatusBarColorSpaceAgnosticFlag(state); - if (mLp != null && mLp.copyFrom(mLpChanged) != 0) { - mWindowManager.updateViewLayout(mNotificationShadeView, mLp); - } + applyWindowLayoutParams(); + if (mHasTopUi != mHasTopUiChanged) { whitelistIpcs(() -> { try { @@ -722,6 +741,7 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW pw.println(TAG + ":"); pw.println(" mKeyguardMaxRefreshRate=" + mKeyguardMaxRefreshRate); pw.println(" mKeyguardPreferredRefreshRate=" + mKeyguardPreferredRefreshRate); + pw.println(" mDeferWindowLayoutParams=" + mDeferWindowLayoutParams); pw.println(mCurrentState); if (mNotificationShadeView != null && mNotificationShadeView.getViewRootImpl() != null) { mNotificationShadeView.getViewRootImpl().dump(" ", pw); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java index 2bf16fc9e52c..040820e90790 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java @@ -54,6 +54,7 @@ import com.android.systemui.animation.Interpolators; import com.android.systemui.classifier.Classifier; import com.android.systemui.doze.DozeLog; import com.android.systemui.plugins.FalsingManager; +import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.VibratorHelper; @@ -177,6 +178,7 @@ public abstract class PanelViewController { private boolean mExpandLatencyTracking; private final PanelView mView; private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; + private final NotificationShadeWindowController mNotificationShadeWindowController; protected final Resources mResources; protected final KeyguardStateController mKeyguardStateController; protected final SysuiStatusBarStateController mStatusBarStateController; @@ -215,6 +217,7 @@ public abstract class PanelViewController { DozeLog dozeLog, KeyguardStateController keyguardStateController, SysuiStatusBarStateController statusBarStateController, + NotificationShadeWindowController notificationShadeWindowController, VibratorHelper vibratorHelper, StatusBarKeyguardViewManager statusBarKeyguardViewManager, LatencyTracker latencyTracker, @@ -247,6 +250,7 @@ public abstract class PanelViewController { mResources = mView.getResources(); mKeyguardStateController = keyguardStateController; mStatusBarStateController = statusBarStateController; + mNotificationShadeWindowController = notificationShadeWindowController; mFlingAnimationUtils = flingAnimationUtilsBuilder .reset() .setMaxLengthSeconds(0.6f) @@ -743,34 +747,36 @@ public abstract class PanelViewController { if (isNaN(h)) { Log.wtf(TAG, "ExpandedHeight set to NaN"); } - if (mExpandLatencyTracking && h != 0f) { - DejankUtils.postAfterTraversal( - () -> mLatencyTracker.onActionEnd(LatencyTracker.ACTION_EXPAND_PANEL)); - mExpandLatencyTracking = false; - } - float maxPanelHeight = getMaxPanelHeight(); - if (mHeightAnimator == null) { - if (mTracking) { - float overExpansionPixels = Math.max(0, h - maxPanelHeight); - setOverExpansionInternal(overExpansionPixels, true /* isFromGesture */); + mNotificationShadeWindowController.batchApplyWindowLayoutParams(()-> { + if (mExpandLatencyTracking && h != 0f) { + DejankUtils.postAfterTraversal( + () -> mLatencyTracker.onActionEnd(LatencyTracker.ACTION_EXPAND_PANEL)); + mExpandLatencyTracking = false; + } + float maxPanelHeight = getMaxPanelHeight(); + if (mHeightAnimator == null) { + if (mTracking) { + float overExpansionPixels = Math.max(0, h - maxPanelHeight); + setOverExpansionInternal(overExpansionPixels, true /* isFromGesture */); + } + mExpandedHeight = Math.min(h, maxPanelHeight); + } else { + mExpandedHeight = h; } - mExpandedHeight = Math.min(h, maxPanelHeight); - } else { - mExpandedHeight = h; - } - // If we are closing the panel and we are almost there due to a slow decelerating - // interpolator, abort the animation. - if (mExpandedHeight < 1f && mExpandedHeight != 0f && mClosing) { - mExpandedHeight = 0f; - if (mHeightAnimator != null) { - mHeightAnimator.end(); + // If we are closing the panel and we are almost there due to a slow decelerating + // interpolator, abort the animation. + if (mExpandedHeight < 1f && mExpandedHeight != 0f && mClosing) { + mExpandedHeight = 0f; + if (mHeightAnimator != null) { + mHeightAnimator.end(); + } } - } - mExpandedFraction = Math.min(1f, - maxPanelHeight == 0 ? 0 : mExpandedHeight / maxPanelHeight); - onHeightUpdated(mExpandedHeight); - updatePanelExpansionAndVisibility(); + mExpandedFraction = Math.min(1f, + maxPanelHeight == 0 ? 0 : mExpandedHeight / maxPanelHeight); + onHeightUpdated(mExpandedHeight); + updatePanelExpansionAndVisibility(); + }); } /** diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index 33212182cfcf..a6fb317cdfc8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -1351,8 +1351,11 @@ public class StatusBar extends SystemUI implements * keyguard. */ private void dispatchPanelExpansionForKeyguardDismiss(float fraction, boolean trackingTouch) { - // Things that mean we're not dismissing the keyguard, and should ignore this expansion: + // Things that mean we're not swiping to dismiss the keyguard, and should ignore this + // expansion: // - Keyguard isn't even visible. + // - Keyguard is occluded. Expansion changes here are the shade being expanded over the + // occluding activity. // - Keyguard is visible, but can't be dismissed (swiping up will show PIN/password prompt). // - The SIM is locked, you can't swipe to unlock. If the SIM is locked but there is no // device lock set, canDismissLockScreen returns true even though you should not be able @@ -1360,6 +1363,7 @@ public class StatusBar extends SystemUI implements // - QS is expanded and we're swiping - swiping up now will hide QS, not dismiss the // keyguard. if (!isKeyguardShowing() + || mIsOccluded || !mKeyguardStateController.canDismissLockScreen() || mKeyguardViewMediator.isAnySimPinSecure() || (mNotificationPanelViewController.isQsExpanded() && trackingTouch)) { @@ -2957,6 +2961,7 @@ public class StatusBar extends SystemUI implements } public void showKeyguardImpl() { + Trace.beginSection("StatusBar#showKeyguard"); mIsKeyguard = true; if (mKeyguardStateController.isLaunchTransitionFadingAway()) { mNotificationPanelViewController.cancelAnimation(); @@ -2969,6 +2974,7 @@ public class StatusBar extends SystemUI implements mStatusBarStateController.setState(StatusBarState.KEYGUARD); } updatePanelExpansionForKeyguard(); + Trace.endSection(); } private void updatePanelExpansionForKeyguard() { @@ -3557,26 +3563,29 @@ public class StatusBar extends SystemUI implements public void onStartedWakingUp() { String tag = "StatusBar#onStartedWakingUp"; DejankUtils.startDetectingBlockingIpcs(tag); - mDeviceInteractive = true; - mWakeUpCoordinator.setWakingUp(true); - if (!mKeyguardBypassController.getBypassEnabled()) { - mHeadsUpManager.releaseAllImmediately(); - } - updateVisibleToUser(); - updateIsKeyguard(); - mDozeServiceHost.stopDozing(); - // This is intentionally below the stopDozing call above, since it avoids that we're - // unnecessarily animating the wakeUp transition. Animations should only be enabled - // once we fully woke up. - updateRevealEffect(true /* wakingUp */); - updateNotificationPanelTouchState(); - - // If we are waking up during the screen off animation, we should undo making the - // expanded visible (we did that so the LightRevealScrim would be visible). - if (mUnlockedScreenOffAnimationController.isScreenOffLightRevealAnimationPlaying()) { - makeExpandedInvisible(); - } + mNotificationShadeWindowController.batchApplyWindowLayoutParams(()-> { + mDeviceInteractive = true; + mWakeUpCoordinator.setWakingUp(true); + if (!mKeyguardBypassController.getBypassEnabled()) { + mHeadsUpManager.releaseAllImmediately(); + } + updateVisibleToUser(); + updateIsKeyguard(); + mDozeServiceHost.stopDozing(); + // This is intentionally below the stopDozing call above, since it avoids that we're + // unnecessarily animating the wakeUp transition. Animations should only be enabled + // once we fully woke up. + updateRevealEffect(true /* wakingUp */); + updateNotificationPanelTouchState(); + + // If we are waking up during the screen off animation, we should undo making the + // expanded visible (we did that so the LightRevealScrim would be visible). + if (mUnlockedScreenOffAnimationController + .isScreenOffLightRevealAnimationPlaying()) { + makeExpandedInvisible(); + } + }); DejankUtils.stopDetectingBlockingIpcs(tag); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java index 48fe77482340..fd435d45934a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java @@ -47,6 +47,7 @@ import com.android.systemui.statusbar.StatusIconDisplayable; import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.CallIndicatorIconState; import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.MobileIconState; import com.android.systemui.statusbar.phone.StatusBarSignalPolicy.WifiIconState; +import com.android.systemui.util.Assert; import java.util.ArrayList; import java.util.List; @@ -65,6 +66,8 @@ public interface StatusBarIconController { void addIconGroup(IconManager iconManager); /** */ void removeIconGroup(IconManager iconManager); + /** Refresh the state of an IconManager by recreating the views */ + void refreshIconGroup(IconManager iconManager); /** */ void setExternalIcon(String slot); /** */ @@ -242,6 +245,7 @@ public interface StatusBarIconController { protected final int mIconSize; // Whether or not these icons show up in dumpsys protected boolean mShouldLog = false; + private StatusBarIconController mController; // Enables SystemUI demo mode to take effect in this group protected boolean mDemoable = true; @@ -266,13 +270,17 @@ public interface StatusBarIconController { mDemoable = demoable; } + void setController(StatusBarIconController controller) { + mController = controller; + } + public void setBlockList(@Nullable List<String> blockList) { + Assert.isMainThread(); mBlockList.clear(); - if (blockList == null || blockList.isEmpty()) { - return; - } - mBlockList.addAll(blockList); + if (mController != null) { + mController.refreshIconGroup(this); + } } public void setShouldLog(boolean should) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java index 88a7dc7bcd75..d6cf80ec70aa 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java @@ -99,6 +99,7 @@ public class StatusBarIconControllerImpl extends StatusBarIconList implements Tu } } + group.setController(this); mIconGroups.add(group); List<Slot> allSlots = getSlots(); for (int i = 0; i < allSlots.size(); i++) { @@ -114,6 +115,12 @@ public class StatusBarIconControllerImpl extends StatusBarIconList implements Tu } } + @Override + public void refreshIconGroup(IconManager iconManager) { + removeIconGroup(iconManager); + addIconGroup(iconManager); + } + private void refreshIconGroups() { for (int i = mIconGroups.size() - 1; i >= 0; --i) { IconManager group = mIconGroups.get(i); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java index e7889286d195..fe96a5b9979f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java @@ -29,6 +29,7 @@ import android.content.res.ColorStateList; import android.hardware.biometrics.BiometricSourceType; import android.os.Bundle; import android.os.SystemClock; +import android.os.Trace; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; @@ -377,6 +378,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb */ @Override public void show(Bundle options) { + Trace.beginSection("StatusBarKeyguardViewManager#show"); mShowing = true; mNotificationShadeWindowController.setKeyguardShowing(true); mKeyguardStateController.notifyKeyguardState(mShowing, @@ -384,6 +386,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb reset(true /* hideBouncerWhenShowing */); SysUiStatsLog.write(SysUiStatsLog.KEYGUARD_STATE_CHANGED, SysUiStatsLog.KEYGUARD_STATE_CHANGED__STATE__SHOWN); + Trace.endSection(); } /** @@ -722,6 +725,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb @Override public void hide(long startTime, long fadeoutDuration) { + Trace.beginSection("StatusBarKeyguardViewManager#hide"); mShowing = false; mKeyguardStateController.notifyKeyguardState(mShowing, mKeyguardStateController.isOccluded()); @@ -821,6 +825,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb } SysUiStatsLog.write(SysUiStatsLog.KEYGUARD_STATE_CHANGED, SysUiStatsLog.KEYGUARD_STATE_CHANGED__STATE__HIDDEN); + Trace.endSection(); } private boolean needsBypassFading() { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java index 14cca13b396b..8750845e57a8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java @@ -60,6 +60,9 @@ import com.android.systemui.statusbar.policy.BatteryController; import com.android.systemui.statusbar.policy.ConfigurationController; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.tuner.TunerService; +import com.android.systemui.util.settings.SecureSettings; + +import java.util.concurrent.Executor; import javax.inject.Named; @@ -257,7 +260,9 @@ public abstract class StatusBarViewModule { StatusBarStateController statusBarStateController, CommandQueue commandQueue, CollapsedStatusBarFragmentLogger collapsedStatusBarFragmentLogger, - OperatorNameViewController.Factory operatorNameViewControllerFactory + OperatorNameViewController.Factory operatorNameViewControllerFactory, + SecureSettings secureSettings, + @Main Executor mainExecutor ) { return new CollapsedStatusBarFragment(statusBarFragmentComponentFactory, ongoingCallController, @@ -274,6 +279,8 @@ public abstract class StatusBarViewModule { statusBarStateController, commandQueue, collapsedStatusBarFragmentLogger, - operatorNameViewControllerFactory); + operatorNameViewControllerFactory, + secureSettings, + mainExecutor); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java index 2670ed838f2e..2383c3e2199e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragment.java @@ -29,8 +29,10 @@ import android.animation.ValueAnimator; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.Fragment; +import android.database.ContentObserver; import android.os.Bundle; import android.os.Parcelable; +import android.provider.Settings; import android.util.SparseArray; import android.view.LayoutInflater; import android.view.View; @@ -38,8 +40,11 @@ import android.view.ViewGroup; import android.view.ViewStub; import android.widget.LinearLayout; +import androidx.annotation.VisibleForTesting; + import com.android.systemui.R; import com.android.systemui.animation.Interpolators; +import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.flags.FeatureFlags; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.CommandQueue; @@ -65,12 +70,14 @@ import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallListener; import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager; import com.android.systemui.statusbar.policy.EncryptionHelper; import com.android.systemui.statusbar.policy.KeyguardStateController; +import com.android.systemui.util.settings.SecureSettings; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.concurrent.Executor; import javax.inject.Inject; @@ -114,6 +121,8 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue private final PanelExpansionStateManager mPanelExpansionStateManager; private final StatusBarIconController mStatusBarIconController; private final StatusBarHideIconsForBouncerManager mStatusBarHideIconsForBouncerManager; + private final SecureSettings mSecureSettings; + private final Executor mMainExecutor; private List<String> mBlockedIcons = new ArrayList<>(); @@ -149,7 +158,9 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue StatusBarStateController statusBarStateController, CommandQueue commandQueue, CollapsedStatusBarFragmentLogger collapsedStatusBarFragmentLogger, - OperatorNameViewController.Factory operatorNameViewControllerFactory + OperatorNameViewController.Factory operatorNameViewControllerFactory, + SecureSettings secureSettings, + @Main Executor mainExecutor ) { mStatusBarFragmentComponentFactory = statusBarFragmentComponentFactory; mOngoingCallController = ongoingCallController; @@ -167,6 +178,8 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue mCommandQueue = commandQueue; mCollapsedStatusBarFragmentLogger = collapsedStatusBarFragmentLogger; mOperatorNameViewControllerFactory = operatorNameViewControllerFactory; + mSecureSettings = secureSettings; + mMainExecutor = mainExecutor; } @Override @@ -191,9 +204,7 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue } mDarkIconManager = new DarkIconManager(view.findViewById(R.id.statusIcons), mFeatureFlags); mDarkIconManager.setShouldLog(true); - mBlockedIcons = Arrays.asList(getResources().getStringArray( - R.array.config_collapsed_statusbar_icon_blocklist)); - mDarkIconManager.setBlockList(mBlockedIcons); + updateBlockedIcons(); mStatusBarIconController.addIconGroup(mDarkIconManager); mSystemIconArea = mStatusBar.findViewById(R.id.system_icon_area); mClockView = mStatusBar.findViewById(R.id.clock); @@ -206,6 +217,36 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue mAnimationScheduler.addCallback(this); } + @VisibleForTesting + void updateBlockedIcons() { + mBlockedIcons.clear(); + + // Reload the blocklist from res + List<String> blockList = Arrays.asList(getResources().getStringArray( + R.array.config_collapsed_statusbar_icon_blocklist)); + String vibrateIconSlot = getString(com.android.internal.R.string.status_bar_volume); + boolean showVibrateIcon = + mSecureSettings.getInt(Settings.Secure.STATUS_BAR_SHOW_VIBRATE_ICON, 0) == 0; + + // Filter out vibrate icon from the blocklist if the setting is on + for (int i = 0; i < blockList.size(); i++) { + if (blockList.get(i).equals(vibrateIconSlot)) { + if (showVibrateIcon) { + mBlockedIcons.add(blockList.get(i)); + } + } else { + mBlockedIcons.add(blockList.get(i)); + } + } + + mMainExecutor.execute(() -> mDarkIconManager.setBlockList(mBlockedIcons)); + } + + @VisibleForTesting + List<String> getBlockedIcons() { + return mBlockedIcons; + } + @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); @@ -220,6 +261,11 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue mCommandQueue.addCallback(this); mStatusBarStateController.addCallback(this); initOngoingCallChip(); + + mSecureSettings.registerContentObserver( + Settings.Secure.getUriFor(Settings.Secure.STATUS_BAR_SHOW_VIBRATE_ICON), + false, + mVolumeSettingObserver); } @Override @@ -228,6 +274,7 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue mCommandQueue.removeCallback(this); mStatusBarStateController.removeCallback(this); mOngoingCallController.removeCallback(mOngoingCallListener); + mSecureSettings.unregisterContentObserver(mVolumeSettingObserver); } @Override @@ -597,6 +644,13 @@ public class CollapsedStatusBarFragment extends Fragment implements CommandQueue mLocationPublisher.updateStatusBarMargin(leftMargin, rightMargin); } + private final ContentObserver mVolumeSettingObserver = new ContentObserver(null) { + @Override + public void onChange(boolean selfChange) { + updateBlockedIcons(); + } + }; + // Listen for view end changes of PhoneStatusBarView and publish that to the privacy dot private View.OnLayoutChangeListener mStatusBarLayoutListener = (view, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> { diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbAudioWarningDialogMessage.java b/packages/SystemUI/src/com/android/systemui/usb/UsbAudioWarningDialogMessage.java new file mode 100644 index 000000000000..df845e53a36b --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/usb/UsbAudioWarningDialogMessage.java @@ -0,0 +1,119 @@ +/* + * 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.systemui.usb; + +import static java.lang.annotation.RetentionPolicy.SOURCE; + +import android.annotation.IntDef; +import android.content.Context; +import android.content.Intent; +import android.content.res.Resources; +import android.util.Log; + +import com.android.systemui.R; + +import java.lang.annotation.Retention; + +/** + * USB Audio devices warning dialog messages help class. + */ +public class UsbAudioWarningDialogMessage { + private static final String TAG = "UsbAudioWarningDialogMessage"; + + @Retention(SOURCE) + @IntDef({TYPE_PERMISSION, TYPE_CONFIRM}) + public @interface DialogType {} + public static final int TYPE_PERMISSION = 0; + public static final int TYPE_CONFIRM = 1; + + private final int mDialogType; + private UsbDialogHelper mDialogHelper; + + public UsbAudioWarningDialogMessage(Context context, Intent intent, @DialogType int type) { + mDialogType = type; + try { + mDialogHelper = new UsbDialogHelper(context, intent); + } catch (IllegalStateException e) { + Log.e(TAG, "Unable to initialize UsbDialogHelper!", e); + } + } + + private boolean hasRecordPermission() { + return mDialogHelper.packageHasAudioRecordingPermission(); + } + + private boolean isUsbAudioDevice() { + return mDialogHelper.isUsbDevice() && (mDialogHelper.deviceHasAudioCapture() + || (mDialogHelper.deviceHasAudioPlayback())); + } + + private boolean hasAudioPlayback() { + return mDialogHelper.deviceHasAudioPlayback(); + } + + private boolean hasAudioCapture() { + return mDialogHelper.deviceHasAudioCapture(); + } + + /** + * According to USB audio warning dialog matrix table to return warning message id. + * @return string resId for USB audio warning dialog message, otherwise {ID_NULL}. + * See usb_audio.md for USB audio Permission and Confirmation warning dialog resource + * string id matrix table. + */ + public int getMessageId() { + if (!mDialogHelper.isUsbDevice()) { + return getUsbAccessoryPromptId(); + } + + if (hasRecordPermission() && isUsbAudioDevice()) { + // case# 1, 2, 3 + return R.string.usb_audio_device_prompt; + } else if (!hasRecordPermission() && isUsbAudioDevice() && hasAudioPlayback() + && !hasAudioCapture()) { + // case# 5 + return R.string.usb_audio_device_prompt; + } + + if (!hasRecordPermission() && isUsbAudioDevice() && hasAudioCapture()) { + // case# 6,7 + return R.string.usb_audio_device_prompt_warn; + } + + Log.w(TAG, "Only shows title with empty content description!"); + return Resources.ID_NULL; + } + + /** + * Gets prompt dialog title. + * @return string id for USB prompt dialog title. + */ + public int getPromptTitleId() { + return (mDialogType == TYPE_PERMISSION) + ? R.string.usb_audio_device_permission_prompt_title + : R.string.usb_audio_device_confirm_prompt_title; + } + + /** + * Gets USB Accessory prompt message id. + * @return string id for USB Accessory prompt message. + */ + public int getUsbAccessoryPromptId() { + return (mDialogType == TYPE_PERMISSION) + ? R.string.usb_accessory_permission_prompt : R.string.usb_accessory_confirm_prompt; + } +} diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbConfirmActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbConfirmActivity.java index 21d700e41a40..a2bee05246ce 100644 --- a/packages/SystemUI/src/com/android/systemui/usb/UsbConfirmActivity.java +++ b/packages/SystemUI/src/com/android/systemui/usb/UsbConfirmActivity.java @@ -24,6 +24,7 @@ import android.content.Intent; import android.content.PermissionChecker; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; +import android.content.res.Resources; import android.hardware.usb.IUsbManager; import android.hardware.usb.UsbAccessory; import android.hardware.usb.UsbDevice; @@ -35,7 +36,6 @@ import android.os.UserHandle; import android.util.Log; import android.view.LayoutInflater; import android.view.View; -import android.view.Window; import android.view.WindowManager; import android.widget.CheckBox; import android.widget.CompoundButton; @@ -57,6 +57,7 @@ public class UsbConfirmActivity extends AlertActivity private ResolveInfo mResolveInfo; private boolean mPermissionGranted; private UsbDisconnectedReceiver mDisconnectedReceiver; + private UsbAudioWarningDialogMessage mUsbConfirmMessageHandler; @Override public void onCreate(Bundle icicle) { @@ -70,7 +71,9 @@ public class UsbConfirmActivity extends AlertActivity mAccessory = (UsbAccessory)intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY); mResolveInfo = (ResolveInfo) intent.getParcelableExtra("rinfo"); String packageName = intent.getStringExtra(UsbManager.EXTRA_PACKAGE); - + mUsbConfirmMessageHandler = new UsbAudioWarningDialogMessage( + getApplicationContext(), getIntent(), + UsbAudioWarningDialogMessage.TYPE_CONFIRM); PackageManager packageManager = getPackageManager(); String appName = mResolveInfo.loadLabel(packageManager).toString(); @@ -78,8 +81,8 @@ public class UsbConfirmActivity extends AlertActivity ap.mTitle = appName; boolean useRecordWarning = false; if (mDevice == null) { - ap.mMessage = getString(R.string.usb_accessory_confirm_prompt, appName, - mAccessory.getDescription()); + final int messageId = mUsbConfirmMessageHandler.getUsbAccessoryPromptId(); + ap.mMessage = getString(messageId, appName, mAccessory.getDescription()); mDisconnectedReceiver = new UsbDisconnectedReceiver(this, mAccessory); } else { int uid = intent.getIntExtra(Intent.EXTRA_UID, -1); @@ -91,11 +94,11 @@ public class UsbConfirmActivity extends AlertActivity boolean isAudioCaptureDevice = mDevice.getHasAudioCapture(); useRecordWarning = isAudioCaptureDevice && !hasRecordPermission; - int strID = useRecordWarning - ? R.string.usb_device_confirm_prompt_warn - : R.string.usb_device_confirm_prompt; - - ap.mMessage = getString(strID, appName, mDevice.getProductName()); + final int messageId = mUsbConfirmMessageHandler.getMessageId(); + final int titleId = mUsbConfirmMessageHandler.getPromptTitleId(); + ap.mTitle = getString(titleId, appName, mDevice.getProductName()); + ap.mMessage = (messageId != Resources.ID_NULL) ? getString(messageId, appName, + mDevice.getProductName()) : null; mDisconnectedReceiver = new UsbDisconnectedReceiver(this, mDevice); } ap.mPositiveButtonText = getString(android.R.string.ok); diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbDialogHelper.java b/packages/SystemUI/src/com/android/systemui/usb/UsbDialogHelper.java new file mode 100644 index 000000000000..ab29a9e970c7 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/usb/UsbDialogHelper.java @@ -0,0 +1,303 @@ +/* + * 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.systemui.usb; + +import static android.Manifest.permission.RECORD_AUDIO; + +import android.app.Activity; +import android.app.PendingIntent; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.PermissionChecker; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; +import android.hardware.usb.IUsbManager; +import android.hardware.usb.UsbAccessory; +import android.hardware.usb.UsbDevice; +import android.hardware.usb.UsbManager; +import android.os.IBinder; +import android.os.RemoteException; +import android.os.ServiceManager; +import android.os.UserHandle; +import android.util.Log; + +/** + * Helper class to separate model and view for USB permission and confirm dialogs. + */ +public class UsbDialogHelper { + private static final String TAG = UsbDialogHelper.class.getSimpleName(); + private static final String EXTRA_RESOLVE_INFO = "rinfo"; + + private final UsbDevice mDevice; + private final UsbAccessory mAccessory; + private final ResolveInfo mResolveInfo; + private final String mPackageName; + private final CharSequence mAppName; + private final Context mContext; + private final PendingIntent mPendingIntent; + private final IUsbManager mUsbService; + private final int mUid; + private final boolean mCanBeDefault; + + private UsbDisconnectedReceiver mDisconnectedReceiver; + private boolean mIsUsbDevice; + private boolean mResponseSent; + + /** + * @param context The Context of the caller. + * @param intent The intent of the caller. + * @throws IllegalStateException Thrown if both UsbDevice and UsbAccessory are null or if the + * query for the matching ApplicationInfo is unsuccessful. + */ + public UsbDialogHelper(Context context, Intent intent) throws IllegalStateException { + mContext = context; + mDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); + mAccessory = intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY); + mCanBeDefault = intent.getBooleanExtra(UsbManager.EXTRA_CAN_BE_DEFAULT, false); + if (mDevice == null && mAccessory == null) { + throw new IllegalStateException("Device and accessory are both null."); + } + if (mDevice != null) { + mIsUsbDevice = true; + } + mResolveInfo = intent.getParcelableExtra(EXTRA_RESOLVE_INFO); + PackageManager packageManager = mContext.getPackageManager(); + if (mResolveInfo != null) { + // If a ResolveInfo is provided it will be used to determine the activity to start + mUid = mResolveInfo.activityInfo.applicationInfo.uid; + mPackageName = mResolveInfo.activityInfo.packageName; + mPendingIntent = null; + } else { + mUid = intent.getIntExtra(Intent.EXTRA_UID, -1); + mPackageName = intent.getStringExtra(UsbManager.EXTRA_PACKAGE); + mPendingIntent = intent.getParcelableExtra(Intent.EXTRA_INTENT); + } + try { + ApplicationInfo aInfo = packageManager.getApplicationInfo(mPackageName, 0); + mAppName = aInfo.loadLabel(packageManager); + } catch (PackageManager.NameNotFoundException e) { + throw new IllegalStateException("unable to look up package name", e); + } + IBinder b = ServiceManager.getService(Context.USB_SERVICE); + mUsbService = IUsbManager.Stub.asInterface(b); + } + + /** + * Registers UsbDisconnectedReceiver to dismiss dialog automatically when device or accessory + * gets disconnected + * @param activity The activity to finish when device / accessory gets disconnected. + */ + public void registerUsbDisconnectedReceiver(Activity activity) { + if (mIsUsbDevice) { + mDisconnectedReceiver = new UsbDisconnectedReceiver(activity, mDevice); + } else { + mDisconnectedReceiver = new UsbDisconnectedReceiver(activity, mAccessory); + } + } + + /** + * Unregisters the UsbDisconnectedReceiver. To be called when the activity is destroyed. + * @param activity The activity registered to finish when device / accessory gets disconnected. + */ + public void unregisterUsbDisconnectedReceiver(Activity activity) { + if (mDisconnectedReceiver != null) { + try { + activity.unregisterReceiver(mDisconnectedReceiver); + } catch (Exception e) { + // pass + } + mDisconnectedReceiver = null; + } + } + + /** + * @return True if the intent contains a UsbDevice which can capture audio. + */ + public boolean deviceHasAudioCapture() { + return mDevice != null && mDevice.getHasAudioCapture(); + } + + /** + * @return True if the intent contains a UsbDevice which can play audio. + */ + public boolean deviceHasAudioPlayback() { + return mDevice != null && mDevice.getHasAudioPlayback(); + } + + /** + * @return True if the package has RECORD_AUDIO permission specified in its manifest. + */ + public boolean packageHasAudioRecordingPermission() { + return PermissionChecker.checkPermissionForPreflight(mContext, RECORD_AUDIO, + PermissionChecker.PID_UNKNOWN, mUid, mPackageName) + == android.content.pm.PackageManager.PERMISSION_GRANTED; + } + + /** + * @return True if the intent contains a UsbDevice. + */ + public boolean isUsbDevice() { + return mIsUsbDevice; + } + + /** + * @return True if the intent contains a UsbAccessory. + */ + public boolean isUsbAccessory() { + return !mIsUsbDevice; + } + + /** + * Grants USB permission to the device / accessory to the calling uid. + */ + public void grantUidAccessPermission() { + try { + if (mIsUsbDevice) { + mUsbService.grantDevicePermission(mDevice, mUid); + } else { + mUsbService.grantAccessoryPermission(mAccessory, mUid); + } + } catch (RemoteException e) { + Log.e(TAG, "IUsbService connection failed", e); + } + } + + /** + * Sets the package as default for the device / accessory. + */ + public void setDefaultPackage() { + final int userId = UserHandle.myUserId(); + try { + if (mIsUsbDevice) { + mUsbService.setDevicePackage(mDevice, mPackageName, userId); + } else { + mUsbService.setAccessoryPackage(mAccessory, mPackageName, userId); + } + } catch (RemoteException e) { + Log.e(TAG, "IUsbService connection failed", e); + } + } + + /** + * Clears the default package of the device / accessory. + */ + public void clearDefaultPackage() { + final int userId = UserHandle.myUserId(); + try { + if (mIsUsbDevice) { + mUsbService.setDevicePackage(mDevice, null, userId); + } else { + mUsbService.setAccessoryPackage(mAccessory, null, userId); + } + } catch (RemoteException e) { + Log.e(TAG, "IUsbService connection failed", e); + } + } + + /** + * Starts the activity which was selected to handle the device / accessory. + */ + public void confirmDialogStartActivity() { + final int userId = UserHandle.myUserId(); + Intent intent; + + if (mIsUsbDevice) { + intent = new Intent(UsbManager.ACTION_USB_DEVICE_ATTACHED); + intent.putExtra(UsbManager.EXTRA_DEVICE, mDevice); + } else { + intent = new Intent(UsbManager.ACTION_USB_ACCESSORY_ATTACHED); + intent.putExtra(UsbManager.EXTRA_ACCESSORY, mAccessory); + } + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.setComponent( + new ComponentName(mResolveInfo.activityInfo.packageName, + mResolveInfo.activityInfo.name)); + try { + mContext.startActivityAsUser(intent, new UserHandle(userId)); + } catch (Exception e) { + Log.e(TAG, "Unable to start activity", e); + } + } + + /** + * Sends the result of the permission dialog via the provided PendingIntent. + * + * @param permissionGranted True if the user pressed ok in the permission dialog. + */ + public void sendPermissionDialogResponse(boolean permissionGranted) { + if (!mResponseSent) { + // send response via pending intent + Intent intent = new Intent(); + if (mIsUsbDevice) { + intent.putExtra(UsbManager.EXTRA_DEVICE, mDevice); + } else { + intent.putExtra(UsbManager.EXTRA_ACCESSORY, mAccessory); + } + intent.putExtra(UsbManager.EXTRA_PERMISSION_GRANTED, permissionGranted); + try { + mPendingIntent.send(mContext, 0, intent); + mResponseSent = true; + } catch (PendingIntent.CanceledException e) { + Log.w(TAG, "PendingIntent was cancelled"); + } + } + } + + /** + * @return A description of the device / accessory + */ + public String getDeviceDescription() { + String desc; + if (mIsUsbDevice) { + desc = mDevice.getProductName(); + if (desc == null) { + desc = mDevice.getDeviceName(); + } + } else { + // UsbAccessory + desc = mAccessory.getDescription(); + if (desc == null) { + desc = String.format("%s %s", mAccessory.getManufacturer(), mAccessory.getModel()); + } + } + return desc; + } + + /** + * Whether the calling package can set as default handler of the USB device or accessory. + * In case of a UsbAccessory this is the case if the calling package has an intent filter for + * {@link UsbManager#ACTION_USB_ACCESSORY_ATTACHED} with a usb-accessory filter matching the + * attached accessory. In case of a UsbDevice this is the case if the calling package has an + * intent filter for {@link UsbManager#ACTION_USB_DEVICE_ATTACHED} with a usb-device filter + * matching the attached device. + * + * @return True if the package can be default for the USB device. + */ + public boolean canBeDefault() { + return mCanBeDefault; + } + + /** + * @return The name of the app which requested permission or the name of the app which will be + * opened if the user allows it to handle the USB device. + */ + public CharSequence getAppName() { + return mAppName; + } +} diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java index bfa50bcee270..b9a37b1918f2 100644 --- a/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java +++ b/packages/SystemUI/src/com/android/systemui/usb/UsbPermissionActivity.java @@ -24,6 +24,7 @@ import android.content.Intent; import android.content.PermissionChecker; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; +import android.content.res.Resources; import android.hardware.usb.IUsbManager; import android.hardware.usb.UsbAccessory; import android.hardware.usb.UsbDevice; @@ -59,6 +60,7 @@ public class UsbPermissionActivity extends AlertActivity private int mUid; private boolean mPermissionGranted; private UsbDisconnectedReceiver mDisconnectedReceiver; + private UsbAudioWarningDialogMessage mUsbAudioPermissionMessageHandler; @Override public void onCreate(Bundle icicle) { @@ -73,7 +75,9 @@ public class UsbPermissionActivity extends AlertActivity mUid = intent.getIntExtra(Intent.EXTRA_UID, -1); mPackageName = intent.getStringExtra(UsbManager.EXTRA_PACKAGE); boolean canBeDefault = intent.getBooleanExtra(UsbManager.EXTRA_CAN_BE_DEFAULT, false); - + mUsbAudioPermissionMessageHandler = new UsbAudioWarningDialogMessage( + getApplicationContext(), getIntent(), + UsbAudioWarningDialogMessage.TYPE_PERMISSION); PackageManager packageManager = getPackageManager(); ApplicationInfo aInfo; try { @@ -91,8 +95,8 @@ public class UsbPermissionActivity extends AlertActivity if (mDevice == null) { // Accessory Case - ap.mMessage = getString(R.string.usb_accessory_permission_prompt, appName, - mAccessory.getDescription()); + final int messageId = mUsbAudioPermissionMessageHandler.getUsbAccessoryPromptId(); + ap.mMessage = getString(messageId, appName, mAccessory.getDescription()); mDisconnectedReceiver = new UsbDisconnectedReceiver(this, mAccessory); } else { boolean hasRecordPermission = @@ -103,10 +107,11 @@ public class UsbPermissionActivity extends AlertActivity boolean isAudioCaptureDevice = mDevice.getHasAudioCapture(); useRecordWarning = isAudioCaptureDevice && !hasRecordPermission; - int strID = useRecordWarning - ? R.string.usb_device_permission_prompt_warn - : R.string.usb_device_permission_prompt; - ap.mMessage = getString(strID, appName, mDevice.getProductName()); + final int messageId = mUsbAudioPermissionMessageHandler.getMessageId(); + final int titleId = mUsbAudioPermissionMessageHandler.getPromptTitleId(); + ap.mTitle = getString(titleId, appName, mDevice.getProductName()); + ap.mMessage = (messageId != Resources.ID_NULL) ? getString(messageId, appName, + mDevice.getProductName()) : null; mDisconnectedReceiver = new UsbDisconnectedReceiver(this, mDevice); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/BiometricDisplayListenerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/BiometricDisplayListenerTest.java new file mode 100644 index 000000000000..40f335dfc20d --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/BiometricDisplayListenerTest.java @@ -0,0 +1,193 @@ +/* + * 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.systemui.biometrics; + +import static com.android.systemui.biometrics.BiometricDisplayListener.SensorType.SideFingerprint; +import static com.android.systemui.biometrics.BiometricDisplayListener.SensorType.UnderDisplayFingerprint; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.same; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.reset; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.hardware.display.DisplayManager; +import android.os.Handler; +import android.testing.AndroidTestingRunner; +import android.testing.TestableLooper; +import android.testing.TestableLooper.RunWithLooper; +import android.view.Display; +import android.view.Surface; +import android.view.Surface.Rotation; + +import androidx.test.filters.SmallTest; + +import com.android.systemui.SysuiTestCase; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import kotlin.Unit; +import kotlin.jvm.functions.Function0; + +@SmallTest +@RunWith(AndroidTestingRunner.class) +@RunWithLooper(setAsMainLooper = true) +public class BiometricDisplayListenerTest extends SysuiTestCase { + + // Dependencies + @Mock private DisplayManager mDisplayManager; + @Mock private Display mDisplay; + @Mock private Function0<Unit> mOnChangedCallback; + @Mock private UnderDisplayFingerprint mUdfpsType; + @Mock private SideFingerprint mSidefpsType; + private Handler mHandler; + private Context mContextSpy; + + // Captors + @Captor private ArgumentCaptor<DisplayManager.DisplayListener> mDisplayListenerCaptor; + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + + // Set up mocks + mContextSpy = spy(mContext); + when(mContextSpy.getDisplay()).thenReturn(mDisplay); + + // Create a real handler with a TestableLooper. + TestableLooper testableLooper = TestableLooper.get(this); + mHandler = new Handler(testableLooper.getLooper()); + } + + @Test + public void registersDisplayListener_whenEnabled() { + BiometricDisplayListener listener = new BiometricDisplayListener( + mContextSpy, mDisplayManager, mHandler, mUdfpsType, mOnChangedCallback); + + listener.enable(); + verify(mDisplayManager).registerDisplayListener(any(), same(mHandler)); + } + + @Test + public void unregistersDisplayListener_whenDisabled() { + BiometricDisplayListener listener = new BiometricDisplayListener( + mContextSpy, mDisplayManager, mHandler, mUdfpsType, mOnChangedCallback); + + listener.enable(); + listener.disable(); + verify(mDisplayManager).unregisterDisplayListener(any()); + } + + @Test + public void detectsRotationChanges_forUdfps_relativeToRotationWhenEnabled() { + // Create a listener when the rotation is portrait. + when(mDisplay.getRotation()).thenReturn(Surface.ROTATION_0); + BiometricDisplayListener listener = new BiometricDisplayListener( + mContextSpy, mDisplayManager, mHandler, mUdfpsType, mOnChangedCallback); + + // Rotate the device to landscape and then enable the listener. + when(mDisplay.getRotation()).thenReturn(Surface.ROTATION_90); + listener.enable(); + verify(mDisplayManager).registerDisplayListener(mDisplayListenerCaptor.capture(), + same(mHandler)); + + // Rotate the device back to portrait and ensure the rotation is detected. + when(mDisplay.getRotation()).thenReturn(Surface.ROTATION_0); + mDisplayListenerCaptor.getValue().onDisplayChanged(999); + verify(mOnChangedCallback).invoke(); + } + + @Test + public void callsOnChanged_forUdfps_onlyWhenRotationChanges() { + final @Rotation int[] rotations = + new int[]{ + Surface.ROTATION_0, + Surface.ROTATION_90, + Surface.ROTATION_180, + Surface.ROTATION_270 + }; + + for (@Rotation int rot1 : rotations) { + for (@Rotation int rot2 : rotations) { + // Make the third rotation the same as the first one to simplify this test. + @Rotation int rot3 = rot1; + + // Clean up prior interactions. + reset(mDisplayManager); + reset(mDisplay); + reset(mOnChangedCallback); + + // Set up the mock for 3 invocations. + when(mDisplay.getRotation()).thenReturn(rot1, rot2, rot3); + + BiometricDisplayListener listener = new BiometricDisplayListener( + mContextSpy, mDisplayManager, mHandler, mUdfpsType, mOnChangedCallback); + listener.enable(); + + // The listener should record the current rotation and register a display listener. + verify(mDisplay).getRotation(); + verify(mDisplayManager) + .registerDisplayListener(mDisplayListenerCaptor.capture(), same(mHandler)); + + // Test the first rotation since the listener was enabled. + mDisplayListenerCaptor.getValue().onDisplayChanged(123); + if (rot2 != rot1) { + verify(mOnChangedCallback).invoke(); + } else { + verify(mOnChangedCallback, never()).invoke(); + } + + // Test continued rotations. + mDisplayListenerCaptor.getValue().onDisplayChanged(123); + if (rot3 != rot2) { + verify(mOnChangedCallback, times(2)).invoke(); + } else { + verify(mOnChangedCallback, never()).invoke(); + } + } + } + } + + @Test + public void callsOnChanged_forSideFingerprint_whenAnythingDisplayChanges() { + // Any rotation will do for this test, we just need to return something. + when(mDisplay.getRotation()).thenReturn(Surface.ROTATION_0); + + BiometricDisplayListener listener = new BiometricDisplayListener( + mContextSpy, mDisplayManager, mHandler, mSidefpsType, mOnChangedCallback); + listener.enable(); + + // The listener should register a display listener. + verify(mDisplayManager) + .registerDisplayListener(mDisplayListenerCaptor.capture(), same(mHandler)); + + // mOnChangedCallback should be invoked for all calls to onDisplayChanged. + mDisplayListenerCaptor.getValue().onDisplayChanged(123); + mDisplayListenerCaptor.getValue().onDisplayChanged(123); + verify(mOnChangedCallback, times(2)).invoke(); + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java index 8078b6c8bda4..56844292ce4a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeMachineTest.java @@ -42,12 +42,14 @@ import static org.mockito.Mockito.when; import android.hardware.display.AmbientDisplayConfiguration; import android.testing.AndroidTestingRunner; import android.testing.UiThreadTest; +import android.view.Display; import androidx.test.filters.SmallTest; import com.android.systemui.SysuiTestCase; import com.android.systemui.dock.DockManager; import com.android.systemui.keyguard.WakefulnessLifecycle; +import com.android.systemui.statusbar.phone.DozeParameters; import com.android.systemui.statusbar.policy.BatteryController; import com.android.systemui.util.wakelock.WakeLockFake; @@ -444,4 +446,20 @@ public class DozeMachineTest extends SysuiTestCase { assertTrue(mServiceFake.requestedWakeup); } + + @Test + public void testDozePulsing_displayRequiresBlanking_screenState() { + DozeParameters dozeParameters = mock(DozeParameters.class); + when(dozeParameters.getDisplayNeedsBlanking()).thenReturn(true); + + assertEquals(Display.STATE_OFF, DOZE_REQUEST_PULSE.screenState(dozeParameters)); + } + + @Test + public void testDozePulsing_displayDoesNotRequireBlanking_screenState() { + DozeParameters dozeParameters = mock(DozeParameters.class); + when(dozeParameters.getDisplayNeedsBlanking()).thenReturn(false); + + assertEquals(Display.STATE_ON, DOZE_REQUEST_PULSE.screenState(dozeParameters)); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java index 3e19cc436dca..992a82b6e7fe 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java @@ -35,6 +35,7 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Matchers.anyObject; import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.verify; @@ -306,4 +307,11 @@ public class DozeScreenStateTest extends SysuiTestCase { // THEN the display screen state will change assertEquals(Display.STATE_DOZE_SUSPEND, mServiceFake.screenState); } + + @Test + public void authCallbackRemovedOnDestroy() { + mScreen.destroy(); + + verify(mAuthController).removeCallback(anyObject()); + } }
\ No newline at end of file diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java index 6d8645e44fb0..086cb1ab68fb 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java @@ -51,6 +51,7 @@ import com.android.systemui.classifier.FalsingCollectorFake; import com.android.systemui.dump.DumpManager; import com.android.systemui.navigationbar.NavigationModeController; import com.android.systemui.statusbar.NotificationShadeDepthController; +import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.phone.DozeParameters; import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager; @@ -64,9 +65,6 @@ import com.android.systemui.util.DeviceConfigProxyFake; import com.android.systemui.util.concurrency.FakeExecutor; import com.android.systemui.util.time.FakeSystemClock; -import java.util.Optional; -import java.util.function.Function; - import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -75,6 +73,11 @@ import org.mockito.ArgumentMatchers; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import java.util.Optional; +import java.util.function.Function; + +import dagger.Lazy; + @RunWith(AndroidTestingRunner.class) @TestableLooper.RunWithLooper @SmallTest @@ -103,6 +106,7 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { private @Mock KeyguardUnlockAnimationController mKeyguardUnlockAnimationController; private @Mock UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController; private @Mock IKeyguardDrawnCallback mKeyguardDrawnCallback; + private @Mock Lazy<NotificationShadeWindowController> mNotificationShadeWindowControllerLazy; private DeviceConfigProxy mDeviceConfig = new DeviceConfigProxyFake(); private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock()); @@ -144,7 +148,8 @@ public class KeyguardViewMediatorTest extends SysuiTestCase { mKeyguardStateController, () -> mKeyguardUnlockAnimationController, mUnlockedScreenOffAnimationController, - () -> mNotificationShadeDepthController); + () -> mNotificationShadeDepthController, + mNotificationShadeWindowControllerLazy); mViewMediator.start(); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt index a6e567ea8b5a..36e83704f7cf 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt @@ -156,7 +156,7 @@ class MediaCarouselControllerTest : SysuiTestCase() { expected.forEach { clock.setCurrentTimeMillis(it.third) MediaPlayerData.addMediaPlayer(it.first, it.second.copy(notificationKey = it.first), - panel, clock) + panel, clock, isSsReactivated = false) } for ((index, key) in MediaPlayerData.playerKeys().withIndex()) { diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataCombineLatestTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataCombineLatestTest.java index 09c83e566ee8..06fa28887e0a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataCombineLatestTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataCombineLatestTest.java @@ -84,10 +84,10 @@ public class MediaDataCombineLatestTest extends SysuiTestCase { public void eventNotEmittedWithoutDevice() { // WHEN data source emits an event without device data mManager.onMediaDataLoaded(KEY, null, mMediaData, true /* immediately */, - 0 /* receivedSmartspaceCardLatency */); + 0 /* receivedSmartspaceCardLatency */, false /* isSsReactivated */); // THEN an event isn't emitted verify(mListener, never()).onMediaDataLoaded(eq(KEY), any(), any(), anyBoolean(), - anyInt()); + anyInt(), anyBoolean()); } @Test @@ -96,7 +96,7 @@ public class MediaDataCombineLatestTest extends SysuiTestCase { mManager.onMediaDeviceChanged(KEY, null, mDeviceData); // THEN an event isn't emitted verify(mListener, never()).onMediaDataLoaded(eq(KEY), any(), any(), anyBoolean(), - anyInt()); + anyInt(), anyBoolean()); } @Test @@ -105,11 +105,11 @@ public class MediaDataCombineLatestTest extends SysuiTestCase { mManager.onMediaDeviceChanged(KEY, null, mDeviceData); // WHEN media event is received mManager.onMediaDataLoaded(KEY, null, mMediaData, true /* immediately */, - 0 /* receivedSmartspaceCardLatency */); + 0 /* receivedSmartspaceCardLatency */, false /* isSsReactivated */); // THEN the listener receives a combined event ArgumentCaptor<MediaData> captor = ArgumentCaptor.forClass(MediaData.class); verify(mListener).onMediaDataLoaded(eq(KEY), any(), captor.capture(), anyBoolean(), - anyInt()); + anyInt(), anyBoolean()); assertThat(captor.getValue().getDevice()).isNotNull(); } @@ -117,13 +117,13 @@ public class MediaDataCombineLatestTest extends SysuiTestCase { public void emitEventAfterMediaFirst() { // GIVEN that media event has already been received mManager.onMediaDataLoaded(KEY, null, mMediaData, true /* immediately */, - 0 /* receivedSmartspaceCardLatency */); + 0 /* receivedSmartspaceCardLatency */, false /* isSsReactivated */); // WHEN device event is received mManager.onMediaDeviceChanged(KEY, null, mDeviceData); // THEN the listener receives a combined event ArgumentCaptor<MediaData> captor = ArgumentCaptor.forClass(MediaData.class); verify(mListener).onMediaDataLoaded(eq(KEY), any(), captor.capture(), anyBoolean(), - anyInt()); + anyInt(), anyBoolean()); assertThat(captor.getValue().getDevice()).isNotNull(); } @@ -131,16 +131,16 @@ public class MediaDataCombineLatestTest extends SysuiTestCase { public void migrateKeyMediaFirst() { // GIVEN that media and device info has already been received mManager.onMediaDataLoaded(OLD_KEY, null, mMediaData, true /* immediately */, - 0 /* receivedSmartspaceCardLatency */); + 0 /* receivedSmartspaceCardLatency */, false /* isSsReactivated */); mManager.onMediaDeviceChanged(OLD_KEY, null, mDeviceData); reset(mListener); // WHEN a key migration event is received mManager.onMediaDataLoaded(KEY, OLD_KEY, mMediaData, true /* immediately */, - 0 /* receivedSmartspaceCardLatency */); + 0 /* receivedSmartspaceCardLatency */, false /* isSsReactivated */); // THEN the listener receives a combined event ArgumentCaptor<MediaData> captor = ArgumentCaptor.forClass(MediaData.class); verify(mListener).onMediaDataLoaded(eq(KEY), eq(OLD_KEY), captor.capture(), anyBoolean(), - anyInt()); + anyInt(), anyBoolean()); assertThat(captor.getValue().getDevice()).isNotNull(); } @@ -148,7 +148,7 @@ public class MediaDataCombineLatestTest extends SysuiTestCase { public void migrateKeyDeviceFirst() { // GIVEN that media and device info has already been received mManager.onMediaDataLoaded(OLD_KEY, null, mMediaData, true /* immediately */, - 0 /* receivedSmartspaceCardLatency */); + 0 /* receivedSmartspaceCardLatency */, false /* isSsReactivated */); mManager.onMediaDeviceChanged(OLD_KEY, null, mDeviceData); reset(mListener); // WHEN a key migration event is received @@ -156,7 +156,7 @@ public class MediaDataCombineLatestTest extends SysuiTestCase { // THEN the listener receives a combined event ArgumentCaptor<MediaData> captor = ArgumentCaptor.forClass(MediaData.class); verify(mListener).onMediaDataLoaded(eq(KEY), eq(OLD_KEY), captor.capture(), anyBoolean(), - anyInt()); + anyInt(), anyBoolean()); assertThat(captor.getValue().getDevice()).isNotNull(); } @@ -164,17 +164,17 @@ public class MediaDataCombineLatestTest extends SysuiTestCase { public void migrateKeyMediaAfter() { // GIVEN that media and device info has already been received mManager.onMediaDataLoaded(OLD_KEY, null, mMediaData, true /* immediately */, - 0 /* receivedSmartspaceCardLatency */); + 0 /* receivedSmartspaceCardLatency */, false /* isSsReactivated */); mManager.onMediaDeviceChanged(OLD_KEY, null, mDeviceData); mManager.onMediaDeviceChanged(KEY, OLD_KEY, mDeviceData); reset(mListener); // WHEN a second key migration event is received for media mManager.onMediaDataLoaded(KEY, OLD_KEY, mMediaData, true /* immediately */, - 0 /* receivedSmartspaceCardLatency */); + 0 /* receivedSmartspaceCardLatency */, false /* isSsReactivated */); // THEN the key has already been migrated ArgumentCaptor<MediaData> captor = ArgumentCaptor.forClass(MediaData.class); verify(mListener).onMediaDataLoaded(eq(KEY), eq(KEY), captor.capture(), anyBoolean(), - anyInt()); + anyInt(), anyBoolean()); assertThat(captor.getValue().getDevice()).isNotNull(); } @@ -182,17 +182,17 @@ public class MediaDataCombineLatestTest extends SysuiTestCase { public void migrateKeyDeviceAfter() { // GIVEN that media and device info has already been received mManager.onMediaDataLoaded(OLD_KEY, null, mMediaData, true /* immediately */, - 0 /* receivedSmartspaceCardLatency */); + 0 /* receivedSmartspaceCardLatency */, false /* isSsReactivated */); mManager.onMediaDeviceChanged(OLD_KEY, null, mDeviceData); mManager.onMediaDataLoaded(KEY, OLD_KEY, mMediaData, true /* immediately */, - 0 /* receivedSmartspaceCardLatency */); + 0 /* receivedSmartspaceCardLatency */, false /* isSsReactivated */); reset(mListener); // WHEN a second key migration event is received for the device mManager.onMediaDeviceChanged(KEY, OLD_KEY, mDeviceData); // THEN the key has already be migrated ArgumentCaptor<MediaData> captor = ArgumentCaptor.forClass(MediaData.class); verify(mListener).onMediaDataLoaded(eq(KEY), eq(KEY), captor.capture(), anyBoolean(), - anyInt()); + anyInt(), anyBoolean()); assertThat(captor.getValue().getDevice()).isNotNull(); } @@ -207,7 +207,7 @@ public class MediaDataCombineLatestTest extends SysuiTestCase { @Test public void mediaDataRemovedAfterMediaEvent() { mManager.onMediaDataLoaded(KEY, null, mMediaData, true /* immediately */, - 0 /* receivedSmartspaceCardLatency */); + 0 /* receivedSmartspaceCardLatency */, false /* isSsReactivated */); mManager.onMediaDataRemoved(KEY); verify(mListener).onMediaDataRemoved(eq(KEY)); } @@ -223,14 +223,14 @@ public class MediaDataCombineLatestTest extends SysuiTestCase { public void mediaDataKeyUpdated() { // GIVEN that device and media events have already been received mManager.onMediaDataLoaded(KEY, null, mMediaData, true /* immediately */, - 0 /* receivedSmartspaceCardLatency */); + 0 /* receivedSmartspaceCardLatency */, false /* isSsReactivated */); mManager.onMediaDeviceChanged(KEY, null, mDeviceData); // WHEN the key is changed mManager.onMediaDataLoaded("NEW_KEY", KEY, mMediaData, true /* immediately */, - 0 /* receivedSmartspaceCardLatency */); + 0 /* receivedSmartspaceCardLatency */, false /* isSsReactivated */); // THEN the listener gets a load event with the correct keys ArgumentCaptor<MediaData> captor = ArgumentCaptor.forClass(MediaData.class); verify(mListener).onMediaDataLoaded( - eq("NEW_KEY"), any(), captor.capture(), anyBoolean(), anyInt()); + eq("NEW_KEY"), any(), captor.capture(), anyBoolean(), anyInt(), anyBoolean()); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataFilterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataFilterTest.kt index 5a3c43c6cc15..2ecf80e914c7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataFilterTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataFilterTest.kt @@ -124,7 +124,7 @@ class MediaDataFilterTest : SysuiTestCase() { // THEN we should tell the listener verify(listener).onMediaDataLoaded(eq(KEY), eq(null), eq(dataMain), eq(true), - eq(0)) + eq(0), eq(false)) } @Test @@ -133,7 +133,8 @@ class MediaDataFilterTest : SysuiTestCase() { mediaDataFilter.onMediaDataLoaded(KEY, null, dataGuest) // THEN we should NOT tell the listener - verify(listener, never()).onMediaDataLoaded(any(), any(), any(), anyBoolean(), anyInt()) + verify(listener, never()).onMediaDataLoaded(any(), any(), any(), anyBoolean(), + anyInt(), anyBoolean()) } @Test @@ -180,51 +181,56 @@ class MediaDataFilterTest : SysuiTestCase() { // THEN we should add back the guest user media verify(listener).onMediaDataLoaded(eq(KEY_ALT), eq(null), eq(dataGuest), eq(true), - eq(0)) + eq(0), eq(false)) // but not the main user's verify(listener, never()).onMediaDataLoaded(eq(KEY), any(), eq(dataMain), anyBoolean(), - anyInt()) + anyInt(), anyBoolean()) } @Test - fun testHasAnyMedia() { - assertThat(mediaDataFilter.hasAnyMedia()).isFalse() + fun testHasAnyMediaOrRecommendation() { + assertThat(mediaDataFilter.hasAnyMediaOrRecommendation()).isFalse() mediaDataFilter.onMediaDataLoaded(KEY, oldKey = null, data = dataMain) + assertThat(mediaDataFilter.hasAnyMediaOrRecommendation()).isTrue() assertThat(mediaDataFilter.hasAnyMedia()).isTrue() } @Test - fun testHasActiveMedia() { - assertThat(mediaDataFilter.hasActiveMedia()).isFalse() + fun testHasActiveMediaOrRecommendation() { + assertThat(mediaDataFilter.hasActiveMediaOrRecommendation()).isFalse() val data = dataMain.copy(active = true) mediaDataFilter.onMediaDataLoaded(KEY, oldKey = null, data = data) + assertThat(mediaDataFilter.hasActiveMediaOrRecommendation()).isTrue() assertThat(mediaDataFilter.hasActiveMedia()).isTrue() } @Test - fun testHasAnyMedia_onlyCurrentUser() { - assertThat(mediaDataFilter.hasAnyMedia()).isFalse() + fun testHasAnyMediaOrRecommendation_onlyCurrentUser() { + assertThat(mediaDataFilter.hasAnyMediaOrRecommendation()).isFalse() mediaDataFilter.onMediaDataLoaded(KEY, oldKey = null, data = dataGuest) + assertThat(mediaDataFilter.hasAnyMediaOrRecommendation()).isFalse() assertThat(mediaDataFilter.hasAnyMedia()).isFalse() } @Test - fun testHasActiveMedia_onlyCurrentUser() { - assertThat(mediaDataFilter.hasActiveMedia()).isFalse() + fun testHasActiveMediaOrRecommendation_onlyCurrentUser() { + assertThat(mediaDataFilter.hasActiveMediaOrRecommendation()).isFalse() val data = dataGuest.copy(active = true) mediaDataFilter.onMediaDataLoaded(KEY, oldKey = null, data = data) - assertThat(mediaDataFilter.hasActiveMedia()).isFalse() + assertThat(mediaDataFilter.hasActiveMediaOrRecommendation()).isFalse() + assertThat(mediaDataFilter.hasAnyMedia()).isFalse() } @Test fun testOnNotificationRemoved_doesntHaveMedia() { mediaDataFilter.onMediaDataLoaded(KEY, oldKey = null, data = dataMain) mediaDataFilter.onMediaDataRemoved(KEY) + assertThat(mediaDataFilter.hasAnyMediaOrRecommendation()).isFalse() assertThat(mediaDataFilter.hasAnyMedia()).isFalse() } @@ -241,9 +247,9 @@ class MediaDataFilterTest : SysuiTestCase() { mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData) verify(listener) - .onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), eq(true), - eq(false)) - assertThat(mediaDataFilter.hasActiveMedia()).isTrue() + .onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), eq(true)) + assertThat(mediaDataFilter.hasActiveMediaOrRecommendation()).isTrue() + assertThat(mediaDataFilter.hasActiveMedia()).isFalse() } @Test @@ -252,9 +258,10 @@ class MediaDataFilterTest : SysuiTestCase() { mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData) - verify(listener, never()).onMediaDataLoaded(any(), any(), any(), anyBoolean(), anyInt()) - verify(listener, never()).onSmartspaceMediaDataLoaded(any(), any(), anyBoolean(), - anyBoolean()) + verify(listener, never()).onMediaDataLoaded(any(), any(), any(), anyBoolean(), + anyInt(), anyBoolean()) + verify(listener, never()).onSmartspaceMediaDataLoaded(any(), any(), anyBoolean()) + assertThat(mediaDataFilter.hasActiveMediaOrRecommendation()).isFalse() assertThat(mediaDataFilter.hasActiveMedia()).isFalse() } @@ -266,9 +273,9 @@ class MediaDataFilterTest : SysuiTestCase() { mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData) verify(listener) - .onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), eq(true), - eq(true)) - assertThat(mediaDataFilter.hasActiveMedia()).isTrue() + .onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), eq(true)) + assertThat(mediaDataFilter.hasActiveMediaOrRecommendation()).isTrue() + assertThat(mediaDataFilter.hasActiveMedia()).isFalse() } @Test @@ -280,8 +287,8 @@ class MediaDataFilterTest : SysuiTestCase() { clock.advanceTime(SMARTSPACE_MAX_AGE + 100) mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData) - verify(listener, never()).onSmartspaceMediaDataLoaded(any(), any(), anyBoolean(), - anyBoolean()) + verify(listener, never()).onSmartspaceMediaDataLoaded(any(), any(), anyBoolean()) + assertThat(mediaDataFilter.hasActiveMediaOrRecommendation()).isFalse() assertThat(mediaDataFilter.hasActiveMedia()).isFalse() } @@ -293,16 +300,16 @@ class MediaDataFilterTest : SysuiTestCase() { val dataCurrent = dataMain.copy(active = false, lastActive = clock.elapsedRealtime()) mediaDataFilter.onMediaDataLoaded(KEY, null, dataCurrent) verify(listener).onMediaDataLoaded(eq(KEY), eq(null), eq(dataCurrent), eq(true), - eq(0)) + eq(0), eq(false)) // AND we get a smartspace signal mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData) // THEN we should tell listeners to treat the media as not active instead verify(listener, never()).onMediaDataLoaded(eq(KEY), eq(KEY), any(), anyBoolean(), - anyInt()) - verify(listener, never()).onSmartspaceMediaDataLoaded(any(), any(), anyBoolean(), - anyBoolean()) + anyInt(), anyBoolean()) + verify(listener, never()).onSmartspaceMediaDataLoaded(any(), any(), anyBoolean()) + assertThat(mediaDataFilter.hasActiveMediaOrRecommendation()).isFalse() assertThat(mediaDataFilter.hasActiveMedia()).isFalse() } @@ -314,7 +321,7 @@ class MediaDataFilterTest : SysuiTestCase() { val dataCurrent = dataMain.copy(active = false, lastActive = clock.elapsedRealtime()) mediaDataFilter.onMediaDataLoaded(KEY, null, dataCurrent) verify(listener).onMediaDataLoaded(eq(KEY), eq(null), eq(dataCurrent), eq(true), - eq(0)) + eq(0), eq(false)) // AND we get a smartspace signal mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData) @@ -322,11 +329,10 @@ class MediaDataFilterTest : SysuiTestCase() { // THEN we should tell listeners to treat the media as active instead val dataCurrentAndActive = dataCurrent.copy(active = true) verify(listener).onMediaDataLoaded(eq(KEY), eq(KEY), eq(dataCurrentAndActive), eq(true), - eq(100)) - assertThat(mediaDataFilter.hasActiveMedia()).isTrue() + eq(100), eq(true)) + assertThat(mediaDataFilter.hasActiveMediaOrRecommendation()).isFalse() // Smartspace update shouldn't be propagated for the empty rec list. - verify(listener, never()).onSmartspaceMediaDataLoaded(any(), any(), anyBoolean(), - anyBoolean()) + verify(listener, never()).onSmartspaceMediaDataLoaded(any(), any(), anyBoolean()) } @Test @@ -335,7 +341,7 @@ class MediaDataFilterTest : SysuiTestCase() { val dataCurrent = dataMain.copy(active = false, lastActive = clock.elapsedRealtime()) mediaDataFilter.onMediaDataLoaded(KEY, null, dataCurrent) verify(listener).onMediaDataLoaded(eq(KEY), eq(null), eq(dataCurrent), eq(true), - eq(0)) + eq(0), eq(false)) // AND we get a smartspace signal mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData) @@ -343,12 +349,11 @@ class MediaDataFilterTest : SysuiTestCase() { // THEN we should tell listeners to treat the media as active instead val dataCurrentAndActive = dataCurrent.copy(active = true) verify(listener).onMediaDataLoaded(eq(KEY), eq(KEY), eq(dataCurrentAndActive), eq(true), - eq(100)) - assertThat(mediaDataFilter.hasActiveMedia()).isTrue() + eq(100), eq(true)) + assertThat(mediaDataFilter.hasActiveMediaOrRecommendation()).isTrue() // Smartspace update should also be propagated but not prioritized. verify(listener) - .onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), eq(false), - eq(true)) + .onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), eq(false)) } @Test @@ -357,6 +362,7 @@ class MediaDataFilterTest : SysuiTestCase() { mediaDataFilter.onSmartspaceMediaDataRemoved(SMARTSPACE_KEY) verify(listener).onSmartspaceMediaDataRemoved(SMARTSPACE_KEY) + assertThat(mediaDataFilter.hasActiveMediaOrRecommendation()).isFalse() assertThat(mediaDataFilter.hasActiveMedia()).isFalse() } @@ -365,17 +371,18 @@ class MediaDataFilterTest : SysuiTestCase() { val dataCurrent = dataMain.copy(active = false, lastActive = clock.elapsedRealtime()) mediaDataFilter.onMediaDataLoaded(KEY, null, dataCurrent) verify(listener).onMediaDataLoaded(eq(KEY), eq(null), eq(dataCurrent), eq(true), - eq(0)) + eq(0), eq(false)) mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData) val dataCurrentAndActive = dataCurrent.copy(active = true) verify(listener).onMediaDataLoaded(eq(KEY), eq(KEY), eq(dataCurrentAndActive), eq(true), - eq(100)) + eq(100), eq(true)) mediaDataFilter.onSmartspaceMediaDataRemoved(SMARTSPACE_KEY) verify(listener).onSmartspaceMediaDataRemoved(SMARTSPACE_KEY) + assertThat(mediaDataFilter.hasActiveMediaOrRecommendation()).isFalse() assertThat(mediaDataFilter.hasActiveMedia()).isFalse() } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt index e2019e089329..81e4182f2ad5 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaDataManagerTest.kt @@ -214,7 +214,7 @@ class MediaDataManagerTest : SysuiTestCase() { mediaDataManager.onNotificationAdded(KEY, mediaNotification) mediaDataManager.onMediaDataLoaded(KEY, oldKey = null, data = mock(MediaData::class.java)) verify(listener).onMediaDataLoaded(eq(KEY), eq(null), anyObject(), eq(true), - eq(0)) + eq(0), eq(false)) } @Test @@ -226,7 +226,7 @@ class MediaDataManagerTest : SysuiTestCase() { assertThat(backgroundExecutor.runAllReady()).isEqualTo(1) assertThat(foregroundExecutor.runAllReady()).isEqualTo(1) verify(listener).onMediaDataLoaded(eq(KEY), eq(null), capture(mediaDataCaptor), eq(true), - eq(0)) + eq(0), eq(false)) assertThat(mediaDataCaptor.value!!.active).isTrue() } @@ -249,7 +249,7 @@ class MediaDataManagerTest : SysuiTestCase() { assertThat(backgroundExecutor.runAllReady()).isEqualTo(1) assertThat(foregroundExecutor.runAllReady()).isEqualTo(1) verify(listener).onMediaDataLoaded(eq(KEY), eq(null), capture(mediaDataCaptor), eq(true), - eq(0)) + eq(0), eq(false)) assertThat(mediaDataCaptor.value!!.playbackLocation).isEqualTo( MediaData.PLAYBACK_CAST_REMOTE) } @@ -270,7 +270,7 @@ class MediaDataManagerTest : SysuiTestCase() { assertThat(backgroundExecutor.runAllReady()).isEqualTo(1) assertThat(foregroundExecutor.runAllReady()).isEqualTo(1) verify(listener).onMediaDataLoaded(eq(KEY), eq(null), capture(mediaDataCaptor), eq(true), - eq(0)) + eq(0), eq(false)) val data = mediaDataCaptor.value assertThat(data.resumption).isFalse() mediaDataManager.onMediaDataLoaded(KEY, null, data.copy(resumeAction = Runnable {})) @@ -279,7 +279,7 @@ class MediaDataManagerTest : SysuiTestCase() { // THEN the media data indicates that it is for resumption verify(listener) .onMediaDataLoaded(eq(PACKAGE_NAME), eq(KEY), capture(mediaDataCaptor), eq(true), - eq(0)) + eq(0), eq(false)) assertThat(mediaDataCaptor.value.resumption).isTrue() assertThat(mediaDataCaptor.value.isPlaying).isFalse() } @@ -294,7 +294,7 @@ class MediaDataManagerTest : SysuiTestCase() { assertThat(foregroundExecutor.runAllReady()).isEqualTo(2) verify(listener) .onMediaDataLoaded(eq(KEY), eq(null), capture(mediaDataCaptor), eq(true), - eq(0)) + eq(0), eq(false)) val data = mediaDataCaptor.value assertThat(data.resumption).isFalse() val resumableData = data.copy(resumeAction = Runnable {}) @@ -306,7 +306,7 @@ class MediaDataManagerTest : SysuiTestCase() { // THEN the data is for resumption and the key is migrated to the package name verify(listener) .onMediaDataLoaded(eq(PACKAGE_NAME), eq(KEY), capture(mediaDataCaptor), eq(true), - eq(0)) + eq(0), eq(false)) assertThat(mediaDataCaptor.value.resumption).isTrue() verify(listener, never()).onMediaDataRemoved(eq(KEY)) // WHEN the second is removed @@ -315,7 +315,7 @@ class MediaDataManagerTest : SysuiTestCase() { verify(listener) .onMediaDataLoaded( eq(PACKAGE_NAME), eq(PACKAGE_NAME), capture(mediaDataCaptor), eq(true), - eq(0)) + eq(0), eq(false)) assertThat(mediaDataCaptor.value.resumption).isTrue() verify(listener).onMediaDataRemoved(eq(KEY_2)) } @@ -330,7 +330,7 @@ class MediaDataManagerTest : SysuiTestCase() { assertThat(backgroundExecutor.runAllReady()).isEqualTo(1) assertThat(foregroundExecutor.runAllReady()).isEqualTo(1) verify(listener).onMediaDataLoaded(eq(KEY), eq(null), capture(mediaDataCaptor), eq(true), - eq(0)) + eq(0), eq(false)) val data = mediaDataCaptor.value val dataRemoteWithResume = data.copy(resumeAction = Runnable {}, playbackLocation = MediaData.PLAYBACK_CAST_LOCAL) @@ -358,7 +358,7 @@ class MediaDataManagerTest : SysuiTestCase() { // THEN the media data indicates that it is for resumption verify(listener) .onMediaDataLoaded(eq(PACKAGE_NAME), eq(null), capture(mediaDataCaptor), eq(true), - eq(0)) + eq(0), eq(false)) val data = mediaDataCaptor.value assertThat(data.resumption).isTrue() assertThat(data.song).isEqualTo(SESSION_TITLE) @@ -406,7 +406,7 @@ class MediaDataManagerTest : SysuiTestCase() { assertThat(foregroundExecutor.runAllReady()).isEqualTo(1) verify(listener) .onMediaDataLoaded(eq(KEY), eq(null), capture(mediaDataCaptor), eq(true), - eq(0)) + eq(0), eq(false)) } @Test @@ -417,7 +417,7 @@ class MediaDataManagerTest : SysuiTestCase() { eq(SmartspaceMediaData(KEY_MEDIA_SMARTSPACE, true /* isActive */, true /*isValid */, PACKAGE_NAME, mediaSmartspaceBaseAction, listOf(mediaRecommendationItem), DISMISS_INTENT, 0, 1234L)), - eq(false), eq(false)) + eq(false)) } @Test @@ -430,7 +430,7 @@ class MediaDataManagerTest : SysuiTestCase() { .copy(targetId = KEY_MEDIA_SMARTSPACE, isActive = true, isValid = false, dismissIntent = DISMISS_INTENT, headphoneConnectionTimeMillis = 1234L)), - eq(false), eq(false)) + eq(false)) } @Test @@ -450,14 +450,14 @@ class MediaDataManagerTest : SysuiTestCase() { eq(EMPTY_SMARTSPACE_MEDIA_DATA .copy(targetId = KEY_MEDIA_SMARTSPACE, isActive = true, isValid = false, dismissIntent = null, headphoneConnectionTimeMillis = 1234L)), - eq(false), eq(false)) + eq(false)) } @Test fun testOnSmartspaceMediaDataLoaded_hasNoneMediaTarget_notCallsListener() { smartspaceMediaDataProvider.onTargetsAvailable(listOf()) verify(listener, never()) - .onSmartspaceMediaDataLoaded(anyObject(), anyObject(), anyBoolean(), anyBoolean()) + .onSmartspaceMediaDataLoaded(anyObject(), anyObject(), anyBoolean()) } @Test @@ -481,7 +481,7 @@ class MediaDataManagerTest : SysuiTestCase() { // THEN smartspace signal is ignored verify(listener, never()) - .onSmartspaceMediaDataLoaded(anyObject(), anyObject(), anyBoolean(), anyBoolean()) + .onSmartspaceMediaDataLoaded(anyObject(), anyObject(), anyBoolean()) } @Test @@ -489,7 +489,7 @@ class MediaDataManagerTest : SysuiTestCase() { // GIVEN a media recommendation card is present smartspaceMediaDataProvider.onTargetsAvailable(listOf(mediaSmartspaceTarget)) verify(listener).onSmartspaceMediaDataLoaded(eq(KEY_MEDIA_SMARTSPACE), anyObject(), - anyBoolean(), anyBoolean()) + anyBoolean()) // WHEN the media recommendation setting is turned off Settings.Secure.putInt(context.contentResolver, @@ -509,7 +509,7 @@ class MediaDataManagerTest : SysuiTestCase() { assertThat(backgroundExecutor.runAllReady()).isEqualTo(1) assertThat(foregroundExecutor.runAllReady()).isEqualTo(1) verify(listener).onMediaDataLoaded(eq(KEY), eq(null), capture(mediaDataCaptor), eq(true), - eq(0)) + eq(0), eq(false)) assertThat(mediaDataCaptor.value!!.lastActive).isAtLeast(currentTime) } @@ -527,7 +527,7 @@ class MediaDataManagerTest : SysuiTestCase() { // THEN the last active time is not changed verify(listener).onMediaDataLoaded(eq(KEY), eq(KEY), capture(mediaDataCaptor), eq(true), - eq(0)) + eq(0), eq(false)) assertThat(mediaDataCaptor.value.lastActive).isLessThan(currentTime) } @@ -539,7 +539,7 @@ class MediaDataManagerTest : SysuiTestCase() { assertThat(backgroundExecutor.runAllReady()).isEqualTo(1) assertThat(foregroundExecutor.runAllReady()).isEqualTo(1) verify(listener).onMediaDataLoaded(eq(KEY), eq(null), capture(mediaDataCaptor), eq(true), - eq(0)) + eq(0), eq(false)) val data = mediaDataCaptor.value assertThat(data.resumption).isFalse() mediaDataManager.onMediaDataLoaded(KEY, null, data.copy(resumeAction = Runnable {})) @@ -552,7 +552,7 @@ class MediaDataManagerTest : SysuiTestCase() { // THEN the last active time is not changed verify(listener) .onMediaDataLoaded(eq(PACKAGE_NAME), eq(KEY), capture(mediaDataCaptor), eq(true), - eq(0)) + eq(0), eq(false)) assertThat(mediaDataCaptor.value.resumption).isTrue() assertThat(mediaDataCaptor.value.lastActive).isLessThan(currentTime) } @@ -579,7 +579,7 @@ class MediaDataManagerTest : SysuiTestCase() { // THEN only the first MAX_COMPACT_ACTIONS are actually set verify(listener).onMediaDataLoaded(eq(KEY), eq(null), capture(mediaDataCaptor), eq(true), - eq(0)) + eq(0), eq(false)) assertThat(mediaDataCaptor.value.actionsToShowInCompact.size).isEqualTo( MediaDataManager.MAX_COMPACT_ACTIONS) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt index a3ffb2fe4b8d..7565fe1c5c0e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt @@ -22,6 +22,7 @@ import android.testing.TestableLooper import android.view.ViewGroup import android.widget.FrameLayout import androidx.test.filters.SmallTest +import com.android.keyguard.KeyguardViewController import com.android.systemui.R import com.android.systemui.SysuiTestCase import com.android.systemui.controls.controller.ControlsControllerImplTest.Companion.eq @@ -31,7 +32,6 @@ import com.android.systemui.statusbar.NotificationLockscreenUserManager import com.android.systemui.statusbar.StatusBarState import com.android.systemui.statusbar.SysuiStatusBarStateController import com.android.systemui.statusbar.phone.KeyguardBypassController -import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.util.animation.UniqueObjectHostView @@ -80,7 +80,7 @@ class MediaHierarchyManagerTest : SysuiTestCase() { @Mock private lateinit var wakefulnessLifecycle: WakefulnessLifecycle @Mock - private lateinit var statusBarKeyguardViewManager: StatusBarKeyguardViewManager + private lateinit var keyguardViewController: KeyguardViewController @Mock private lateinit var configurationController: ConfigurationController @Mock @@ -110,7 +110,7 @@ class MediaHierarchyManagerTest : SysuiTestCase() { notificationLockscreenUserManager, configurationController, wakefulnessLifecycle, - statusBarKeyguardViewManager) + keyguardViewController) verify(wakefulnessLifecycle).addObserver(wakefullnessObserver.capture()) verify(statusBarStateController).addCallback(statusBarCallback.capture()) setupHost(lockHost, MediaHierarchyManager.LOCATION_LOCKSCREEN) diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaPlayerDataTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaPlayerDataTest.kt index 421f9bee78fa..e92f6b57c633 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaPlayerDataTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaPlayerDataTest.kt @@ -61,8 +61,10 @@ public class MediaPlayerDataTest : SysuiTestCase() { val playerIsRemote = mock(MediaControlPanel::class.java) val dataIsRemote = createMediaData("app2", PLAYING, REMOTE, !RESUMPTION) - MediaPlayerData.addMediaPlayer("2", dataIsRemote, playerIsRemote, systemClock) - MediaPlayerData.addMediaPlayer("1", dataIsPlaying, playerIsPlaying, systemClock) + MediaPlayerData.addMediaPlayer("2", dataIsRemote, playerIsRemote, systemClock, + isSsReactivated = false) + MediaPlayerData.addMediaPlayer("1", dataIsPlaying, playerIsPlaying, systemClock, + isSsReactivated = false) val players = MediaPlayerData.players() assertThat(players).hasSize(2) @@ -77,18 +79,22 @@ public class MediaPlayerDataTest : SysuiTestCase() { val playerIsPlaying2 = mock(MediaControlPanel::class.java) var dataIsPlaying2 = createMediaData("app2", !PLAYING, LOCAL, !RESUMPTION) - MediaPlayerData.addMediaPlayer("1", dataIsPlaying1, playerIsPlaying1, systemClock) + MediaPlayerData.addMediaPlayer("1", dataIsPlaying1, playerIsPlaying1, systemClock, + isSsReactivated = false) systemClock.advanceTime(1) - MediaPlayerData.addMediaPlayer("2", dataIsPlaying2, playerIsPlaying2, systemClock) + MediaPlayerData.addMediaPlayer("2", dataIsPlaying2, playerIsPlaying2, systemClock, + isSsReactivated = false) systemClock.advanceTime(1) dataIsPlaying1 = createMediaData("app1", !PLAYING, LOCAL, !RESUMPTION) dataIsPlaying2 = createMediaData("app2", PLAYING, LOCAL, !RESUMPTION) - MediaPlayerData.addMediaPlayer("1", dataIsPlaying1, playerIsPlaying1, systemClock) + MediaPlayerData.addMediaPlayer("1", dataIsPlaying1, playerIsPlaying1, systemClock, + isSsReactivated = false) systemClock.advanceTime(1) - MediaPlayerData.addMediaPlayer("2", dataIsPlaying2, playerIsPlaying2, systemClock) + MediaPlayerData.addMediaPlayer("2", dataIsPlaying2, playerIsPlaying2, systemClock, + isSsReactivated = false) systemClock.advanceTime(1) val players = MediaPlayerData.players() @@ -116,14 +122,20 @@ public class MediaPlayerDataTest : SysuiTestCase() { val dataUndetermined = createMediaData("app6", UNDETERMINED, LOCAL, RESUMPTION) MediaPlayerData.addMediaPlayer( - "3", dataIsStoppedAndLocal, playerIsStoppedAndLocal, systemClock) + "3", dataIsStoppedAndLocal, playerIsStoppedAndLocal, systemClock, + isSsReactivated = false) MediaPlayerData.addMediaPlayer( - "5", dataIsStoppedAndRemote, playerIsStoppedAndRemote, systemClock) - MediaPlayerData.addMediaPlayer("4", dataCanResume, playerCanResume, systemClock) - MediaPlayerData.addMediaPlayer("1", dataIsPlaying, playerIsPlaying, systemClock) + "5", dataIsStoppedAndRemote, playerIsStoppedAndRemote, systemClock, + isSsReactivated = false) + MediaPlayerData.addMediaPlayer("4", dataCanResume, playerCanResume, systemClock, + isSsReactivated = false) + MediaPlayerData.addMediaPlayer("1", dataIsPlaying, playerIsPlaying, systemClock, + isSsReactivated = false) MediaPlayerData.addMediaPlayer( - "2", dataIsPlayingAndRemote, playerIsPlayingAndRemote, systemClock) - MediaPlayerData.addMediaPlayer("6", dataUndetermined, playerUndetermined, systemClock) + "2", dataIsPlayingAndRemote, playerIsPlayingAndRemote, systemClock, + isSsReactivated = false) + MediaPlayerData.addMediaPlayer("6", dataUndetermined, playerUndetermined, systemClock, + isSsReactivated = false) val players = MediaPlayerData.players() assertThat(players).hasSize(6) @@ -141,11 +153,13 @@ public class MediaPlayerDataTest : SysuiTestCase() { assertThat(MediaPlayerData.players()).hasSize(0) - MediaPlayerData.addMediaPlayer(keyA, data, playerIsPlaying, systemClock) + MediaPlayerData.addMediaPlayer(keyA, data, playerIsPlaying, systemClock, + isSsReactivated = false) systemClock.advanceTime(1) assertThat(MediaPlayerData.players()).hasSize(1) - MediaPlayerData.addMediaPlayer(keyB, data, playerIsPlaying, systemClock) + MediaPlayerData.addMediaPlayer(keyB, data, playerIsPlaying, systemClock, + isSsReactivated = false) systemClock.advanceTime(1) assertThat(MediaPlayerData.players()).hasSize(2) diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaSessionBasedFilterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaSessionBasedFilterTest.kt index 5d53181c8345..983f7492794c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaSessionBasedFilterTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaSessionBasedFilterTest.kt @@ -187,7 +187,7 @@ public class MediaSessionBasedFilterTest : SysuiTestCase() { bgExecutor.runAllReady() fgExecutor.runAllReady() verify(mediaListener).onMediaDataLoaded(eq(KEY), eq(null), eq(mediaData1), eq(true), - eq(0)) + eq(0), eq(false)) } @Test @@ -210,7 +210,7 @@ public class MediaSessionBasedFilterTest : SysuiTestCase() { fgExecutor.runAllReady() // THEN the event is not filtered verify(mediaListener).onMediaDataLoaded(eq(KEY), eq(null), eq(mediaData1), eq(true), - eq(0)) + eq(0), eq(false)) } @Test @@ -240,7 +240,7 @@ public class MediaSessionBasedFilterTest : SysuiTestCase() { fgExecutor.runAllReady() // THEN the event is not filtered verify(mediaListener).onMediaDataLoaded(eq(KEY), eq(null), eq(mediaData1), eq(true), - eq(0)) + eq(0), eq(false)) } @Test @@ -256,14 +256,14 @@ public class MediaSessionBasedFilterTest : SysuiTestCase() { fgExecutor.runAllReady() // THEN the event is not filtered verify(mediaListener).onMediaDataLoaded(eq(KEY), eq(null), eq(mediaData1), eq(true), - eq(0)) + eq(0), eq(false)) // WHEN a loaded event is received that matches the local session filter.onMediaDataLoaded(KEY, null, mediaData2) bgExecutor.runAllReady() fgExecutor.runAllReady() // THEN the event is filtered verify(mediaListener, never()).onMediaDataLoaded( - eq(KEY), eq(null), eq(mediaData2), anyBoolean(), anyInt()) + eq(KEY), eq(null), eq(mediaData2), anyBoolean(), anyInt(), anyBoolean()) } @Test @@ -280,7 +280,7 @@ public class MediaSessionBasedFilterTest : SysuiTestCase() { // THEN the event is not filtered because there isn't a notification for the remote // session. verify(mediaListener).onMediaDataLoaded(eq(KEY), eq(null), eq(mediaData1), eq(true), - eq(0)) + eq(0), eq(false)) } @Test @@ -298,14 +298,15 @@ public class MediaSessionBasedFilterTest : SysuiTestCase() { fgExecutor.runAllReady() // THEN the event is not filtered verify(mediaListener).onMediaDataLoaded(eq(key1), eq(null), eq(mediaData1), eq(true), - eq(0)) + eq(0), eq(false)) // WHEN a loaded event is received that matches the local session filter.onMediaDataLoaded(key2, null, mediaData2) bgExecutor.runAllReady() fgExecutor.runAllReady() // THEN the event is filtered verify(mediaListener, never()) - .onMediaDataLoaded(eq(key2), eq(null), eq(mediaData2), anyBoolean(), anyInt()) + .onMediaDataLoaded(eq(key2), eq(null), eq(mediaData2), anyBoolean(), + anyInt(), anyBoolean()) // AND there should be a removed event for key2 verify(mediaListener).onMediaDataRemoved(eq(key2)) } @@ -325,14 +326,14 @@ public class MediaSessionBasedFilterTest : SysuiTestCase() { fgExecutor.runAllReady() // THEN the event is not filtered verify(mediaListener).onMediaDataLoaded(eq(key1), eq(null), eq(mediaData1), eq(true), - eq(0)) + eq(0), eq(false)) // WHEN a loaded event is received that matches the remote session filter.onMediaDataLoaded(key2, null, mediaData2) bgExecutor.runAllReady() fgExecutor.runAllReady() // THEN the event is not filtered verify(mediaListener).onMediaDataLoaded(eq(key2), eq(null), eq(mediaData2), eq(true), - eq(0)) + eq(0), eq(false)) } @Test @@ -349,14 +350,14 @@ public class MediaSessionBasedFilterTest : SysuiTestCase() { fgExecutor.runAllReady() // THEN the event is not filtered verify(mediaListener).onMediaDataLoaded(eq(KEY), eq(null), eq(mediaData1), eq(true), - eq(0)) + eq(0), eq(false)) // WHEN a loaded event is received that matches the local session filter.onMediaDataLoaded(KEY, null, mediaData2) bgExecutor.runAllReady() fgExecutor.runAllReady() // THEN the event is not filtered verify(mediaListener).onMediaDataLoaded(eq(KEY), eq(null), eq(mediaData2), eq(true), - eq(0)) + eq(0), eq(false)) } @Test @@ -375,7 +376,7 @@ public class MediaSessionBasedFilterTest : SysuiTestCase() { fgExecutor.runAllReady() // THEN the event is not filtered verify(mediaListener).onMediaDataLoaded(eq(KEY), eq(null), eq(mediaData1), eq(true), - eq(0)) + eq(0), eq(false)) } @Test @@ -398,7 +399,7 @@ public class MediaSessionBasedFilterTest : SysuiTestCase() { fgExecutor.runAllReady() // THEN the key migration event is fired verify(mediaListener).onMediaDataLoaded(eq(key2), eq(key1), eq(mediaData2), eq(true), - eq(0)) + eq(0), eq(false)) } @Test @@ -428,13 +429,14 @@ public class MediaSessionBasedFilterTest : SysuiTestCase() { fgExecutor.runAllReady() // THEN the key migration event is filtered verify(mediaListener, never()) - .onMediaDataLoaded(eq(key2), eq(null), eq(mediaData2), anyBoolean(), anyInt()) + .onMediaDataLoaded(eq(key2), eq(null), eq(mediaData2), anyBoolean(), + anyInt(), anyBoolean()) // WHEN a loaded event is received that matches the remote session filter.onMediaDataLoaded(key2, null, mediaData1) bgExecutor.runAllReady() fgExecutor.runAllReady() // THEN the key migration event is fired verify(mediaListener).onMediaDataLoaded(eq(key2), eq(null), eq(mediaData1), eq(true), - eq(0)) + eq(0), eq(false)) } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java index cd26e0d960dc..b5c501ab388b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java @@ -201,7 +201,7 @@ public class MediaOutputControllerTest extends SysuiTestCase { assertThat(devices.containsAll(mMediaDevices)).isTrue(); assertThat(devices.size()).isEqualTo(mMediaDevices.size()); - verify(mCb).onRouteChanged(); + verify(mCb).onDeviceListChanged(); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSBrightnessControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSBrightnessControllerTest.kt deleted file mode 100644 index de1d86b08785..000000000000 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSBrightnessControllerTest.kt +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (C) 2021 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.systemui.qs - -import androidx.test.filters.SmallTest -import com.android.systemui.SysuiTestCase -import com.android.systemui.settings.brightness.BrightnessController -import com.android.systemui.statusbar.policy.BrightnessMirrorController -import org.junit.Before -import org.junit.Rule -import org.junit.Test -import org.mockito.Mock -import org.mockito.Mockito.times -import org.mockito.Mockito.verify -import org.mockito.Mockito.never -import org.mockito.Mockito.mock -import org.mockito.junit.MockitoJUnit - -@SmallTest -class QuickQSBrightnessControllerTest : SysuiTestCase() { - - @Mock - lateinit var brightnessController: BrightnessController - @get:Rule - val mockito = MockitoJUnit.rule() - - lateinit var quickQSBrightnessController: QuickQSBrightnessController - - @Before - fun setUp() { - quickQSBrightnessController = QuickQSBrightnessController( - brightnessControllerFactory = { brightnessController }) - } - - @Test - fun testSliderIsShownWhenInitializedInSplitShade() { - quickQSBrightnessController.init(shouldUseSplitNotificationShade = true) - - verify(brightnessController).showSlider() - } - - @Test - fun testSliderIsShownWhenRefreshedInSplitShade() { - quickQSBrightnessController.refreshVisibility(shouldUseSplitNotificationShade = true) - - verify(brightnessController, times(1)).showSlider() - } - - @Test - fun testSliderIsHiddenWhenRefreshedInNonSplitShade() { - // needs to be shown first - quickQSBrightnessController.refreshVisibility(shouldUseSplitNotificationShade = true) - quickQSBrightnessController.refreshVisibility(shouldUseSplitNotificationShade = false) - - verify(brightnessController).hideSlider() - } - - @Test - fun testSliderChangesVisibilityWhenRotating() { - quickQSBrightnessController.refreshVisibility(shouldUseSplitNotificationShade = true) - verify(brightnessController, times(1)).showSlider() - - quickQSBrightnessController.refreshVisibility(shouldUseSplitNotificationShade = false) - verify(brightnessController, times(1)).hideSlider() - } - - @Test - fun testCallbacksAreRegisteredOnlyOnce() { - // this flow simulates expanding shade in portrait... - quickQSBrightnessController.setListening(true) - quickQSBrightnessController.refreshVisibility(shouldUseSplitNotificationShade = false) - // ... and rotating to landscape/split shade where slider is visible - quickQSBrightnessController.refreshVisibility(shouldUseSplitNotificationShade = true) - - verify(brightnessController, times(1)).registerCallbacks() - } - - @Test - fun testCallbacksAreRegisteredOnlyOnceWhenRotatingPhone() { - quickQSBrightnessController.setListening(true) - quickQSBrightnessController.refreshVisibility(shouldUseSplitNotificationShade = true) - quickQSBrightnessController.refreshVisibility(shouldUseSplitNotificationShade = false) - quickQSBrightnessController.refreshVisibility(shouldUseSplitNotificationShade = true) - - verify(brightnessController, times(1)).registerCallbacks() - } - - @Test - fun testCallbacksAreNotRegisteredWhenSliderNotVisible() { - quickQSBrightnessController.setListening(true) - quickQSBrightnessController.refreshVisibility(shouldUseSplitNotificationShade = false) - - verify(brightnessController, never()).registerCallbacks() - } - - @Test - fun testMirrorIsSetWhenSliderIsShown() { - val mirrorController = mock(BrightnessMirrorController::class.java) - quickQSBrightnessController.setMirror(mirrorController) - quickQSBrightnessController.refreshVisibility(shouldUseSplitNotificationShade = true) - - verify(brightnessController).setMirror(mirrorController) - } -}
\ No newline at end of file diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt index 59948d310b4f..fb8a6e3d4212 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt @@ -67,8 +67,6 @@ class QuickQSPanelControllerTest : SysuiTestCase() { @Mock private lateinit var tileView: QSTileView @Mock - private lateinit var quickQsBrightnessController: QuickQSBrightnessController - @Mock private lateinit var footerActionsController: FooterActionsController @Captor private lateinit var captor: ArgumentCaptor<QSPanel.OnConfigurationChangedListener> @@ -95,7 +93,6 @@ class QuickQSPanelControllerTest : SysuiTestCase() { uiEventLogger, qsLogger, dumpManager, - quickQsBrightnessController, footerActionsController ) @@ -128,13 +125,11 @@ class QuickQSPanelControllerTest : SysuiTestCase() { } @Test - fun testBrightnessAndFooterVisibilityRefreshedWhenConfigurationChanged() { + fun testFooterVisibilityRefreshedWhenConfigurationChanged() { // times(2) because both controller and base controller are registering their listeners verify(quickQSPanel, times(2)).addOnConfigurationChangedListener(captor.capture()) captor.allValues.forEach { it.onConfigurationChange(Configuration.EMPTY) } - - verify(quickQsBrightnessController).refreshVisibility(anyBoolean()) // times(2) because footer visibility is also refreshed on controller init verify(footerActionsController, times(2)).refreshVisibility(anyBoolean()) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java index cf58c63e3d26..a3e0107c1716 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java @@ -35,6 +35,7 @@ import android.widget.LinearLayout; import androidx.test.filters.SmallTest; +import com.android.keyguard.KeyguardUpdateMonitor; import com.android.systemui.SysuiTestCase; import com.android.systemui.flags.FeatureFlags; import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper; @@ -54,6 +55,7 @@ import com.android.systemui.statusbar.notification.row.NotificationTestHelper; import com.android.systemui.statusbar.notification.stack.ForegroundServiceSectionController; import com.android.systemui.statusbar.notification.stack.NotificationListContainer; import com.android.systemui.statusbar.phone.KeyguardBypassController; +import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.wm.shell.bubbles.Bubbles; import com.google.android.collect.Lists; @@ -118,7 +120,9 @@ public class NotificationViewHierarchyManagerTest extends SysuiTestCase { mock(ForegroundServiceSectionController.class), mock(DynamicChildBindController.class), mock(LowPriorityInflationHelper.class), - mock(AssistantFeedbackController.class)); + mock(AssistantFeedbackController.class), + mock(KeyguardUpdateMonitor.class), + mock(KeyguardStateController.class)); mViewHierarchyManager.setUpWithPresenter(mPresenter, mListContainer); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinatorTest.kt index 5fd4174af164..3f84c161db20 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinatorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinatorTest.kt @@ -19,8 +19,11 @@ package com.android.systemui.statusbar.notification.collection.coordinator import android.os.UserHandle import android.service.notification.StatusBarNotification import androidx.test.filters.SmallTest +import com.android.keyguard.KeyguardUpdateMonitor import com.android.systemui.SysuiTestCase +import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.statusbar.NotificationLockscreenUserManager +import com.android.systemui.statusbar.StatusBarState import com.android.systemui.statusbar.notification.DynamicPrivacyController import com.android.systemui.statusbar.notification.collection.ListEntry import com.android.systemui.statusbar.notification.collection.NotifPipeline @@ -28,9 +31,12 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntry import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Invalidator import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Pluggable +import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.util.mockito.withArgCaptor +import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.mock import org.junit.Test +import org.mockito.Mockito.never import org.mockito.Mockito.verify import org.mockito.Mockito.`when` as whenever @@ -40,9 +46,13 @@ class SensitiveContentCoordinatorTest : SysuiTestCase() { val dynamicPrivacyController: DynamicPrivacyController = mock() val lockscreenUserManager: NotificationLockscreenUserManager = mock() val pipeline: NotifPipeline = mock() + val keyguardUpdateMonitor: KeyguardUpdateMonitor = mock() + val statusBarStateController: StatusBarStateController = mock() + val keyguardStateController: KeyguardStateController = mock() val coordinator: SensitiveContentCoordinator = SensitiveContentCoordinatorModule - .provideCoordinator(dynamicPrivacyController, lockscreenUserManager) + .provideCoordinator(dynamicPrivacyController, lockscreenUserManager, + keyguardUpdateMonitor, statusBarStateController, keyguardStateController) @Test fun onDynamicPrivacyChanged_invokeInvalidationListener() { @@ -190,6 +200,28 @@ class SensitiveContentCoordinatorTest : SysuiTestCase() { verify(entry.representativeEntry!!).setSensitive(true, true) } + @Test + fun onBeforeRenderList_deviceDynamicallyUnlocked_deviceBiometricBypassingLockScreen() { + coordinator.attach(pipeline) + val onBeforeRenderListListener = withArgCaptor<OnBeforeRenderListListener> { + verify(pipeline).addOnBeforeRenderListListener(capture()) + } + + whenever(lockscreenUserManager.currentUserId).thenReturn(1) + whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true) + whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(false) + whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(true) + whenever(statusBarStateController.getState()).thenReturn(StatusBarState.KEYGUARD) + whenever(keyguardUpdateMonitor.getUserUnlockedWithBiometricAndIsBypassing(any())) + .thenReturn(true) + + val entry = fakeNotification(2, true) + + onBeforeRenderListListener.onBeforeRenderList(listOf(entry)) + + verify(entry.representativeEntry!!, never()).setSensitive(any(), any()) + } + private fun fakeNotification(notifUserId: Int, needsRedaction: Boolean): ListEntry { val mockUserHandle = mock<UserHandle>().apply { whenever(identifier).thenReturn(notifUserId) diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java index 13989d3f0ebe..3fc60373e2a4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java @@ -23,7 +23,6 @@ import static com.android.keyguard.KeyguardClockSwitch.SMALL; import static com.android.systemui.statusbar.StatusBarState.KEYGUARD; import static com.android.systemui.statusbar.StatusBarState.SHADE; import static com.android.systemui.statusbar.StatusBarState.SHADE_LOCKED; -import static com.android.systemui.statusbar.notification.ViewGroupFadeHelper.reset; import static com.google.common.truth.Truth.assertThat; @@ -107,6 +106,7 @@ import com.android.systemui.statusbar.LockscreenShadeTransitionController; import com.android.systemui.statusbar.NotificationLockscreenUserManager; import com.android.systemui.statusbar.NotificationRemoteInputManager; import com.android.systemui.statusbar.NotificationShadeDepthController; +import com.android.systemui.statusbar.NotificationShadeWindowController; import com.android.systemui.statusbar.NotificationShelfController; import com.android.systemui.statusbar.PulseExpansionHandler; import com.android.systemui.statusbar.StatusBarStateControllerImpl; @@ -305,6 +305,8 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { @Mock private NotificationsQSContainerController mNotificationsQSContainerController; @Mock + private NotificationShadeWindowController mNotificationShadeWindowController; + @Mock private FeatureFlags mFeatureFlags; private Optional<SysUIUnfoldComponent> mSysUIUnfoldComponent = Optional.empty(); private SysuiStatusBarStateController mStatusBarStateController; @@ -402,8 +404,10 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { when(mLayoutInflater.inflate(eq(R.layout.keyguard_bottom_area), any(), anyBoolean())) .thenReturn(mKeyguardBottomArea); when(mNotificationRemoteInputManager.isRemoteInputActive()).thenReturn(false); - - reset(mView); + doAnswer(invocation -> { + ((Runnable) invocation.getArgument(0)).run(); + return null; + }).when(mNotificationShadeWindowController).batchApplyWindowLayoutParams(any()); mNotificationPanelViewController = new NotificationPanelViewController(mView, mResources, @@ -412,8 +416,9 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { coordinator, expansionHandler, mDynamicPrivacyController, mKeyguardBypassController, mFalsingManager, new FalsingCollectorFake(), mNotificationLockscreenUserManager, mNotificationEntryManager, - mKeyguardStateController, mStatusBarStateController, mDozeLog, - mDozeParameters, mCommandQueue, mVibratorHelper, + mKeyguardStateController, mStatusBarStateController, + mNotificationShadeWindowController, + mDozeLog, mDozeParameters, mCommandQueue, mVibratorHelper, mLatencyTracker, mPowerManager, mAccessibilityManager, 0, mUpdateMonitor, mMetricsLogger, mActivityManager, mConfigurationController, () -> flingAnimationUtilsBuilder, mStatusBarTouchableRegionManager, @@ -824,7 +829,7 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { public void testSwitchesToBigClockInSplitShadeOnAod() { mStatusBarStateController.setState(KEYGUARD); enableSplitShade(/* enabled= */ true); - when(mMediaDataManager.hasActiveMedia()).thenReturn(true); + when(mMediaDataManager.hasActiveMediaOrRecommendation()).thenReturn(true); when(mNotificationStackScrollLayoutController.getVisibleNotificationCount()).thenReturn(2); mNotificationPanelViewController.setDozing(true, false, null); @@ -836,7 +841,7 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { public void testDisplaysSmallClockOnLockscreenInSplitShadeWhenMediaIsPlaying() { mStatusBarStateController.setState(KEYGUARD); enableSplitShade(/* enabled= */ true); - when(mMediaDataManager.hasActiveMedia()).thenReturn(true); + when(mMediaDataManager.hasActiveMediaOrRecommendation()).thenReturn(true); // one notification + media player visible when(mNotificationStackScrollLayoutController.getVisibleNotificationCount()).thenReturn(1); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImplTest.java index 90b8a74d88be..cb468108880a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerImplTest.java @@ -26,6 +26,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.never; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -225,4 +226,17 @@ public class NotificationShadeWindowControllerImplTest extends SysuiTestCase { assertThat((mLayoutParameters.getValue().flags & FLAG_NOT_FOCUSABLE) != 0).isTrue(); assertThat((mLayoutParameters.getValue().flags & FLAG_ALT_FOCUSABLE_IM) == 0).isTrue(); } + + @Test + public void batchApplyWindowLayoutParams_doesNotDispatchEvents() { + mNotificationShadeWindowController.setForceDozeBrightness(true); + verify(mWindowManager).updateViewLayout(any(), any()); + + clearInvocations(mWindowManager); + mNotificationShadeWindowController.batchApplyWindowLayoutParams(()-> { + mNotificationShadeWindowController.setForceDozeBrightness(false); + verify(mWindowManager, never()).updateViewLayout(any(), any()); + }); + verify(mWindowManager).updateViewLayout(any(), any()); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java index 20575ae504ad..2709e436a663 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java @@ -351,6 +351,10 @@ public class StatusBarTest extends SysuiTestCase { when(mStatusBarComponentFactory.create()).thenReturn(mStatusBarComponent); when(mStatusBarComponent.getNotificationShadeWindowViewController()).thenReturn( mNotificationShadeWindowViewController); + doAnswer(invocation -> { + ((Runnable) invocation.getArgument(0)).run(); + return null; + }).when(mNotificationShadeWindowController).batchApplyWindowLayoutParams(any()); mShadeController = new ShadeControllerImpl(mCommandQueue, mStatusBarStateController, mNotificationShadeWindowController, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java index b97f053b24b5..cf9fbe06ef47 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/fragment/CollapsedStatusBarFragmentTest.java @@ -17,6 +17,8 @@ package com.android.systemui.statusbar.phone.fragment; import static android.view.Display.DEFAULT_DISPLAY; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.atLeast; @@ -27,6 +29,7 @@ import android.app.Fragment; import android.app.StatusBarManager; import android.content.Context; import android.os.Bundle; +import android.provider.Settings; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper.RunWithLooper; import android.view.View; @@ -58,6 +61,7 @@ import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController; import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.util.concurrency.FakeExecutor; +import com.android.systemui.util.settings.SecureSettings; import com.android.systemui.util.time.FakeSystemClock; import org.junit.Before; @@ -85,6 +89,8 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest { private final CommandQueue mCommandQueue = mock(CommandQueue.class); private OperatorNameViewController.Factory mOperatorNameViewControllerFactory; private OperatorNameViewController mOperatorNameViewController; + private SecureSettings mSecureSettings; + private FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock()); @Mock private StatusBarFragmentComponent.Factory mStatusBarFragmentComponentFactory; @@ -299,6 +305,40 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest { assertEquals(mStatusBarFragmentComponent, fragment.getStatusBarFragmentComponent()); } + @Test + public void testBlockedIcons_obeysSettingForVibrateIcon_settingOff() { + CollapsedStatusBarFragment fragment = resumeAndGetFragment(); + String str = mContext.getString(com.android.internal.R.string.status_bar_volume); + + // GIVEN the setting is off + when(mSecureSettings.getInt(Settings.Secure.STATUS_BAR_SHOW_VIBRATE_ICON, 0)) + .thenReturn(0); + + // WHEN CollapsedStatusBarFragment builds the blocklist + fragment.updateBlockedIcons(); + + // THEN status_bar_volume SHOULD be present in the list + boolean contains = fragment.getBlockedIcons().contains(str); + assertTrue(contains); + } + + @Test + public void testBlockedIcons_obeysSettingForVibrateIcon_settingOn() { + CollapsedStatusBarFragment fragment = resumeAndGetFragment(); + String str = mContext.getString(com.android.internal.R.string.status_bar_volume); + + // GIVEN the setting is ON + when(mSecureSettings.getInt(Settings.Secure.STATUS_BAR_SHOW_VIBRATE_ICON, 0)) + .thenReturn(1); + + // WHEN CollapsedStatusBarFragment builds the blocklist + fragment.updateBlockedIcons(); + + // THEN status_bar_volume SHOULD NOT be present in the list + boolean contains = fragment.getBlockedIcons().contains(str); + assertFalse(contains); + } + @Override protected Fragment instantiate(Context context, String className, Bundle arguments) { MockitoAnnotations.initMocks(this); @@ -314,6 +354,7 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest { mOperatorNameViewControllerFactory = mock(OperatorNameViewController.Factory.class); when(mOperatorNameViewControllerFactory.create(any())) .thenReturn(mOperatorNameViewController); + mSecureSettings = mock(SecureSettings.class); setUpNotificationIconAreaController(); return new CollapsedStatusBarFragment( @@ -336,7 +377,9 @@ public class CollapsedStatusBarFragmentTest extends SysuiBaseFragmentTest { new LogBuffer("TEST", 1, 1, mock(LogcatEchoTracker.class)), new DisableFlagsLogger() ), - mOperatorNameViewControllerFactory); + mOperatorNameViewControllerFactory, + mSecureSettings, + mExecutor); } private void setUpDaggerComponent() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeStatusBarIconController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeStatusBarIconController.java index 8ad6271bfc7e..2be67edfc946 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeStatusBarIconController.java +++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeStatusBarIconController.java @@ -43,6 +43,10 @@ public class FakeStatusBarIconController extends BaseLeakChecker<IconManager> } @Override + public void refreshIconGroup(IconManager iconManager) { + } + + @Override public void setExternalIcon(String slot) { } diff --git a/packages/VpnDialogs/res/values-af/strings.xml b/packages/VpnDialogs/res/values-af/strings.xml index 88ccbd9e98dc..ac82b0e0009a 100644 --- a/packages/VpnDialogs/res/values-af/strings.xml +++ b/packages/VpnDialogs/res/values-af/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"Verbindingversoek"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> wil \'n VPN-verbinding opstel wat dit sal toelaat om netwerkverkeer te monitor. Aanvaar dit net as jy die bron vertrou. <br /> <br /> <img src=vpn_icon /> verskyn boaan jou skerm as VPN aktief is."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> wil \'n VPN-verbinding opstel wat dit toelaat om netwerkverkeer te monitor. Aanvaar dit net as jy die bron vertrou. <br /> <br /> <img src=vpn_icon /> verskyn op jou skerm wanneer VPN aktief is."</string> <string name="legacy_title" msgid="192936250066580964">"VPN is gekoppel"</string> <string name="session" msgid="6470628549473641030">"Sessie:"</string> <string name="duration" msgid="3584782459928719435">"Tydsduur:"</string> diff --git a/packages/VpnDialogs/res/values-am/strings.xml b/packages/VpnDialogs/res/values-am/strings.xml index 9fc5ff43d946..ad9773b248a4 100644 --- a/packages/VpnDialogs/res/values-am/strings.xml +++ b/packages/VpnDialogs/res/values-am/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"የግንኙነት ጥያቄ"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> የአውታረ መረብ መከታተል የሚያስችል የVPN ግንኑነት ማዋቀር ይፈልጋል። ምንጩን የሚያምኑት ብቻ ከሆኑ ይቀበሉ። <br /> <br /> <img src=vpn_icon /> VPN ገቢር ሲሆን በማያ ገጽዎ ላይኛው ክፍል ላይ ይታያል።"</string> - <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> የአውታረ መረብ ትራፊክን ለመቆጣጠር የሚያስችል የVPN ግንኙነትን ማዋቀር ይፈልጋል። ምንጩን የሚያምኑ ከሆነ ብቻ ይቀበሉ። <br /> <br /> <img src=vpn_icon /> ማያ ገጹ ላይ VPN ገቢር ሲሆን ይታያል።"</string> <string name="legacy_title" msgid="192936250066580964">"VPN ተያይዟል"</string> <string name="session" msgid="6470628549473641030">"ክፍለ ጊዜ፡"</string> <string name="duration" msgid="3584782459928719435">"ጊዜ"</string> diff --git a/packages/VpnDialogs/res/values-ar/strings.xml b/packages/VpnDialogs/res/values-ar/strings.xml index 33be6a3e458a..808cde906d2f 100644 --- a/packages/VpnDialogs/res/values-ar/strings.xml +++ b/packages/VpnDialogs/res/values-ar/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"طلب الاتصال"</string> <string name="warning" msgid="809658604548412033">"يريد <xliff:g id="APP">%s</xliff:g> إعداد الاتصال بالشبكة الافتراضية الخاصة التي تتيح له مراقبة حركة المرور على الشبكة. فلا توافق إلا إذا كنت تثق في المصدر. <br /> <br /> <img src=vpn_icon /> يظهر في الجزء العلوي من الشاشة عندما تكون الشبكة الافتراضية الخاصة نشطة."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"يريد تطبيق <xliff:g id="APP">%s</xliff:g> إعداد اتصال شبكة افتراضية خاصة (VPN) يتيح له مراقبة حركة بيانات الشبكة. لا تقبل السماح بذلك إلا إذا كنت تثق في المصدر. <br /> <br /> <img src=vpn_icon /> يظهر على شاشتك عندما تكون الشبكة الافتراضية الخاصة نشطة."</string> <string name="legacy_title" msgid="192936250066580964">"VPN متصلة"</string> <string name="session" msgid="6470628549473641030">"الجلسة"</string> <string name="duration" msgid="3584782459928719435">"المدة:"</string> diff --git a/packages/VpnDialogs/res/values-as/strings.xml b/packages/VpnDialogs/res/values-as/strings.xml index 3f2e2347135d..45d8458f4d45 100644 --- a/packages/VpnDialogs/res/values-as/strings.xml +++ b/packages/VpnDialogs/res/values-as/strings.xml @@ -17,8 +17,7 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"সংযোগৰ অনুৰোধ"</string> - <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g>এ নেটৱৰ্ক ট্ৰেফিক নিৰীক্ষণ কৰিবলৈ এটা ভিপিএন সংযোগ ছেট আপ কৰিবলৈ বিচাৰিছে৷ আপুনি কেৱল উৎসটোক বিশ্বাস কৰিলেহে অনুৰোধ স্বীকাৰ কৰিব৷ ভিপিএন সক্ৰিয় থকাৰ সময়ত আপোনাৰ স্ক্ৰীনৰ ওপৰত <br /> <br /> <img src=vpn_icon /> দৃশ্যমান হয়৷"</string> - <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g>এ এটা ভিপিএন সংযোগ ছেট আপ কৰিব বিচাৰে, যিটোৱে ইয়াক নেটৱৰ্ক ট্ৰেফিক নিৰীক্ষণ কৰিবলৈ দিয়ে। আপুনি উৎসটোক বিশ্বাস কৰিলেহে গ্ৰহণ কৰক। ভিপিএনটো সক্ৰিয় হৈ থকাৰ সময়ত আপোনাৰ স্ক্ৰীনত<br /> <br /> <img src=vpn_icon /> প্ৰদৰ্শিত হয়।"</string> + <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g>এ নেটৱৰ্ক ট্ৰেফিক নিৰীক্ষণ কৰিবলৈ এটা ভিপিএন সংযোগ ছেট আপ কৰিবলৈ বিচাৰিছে৷ আপুনি কেৱল উৎসটোক বিশ্বাস কৰিলেহে অনুৰোধ স্বীকাৰ কৰিব৷ ভিপিএন সক্ৰিয় থকাৰ সময়ত আপোনাৰ স্ক্ৰীণৰ ওপৰত <br /> <br /> <img src=vpn_icon /> দৃশ্যমান হয়৷"</string> <string name="legacy_title" msgid="192936250066580964">"ভিপিএন সংযোগ হৈ আছে"</string> <string name="session" msgid="6470628549473641030">"ছেশ্বন:"</string> <string name="duration" msgid="3584782459928719435">"সময়সীমা:"</string> @@ -29,7 +28,7 @@ <string name="always_on_disconnected_message" msgid="555634519845992917">"<xliff:g id="VPN_APP_0">%1$s</xliff:g>ক সকলো সময়তে সংযুক্ত হৈ থাকিবলৈ ছেট কৰি থোৱা হৈছে, কিন্তু ই বৰ্তমান সংযোগ কৰিবপৰা নাই। আপোনাৰ ফ\'নটোৱে <xliff:g id="VPN_APP_1">%1$s</xliff:g>ৰ সৈতে সংযোগ কৰিব নোৱাৰালৈকে এটা ৰাজহুৱা নেটৱৰ্ক ব্যৱহাৰ কৰিব।"</string> <string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"<xliff:g id="VPN_APP">%1$s</xliff:g>ক সকলো সময়তে সংযুক্ত হৈ থাকিবলৈ ছেট কৰি থোৱা হৈছে, কিন্তু ই বৰ্তমান সংযোগ কৰিবপৰা নাই। ভিপিএনটোৰ সৈতে পুনৰ সংযুক্ত নোহোৱালৈকে আপোনাৰ কোনো সংযোগ নাথাকিব।"</string> <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> - <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"ভিপিএন ছেটিং সলনি কৰক"</string> + <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"ভিপিএন ছেটিংসমূহ সলনি কৰক"</string> <string name="configure" msgid="4905518375574791375">"কনফিগাৰ কৰক"</string> <string name="disconnect" msgid="971412338304200056">"সংযোগ বিচ্ছিন্ন কৰক"</string> <string name="open_app" msgid="3717639178595958667">"এপ্ খোলক"</string> diff --git a/packages/VpnDialogs/res/values-az/strings.xml b/packages/VpnDialogs/res/values-az/strings.xml index d8788350bb8c..2bdf23ee2aa0 100644 --- a/packages/VpnDialogs/res/values-az/strings.xml +++ b/packages/VpnDialogs/res/values-az/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"Bağlantı Sorğusu"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> VPN bağlantı yaratmaq istəyir ki, bu da şəbəkə trafikini izləyə bilər. Yalnız mənbəyə güvəndiyiniz halda qəbul edin. VPN aktiv olan zaman <br /> <br /> <img src=vpn_icon /> ekranın yuxarısında görünür."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> şəbəkə trafikini izləməyə imkan verən VPN bağlantısı yaratmaq istəyir. Yalnız mənbəyə güvəndiyiniz halda qəbul edin. <br /> <br /> <img src=vpn_icon /> VPN aktiv olan zaman ekranda görünür."</string> <string name="legacy_title" msgid="192936250066580964">"VPN qoşuludur"</string> <string name="session" msgid="6470628549473641030">"Sessiya:"</string> <string name="duration" msgid="3584782459928719435">"Müddət:"</string> diff --git a/packages/VpnDialogs/res/values-b+sr+Latn/strings.xml b/packages/VpnDialogs/res/values-b+sr+Latn/strings.xml index a1075d22df84..f40e40670bf3 100644 --- a/packages/VpnDialogs/res/values-b+sr+Latn/strings.xml +++ b/packages/VpnDialogs/res/values-b+sr+Latn/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"Zahtev za povezivanje"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> želi da podesi VPN vezu koja omogućava praćenje saobraćaja na mreži. Prihvatite samo ako verujete izvoru. <br /> <br /> <img src=vpn_icon /> se prikazuje u vrhu ekrana kada je VPN aktivan."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"Aplikacija <xliff:g id="APP">%s</xliff:g> želi da podesi VPN vezu koja joj omogućava da prati mrežni saobraćaj. Prihvatite ovo samo ako imate poverenja u izvor. <br /> <br /> <img src=vpn_icon /> se prikazuje na ekranu kada je VPN aktivan."</string> <string name="legacy_title" msgid="192936250066580964">"VPN je povezan"</string> <string name="session" msgid="6470628549473641030">"Sesija:"</string> <string name="duration" msgid="3584782459928719435">"Trajanje:"</string> diff --git a/packages/VpnDialogs/res/values-be/strings.xml b/packages/VpnDialogs/res/values-be/strings.xml index fc3f8787b5d7..0903c8ece36b 100644 --- a/packages/VpnDialogs/res/values-be/strings.xml +++ b/packages/VpnDialogs/res/values-be/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"Запыт на падлучэнне"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> спрабуе наладзіць падлучэнне VPN, якое дазваляе сачыць за сеткавым трафікам. Прымайце толькі тады, калі вы давяраеце гэтай крыніцы. Калі VPN актыўны, у верхняй частцы экрана адлюстроўваецца <br /> <br /> <img src=vpn_icon />."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"Праграма \"<xliff:g id="APP">%s</xliff:g>\" запытвае дазвол на падключэнне да сеткі VPN, каб адсочваць сеткавы трафік. Дайце дазвол, толькі калі вы давяраеце крыніцы. Калі адбудзецца падключэнне да VPN, на экране з\'явіцца значок <br /> <br /> <img src=vpn_icon />."</string> <string name="legacy_title" msgid="192936250066580964">"VPN падключаны"</string> <string name="session" msgid="6470628549473641030">"Сессія"</string> <string name="duration" msgid="3584782459928719435">"Працягласць:"</string> diff --git a/packages/VpnDialogs/res/values-bg/strings.xml b/packages/VpnDialogs/res/values-bg/strings.xml index 6345f1dd7911..9ac853d2016f 100644 --- a/packages/VpnDialogs/res/values-bg/strings.xml +++ b/packages/VpnDialogs/res/values-bg/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"Заявка за свързване"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> иска да настрои връзка с виртуална частна мрежа (VPN), за да може да наблюдава мрежовия трафик. Приемете само ако източникът е надежден. Иконата <br /> <br /> <img src=vpn_icon /> се показва в долната част на екрана при активирана VPN."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> иска да настрои връзка с VPN, за да може да наблюдава трафика в мрежата. Приемете само ако източникът е надежден. <br /> <br /> <img src=vpn_icon /> се показва на екрана при активирана VPN."</string> <string name="legacy_title" msgid="192936250066580964">"VPN е свързана"</string> <string name="session" msgid="6470628549473641030">"Сесия:"</string> <string name="duration" msgid="3584782459928719435">"Продължителност:"</string> diff --git a/packages/VpnDialogs/res/values-bn/strings.xml b/packages/VpnDialogs/res/values-bn/strings.xml index 352b786bc009..5e11fd9934b6 100644 --- a/packages/VpnDialogs/res/values-bn/strings.xml +++ b/packages/VpnDialogs/res/values-bn/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"সংযোগের অনুরোধ"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> এমন একটি VPN সংযোগ সেট-আপ করতে চাচ্ছে যেটি দিয়ে এটি নেটওয়ার্ক ট্রাফিক নিরীক্ষণ করতে পারবে। আপনি যদি উৎসটিকে বিশ্বাস করেন, তাহলেই কেবল এতে সম্মতি দিন। VPN সক্রিয় থাকলে আপনার স্ক্রীনের উপরে <br /> <br /> <img src=vpn_icon /> দেখা যাবে।"</string> - <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> এমন একটি VPN সংযোগ সেট আপ করতে চাইছে যেটি দিয়ে এটি নেটওয়ার্ক ট্রাফিক নিরীক্ষণ করতে পারবে। আপনি সোর্সটি বিশ্বাস করলে একমাত্র তখনই অ্যাক্সেপ্ট করুন। PN অ্যাক্টিভ থাকলে <br /> <br /> <img src=vpn_icon /> আপনার স্ক্রিনে দেখা যায়।"</string> <string name="legacy_title" msgid="192936250066580964">"VPN সংযুক্ত হয়েছে"</string> <string name="session" msgid="6470628549473641030">"অধিবেশন:"</string> <string name="duration" msgid="3584782459928719435">"সময়কাল:"</string> diff --git a/packages/VpnDialogs/res/values-bs/strings.xml b/packages/VpnDialogs/res/values-bs/strings.xml index fa5f4ea2b762..56812d59e106 100644 --- a/packages/VpnDialogs/res/values-bs/strings.xml +++ b/packages/VpnDialogs/res/values-bs/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"Zahtjev za povezivanje"</string> <string name="warning" msgid="809658604548412033">"Aplikacija <xliff:g id="APP">%s</xliff:g> želi podesiti VPN vezu koja joj omogućava praćenje mrežnog saobraćaja. Prihvatite samo ako je izvor pouzdan. <br /> <br /> <img src=vpn_icon /> se pojavi na vrhu ekrana kada je VPN aktivna."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"Aplikacija <xliff:g id="APP">%s</xliff:g> želi postaviti VPN vezu koja joj omogućava praćenje mrežnog saobraćaja. Prihvatite samo ako vjerujete izvoru. Kada je VPN aktivan, na ekranu se prikazuje ikona <br /> <br /> <img src=vpn_icon />."</string> <string name="legacy_title" msgid="192936250066580964">"VPN veza uspostavljena"</string> <string name="session" msgid="6470628549473641030">"Sesija:"</string> <string name="duration" msgid="3584782459928719435">"Trajanje:"</string> diff --git a/packages/VpnDialogs/res/values-ca/strings.xml b/packages/VpnDialogs/res/values-ca/strings.xml index cdb754723c28..97738c316f4b 100644 --- a/packages/VpnDialogs/res/values-ca/strings.xml +++ b/packages/VpnDialogs/res/values-ca/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"Sol·licitud de connexió"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> vol configurar una connexió VPN que li permeti controlar el trànsit de xarxa. Accepta la sol·licitud només si prové d\'una font de confiança. <br /> <br /> <img src=vpn_icon /> es mostra a la part superior de la pantalla quan la VPN està activada."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> vol configurar una connexió VPN que li permeti monitorar el trànsit de xarxa. Accepta la sol·licitud només si prové d\'una font de confiança. <br /> <br /> <img src=vpn_icon /> és la icona que veuràs a la pantalla quan la VPN estigui activa."</string> <string name="legacy_title" msgid="192936250066580964">"La VPN està connectada"</string> <string name="session" msgid="6470628549473641030">"Sessió:"</string> <string name="duration" msgid="3584782459928719435">"Durada:"</string> diff --git a/packages/VpnDialogs/res/values-cs/strings.xml b/packages/VpnDialogs/res/values-cs/strings.xml index c06f6ff0cf02..5cc809c7cb02 100644 --- a/packages/VpnDialogs/res/values-cs/strings.xml +++ b/packages/VpnDialogs/res/values-cs/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"Žádost o připojení"</string> <string name="warning" msgid="809658604548412033">"Aplikace <xliff:g id="APP">%s</xliff:g> žádá o nastavení připojení VPN, pomocí kterého bude moci sledovat síťový provoz. Povolte, jen pokud zdroji důvěřujete. <br /> <br /> <img src=vpn_icon /> – když je síť VPN aktivní, v horní části obrazovky se zobrazuje tato ikona."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"Aplikace <xliff:g id="APP">%s</xliff:g> chce nastavit připojení VPN, které umožňuje sledovat síťový provoz. Povolte, jen pokud zdroji důvěřujete. <br /> <br /> <img src=vpn_icon /> – když je síť VPN aktivní, na obrazovce se zobrazuje tato ikona."</string> <string name="legacy_title" msgid="192936250066580964">"Síť VPN je připojena"</string> <string name="session" msgid="6470628549473641030">"Relace:"</string> <string name="duration" msgid="3584782459928719435">"Doba trvání:"</string> diff --git a/packages/VpnDialogs/res/values-da/strings.xml b/packages/VpnDialogs/res/values-da/strings.xml index a4ddc1963de8..7641158af3da 100644 --- a/packages/VpnDialogs/res/values-da/strings.xml +++ b/packages/VpnDialogs/res/values-da/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"Forbindelsesanmodning"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> vil konfigurere en VPN-forbindelse, der giver appen mulighed for at registrere netværkstrafik. Du bør kun acceptere dette, hvis du har tillid til kilden. <br /> <br /> <img src=vpn_icon /> vises øverst på din skærm, når VPN-forbindelsen er aktiv."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> anmoder om at konfigurere en VPN-forbindelse, der giver appen tilladelse til at holde øje med netværkstrafik. Du bør kun acceptere dette, hvis du har tillid til appen. <br /> <br /> <img src=vpn_icon /> vises på din skærm, når VPN-forbindelsen er aktiv."</string> <string name="legacy_title" msgid="192936250066580964">"VPN er tilsluttet"</string> <string name="session" msgid="6470628549473641030">"Session:"</string> <string name="duration" msgid="3584782459928719435">"Varighed:"</string> diff --git a/packages/VpnDialogs/res/values-de/strings.xml b/packages/VpnDialogs/res/values-de/strings.xml index f38e3953855a..0f1e00980439 100644 --- a/packages/VpnDialogs/res/values-de/strings.xml +++ b/packages/VpnDialogs/res/values-de/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"Verbindungsanfrage"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> möchte eine VPN-Verbindung herstellen, über die der Netzwerkverkehr überwacht werden kann. Lass die Verbindung nur zu, wenn die App vertrauenswürdig ist. Wenn VPN aktiv ist, wird oben im Display <br /> <br /> <img src=vpn_icon /> angezeigt."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> möchte eine VPN-Verbindung herstellen, über die der Netzwerkverkehr überwacht werden kann. Lass die Verbindung nur zu, wenn die App vertrauenswürdig ist. <br /> <br /> <img src=vpn_icon /> wird auf dem Display angezeigt, wenn VPN aktiv ist."</string> <string name="legacy_title" msgid="192936250066580964">"VPN ist verbunden"</string> <string name="session" msgid="6470628549473641030">"Sitzung:"</string> <string name="duration" msgid="3584782459928719435">"Dauer:"</string> diff --git a/packages/VpnDialogs/res/values-el/strings.xml b/packages/VpnDialogs/res/values-el/strings.xml index e3eb4603ea61..78bcc43ff609 100644 --- a/packages/VpnDialogs/res/values-el/strings.xml +++ b/packages/VpnDialogs/res/values-el/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"Αίτημα σύνδεσης"</string> <string name="warning" msgid="809658604548412033">"Η εφαρμογή <xliff:g id="APP">%s</xliff:g> επιθυμεί να ρυθμίσει μια σύνδεση VPN που της επιτρέπει να παρακολουθεί την επισκεψιμότητα του δικτύου. Αποδεχτείτε το αίτημα μόνο εάν εμπιστεύεστε την πηγή. Το εικονίδιο <br /> <br /> <img src=vpn_icon /> εμφανίζεται στο επάνω μέρος της οθόνης σας όταν είναι ενεργό το VPN."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"Η εφαρμογή <xliff:g id="APP">%s</xliff:g> επιθυμεί να ρυθμίσει μια σύνδεση VPN που της επιτρέπει να παρακολουθεί την επισκεψιμότητα του δικτύου. Αποδεχτείτε το αίτημα μόνο εάν εμπιστεύεστε την πηγή. Το εικονίδιο <br /> <br /> <img src=vpn_icon /> εμφανίζεται στην οθόνη σας όταν είναι ενεργό το VPN."</string> <string name="legacy_title" msgid="192936250066580964">"Το VPN συνδέθηκε"</string> <string name="session" msgid="6470628549473641030">"Περίοδος σύνδεσης"</string> <string name="duration" msgid="3584782459928719435">"Διάρκεια:"</string> diff --git a/packages/VpnDialogs/res/values-en-rAU/strings.xml b/packages/VpnDialogs/res/values-en-rAU/strings.xml index cb8b79d61ace..6ed50a7668ae 100644 --- a/packages/VpnDialogs/res/values-en-rAU/strings.xml +++ b/packages/VpnDialogs/res/values-en-rAU/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"Connection request"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> wants to set up a VPN connection that allows it to monitor network traffic. Only accept if you trust the source. <br /> <br /> <img src=vpn_icon /> appears at the top of your screen when VPN is active."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> wants to set up a VPN connection that allows it to monitor network traffic. Only accept if you trust the source. <br /> <br /> <img src=vpn_icon /> appears on your screen when VPN is active."</string> <string name="legacy_title" msgid="192936250066580964">"VPN is connected"</string> <string name="session" msgid="6470628549473641030">"Session:"</string> <string name="duration" msgid="3584782459928719435">"Duration:"</string> diff --git a/packages/VpnDialogs/res/values-en-rCA/strings.xml b/packages/VpnDialogs/res/values-en-rCA/strings.xml index cb8b79d61ace..6ed50a7668ae 100644 --- a/packages/VpnDialogs/res/values-en-rCA/strings.xml +++ b/packages/VpnDialogs/res/values-en-rCA/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"Connection request"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> wants to set up a VPN connection that allows it to monitor network traffic. Only accept if you trust the source. <br /> <br /> <img src=vpn_icon /> appears at the top of your screen when VPN is active."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> wants to set up a VPN connection that allows it to monitor network traffic. Only accept if you trust the source. <br /> <br /> <img src=vpn_icon /> appears on your screen when VPN is active."</string> <string name="legacy_title" msgid="192936250066580964">"VPN is connected"</string> <string name="session" msgid="6470628549473641030">"Session:"</string> <string name="duration" msgid="3584782459928719435">"Duration:"</string> diff --git a/packages/VpnDialogs/res/values-en-rGB/strings.xml b/packages/VpnDialogs/res/values-en-rGB/strings.xml index cb8b79d61ace..6ed50a7668ae 100644 --- a/packages/VpnDialogs/res/values-en-rGB/strings.xml +++ b/packages/VpnDialogs/res/values-en-rGB/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"Connection request"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> wants to set up a VPN connection that allows it to monitor network traffic. Only accept if you trust the source. <br /> <br /> <img src=vpn_icon /> appears at the top of your screen when VPN is active."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> wants to set up a VPN connection that allows it to monitor network traffic. Only accept if you trust the source. <br /> <br /> <img src=vpn_icon /> appears on your screen when VPN is active."</string> <string name="legacy_title" msgid="192936250066580964">"VPN is connected"</string> <string name="session" msgid="6470628549473641030">"Session:"</string> <string name="duration" msgid="3584782459928719435">"Duration:"</string> diff --git a/packages/VpnDialogs/res/values-en-rIN/strings.xml b/packages/VpnDialogs/res/values-en-rIN/strings.xml index cb8b79d61ace..6ed50a7668ae 100644 --- a/packages/VpnDialogs/res/values-en-rIN/strings.xml +++ b/packages/VpnDialogs/res/values-en-rIN/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"Connection request"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> wants to set up a VPN connection that allows it to monitor network traffic. Only accept if you trust the source. <br /> <br /> <img src=vpn_icon /> appears at the top of your screen when VPN is active."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> wants to set up a VPN connection that allows it to monitor network traffic. Only accept if you trust the source. <br /> <br /> <img src=vpn_icon /> appears on your screen when VPN is active."</string> <string name="legacy_title" msgid="192936250066580964">"VPN is connected"</string> <string name="session" msgid="6470628549473641030">"Session:"</string> <string name="duration" msgid="3584782459928719435">"Duration:"</string> diff --git a/packages/VpnDialogs/res/values-en-rXC/strings.xml b/packages/VpnDialogs/res/values-en-rXC/strings.xml index f5e2deb071a1..9d010e63518f 100644 --- a/packages/VpnDialogs/res/values-en-rXC/strings.xml +++ b/packages/VpnDialogs/res/values-en-rXC/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"Connection request"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> wants to set up a VPN connection that allows it to monitor network traffic. Only accept if you trust the source. <br /> <br /> <img src=vpn_icon /> appears at the top of your screen when VPN is active."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> wants to set up a VPN connection that allows it to monitor network traffic. Only accept if you trust the source. <br /> <br /> <img src=vpn_icon /> appears on your screen when VPN is active."</string> <string name="legacy_title" msgid="192936250066580964">"VPN is connected"</string> <string name="session" msgid="6470628549473641030">"Session:"</string> <string name="duration" msgid="3584782459928719435">"Duration:"</string> diff --git a/packages/VpnDialogs/res/values-es-rUS/strings.xml b/packages/VpnDialogs/res/values-es-rUS/strings.xml index 108a24e7930e..21cfc042e707 100644 --- a/packages/VpnDialogs/res/values-es-rUS/strings.xml +++ b/packages/VpnDialogs/res/values-es-rUS/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"Solicitud de conexión"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> quiere configurar una conexión VPN capaz de controlar el tráfico de la red. Acéptala solo si confías en la fuente. <br /> <br /> <img src=vpn_icon /> aparece en la parte superior de la pantalla cuando se activa la VPN."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> quiere configurar una conexión VPN que le permita supervisar el tráfico de red. Solo acéptala si confías en la fuente. <br /> <br /> <img src=vpn_icon /> aparecerá en tu pantalla cuando se active la VPN."</string> <string name="legacy_title" msgid="192936250066580964">"La VPN está conectada."</string> <string name="session" msgid="6470628549473641030">"Sesión:"</string> <string name="duration" msgid="3584782459928719435">"Duración:"</string> diff --git a/packages/VpnDialogs/res/values-es/strings.xml b/packages/VpnDialogs/res/values-es/strings.xml index 0eaf3592a510..372147f2479a 100644 --- a/packages/VpnDialogs/res/values-es/strings.xml +++ b/packages/VpnDialogs/res/values-es/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"Solicitud de conexión"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> quiere configurar una conexión VPN para controlar el tráfico de red. Solo debes aceptarla si confías en la fuente. <br /> <br /> <img src=vpn_icon /> aparece en la parte superior de la pantalla cuando se active la conexión VPN."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> quiere configurar una conexión VPN que le permita monitorizar el tráfico de red. Acéptalo solo si confías en la fuente. <br /> <br /> <img src=vpn_icon /> aparecerá en la pantalla cuando la VPN esté activa."</string> <string name="legacy_title" msgid="192936250066580964">"VPN conectada"</string> <string name="session" msgid="6470628549473641030">"Sesión:"</string> <string name="duration" msgid="3584782459928719435">"Duración:"</string> diff --git a/packages/VpnDialogs/res/values-et/strings.xml b/packages/VpnDialogs/res/values-et/strings.xml index 140c18311607..c328cd725396 100644 --- a/packages/VpnDialogs/res/values-et/strings.xml +++ b/packages/VpnDialogs/res/values-et/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"Ühendamise taotlus"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> tahab seadistada VPN-i ühenduse, mis võimaldab jälgida võrguliiklust. Nõustuge ainult siis, kui usaldate seda allikat. <br /> <br /> <img src=vpn_icon /> kuvatakse ekraani ülaservas, kui VPN on aktiivne."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> tahab seadistada VPN-i ühenduse, mis võimaldab jälgida võrguliiklust. Nõustuge ainult siis, kui usaldate seda allikat. <br /> <br /> <img src=vpn_icon /> kuvatakse ekraanil, kui VPN on aktiivne."</string> <string name="legacy_title" msgid="192936250066580964">"VPN on ühendatud"</string> <string name="session" msgid="6470628549473641030">"Seansid"</string> <string name="duration" msgid="3584782459928719435">"Kestus:"</string> diff --git a/packages/VpnDialogs/res/values-eu/strings.xml b/packages/VpnDialogs/res/values-eu/strings.xml index a27a66a86c9d..a3b7716e91d3 100644 --- a/packages/VpnDialogs/res/values-eu/strings.xml +++ b/packages/VpnDialogs/res/values-eu/strings.xml @@ -17,15 +17,14 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"Konektatzeko eskaera"</string> - <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> aplikazioak VPN bidezko konexioa ezarri nahi du sareko trafikoa kontrolatzeko. Iturburua fidagarria bada bakarrik baimendu. <br /> <br /> VPN bidezko konexioa aktibo dagoenean, <img src=vpn_icon /> agertuko da pantailaren goialdean."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> aplikazioak VPN bidezko konexio bat konfiguratu nahi du sareko trafikoa gainbegiratzeko. Onartu soilik iturburuaz fidatzen bazara. <br /> <br /> <img src=vpn_icon /> agertzen da pantailan, VPNa aktibo dagoenean."</string> + <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> aplikazioak VPN bidezko konexioa ezarri nahi du sareko trafikoa kontrolatzeko. Iturburua fidagarria bada bakarrik baimendu. <br /> <br /> VPN konexioa aktibo dagoenean, <img src=vpn_icon /> agertuko da pantailaren goialdean."</string> <string name="legacy_title" msgid="192936250066580964">"VPN sarera konektatuta dago"</string> <string name="session" msgid="6470628549473641030">"Saioa:"</string> <string name="duration" msgid="3584782459928719435">"Iraupena:"</string> <string name="data_transmitted" msgid="7988167672982199061">"Bidalita:"</string> <string name="data_received" msgid="4062776929376067820">"Jasota:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> byte / <xliff:g id="NUMBER_1">%2$s</xliff:g> pakete"</string> - <string name="always_on_disconnected_title" msgid="1906740176262776166">"Ezin da konektatu beti aktibatuta dagoen VPNa"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"Ezin da konektatu beti aktibatuta dagoen VPN sarea"</string> <string name="always_on_disconnected_message" msgid="555634519845992917">"Beti aktibatuta egoteko dago konfiguratuta <xliff:g id="VPN_APP_0">%1$s</xliff:g>, baina une honetan ezin da konektatu. <xliff:g id="VPN_APP_1">%1$s</xliff:g> sarera berriro konektatu ahal izan arte, sare publiko bat erabiliko du telefonoak."</string> <string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"Beti aktibatuta egoteko dago konfiguratuta <xliff:g id="VPN_APP">%1$s</xliff:g>, baina une honetan ezin da konektatu. VPN sarearen konexioa berreskuratu arte, ez duzu izango konexiorik."</string> <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> diff --git a/packages/VpnDialogs/res/values-fa/strings.xml b/packages/VpnDialogs/res/values-fa/strings.xml index 6fb5a001316e..56f847c15827 100644 --- a/packages/VpnDialogs/res/values-fa/strings.xml +++ b/packages/VpnDialogs/res/values-fa/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"درخواست اتصال"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> میخواهد یک اتصال VPN راهاندازی کند که به آن امکان نظارت بر ترافیک شبکه را میدهد. فقط در صورتی بپذیرید که به منبع آن اطمینان دارید. هنگامی که VPN فعال شد، <br /> <br /> <img src=vpn_icon /> در بالای صفحه نمایش شما نشان داده میشود."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> میخواهد یک اتصال VPN راهاندازی کند که به آن امکان نظارت بر ترافیک شبکه را میدهد. فقط درصورتیکه به منبع اعتماد دارید قبول کنید. وقتی VPN فعال باشد، <br /> <br /> <img src=vpn_icon /> در صفحهنمایش نشان داده میشود."</string> <string name="legacy_title" msgid="192936250066580964">"VPN متصل است"</string> <string name="session" msgid="6470628549473641030">"جلسه:"</string> <string name="duration" msgid="3584782459928719435">"مدت زمان:"</string> diff --git a/packages/VpnDialogs/res/values-fi/strings.xml b/packages/VpnDialogs/res/values-fi/strings.xml index 8abca06c2739..91c918af09c3 100644 --- a/packages/VpnDialogs/res/values-fi/strings.xml +++ b/packages/VpnDialogs/res/values-fi/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"Yhteyspyyntö"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> haluaa tehdä asetukset VPN-yhteydellä, jonka kautta sovellus voi valvoa verkkoliikennettä. Hyväksy vain, jos lähde on luotettava. <br /> <br /> <img src=vpn_icon /> näkyy ruudun yläreunassa, kun VPN on käytössä."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> haluaa muodostaa VPN-yhteyden, jonka avulla se voi valvoa verkkoliikennettä. Salli tämä vain, jos luotat lähteeseen. <br /> <br /> <img src=vpn_icon /> näkyy näytölläsi, kun VPN on aktiivinen."</string> <string name="legacy_title" msgid="192936250066580964">"VPN on yhdistetty"</string> <string name="session" msgid="6470628549473641030">"Käyttökerta"</string> <string name="duration" msgid="3584782459928719435">"Kesto:"</string> diff --git a/packages/VpnDialogs/res/values-fr-rCA/strings.xml b/packages/VpnDialogs/res/values-fr-rCA/strings.xml index 876111c26cdf..aa86c7ca8a7f 100644 --- a/packages/VpnDialogs/res/values-fr-rCA/strings.xml +++ b/packages/VpnDialogs/res/values-fr-rCA/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"Demande de connexion"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> veut configurer une connexion RPV qui permet de surveiller le trafic réseau. N\'acceptez que si vous faites confiance à la source. <br /><br /><img src=vpn_icon/> s\'affiche dans le haut de votre écran lorsqu\'une connexion RPV est active."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> veut configurer une connexion RPV qui permet de surveiller le trafic réseau. N\'acceptez que si vous faites confiance à la source. <br /> <br /> <img src=vpn_icon /> s\'affiche dans le haut de votre écran lorsqu\'une connexion RPV est active."</string> <string name="legacy_title" msgid="192936250066580964">"RPV connecté"</string> <string name="session" msgid="6470628549473641030">"Session :"</string> <string name="duration" msgid="3584782459928719435">"Durée :"</string> diff --git a/packages/VpnDialogs/res/values-fr/strings.xml b/packages/VpnDialogs/res/values-fr/strings.xml index 27ebfb01f098..71801197ddf2 100644 --- a/packages/VpnDialogs/res/values-fr/strings.xml +++ b/packages/VpnDialogs/res/values-fr/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"Demande de connexion"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> souhaite configurer une connexion VPN qui lui permet de surveiller le trafic réseau. N\'acceptez que si vous faites confiance à la source. <br /> <br /> <img src=vpn_icon /> s\'affiche en haut de votre écran lorsqu\'une connexion VPN est active."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> souhaite configurer une connexion VPN qui lui permet de surveiller le trafic réseau. N\'acceptez que si vous faites confiance à la source. <br /> <br /> <img src=vpn_icon /> s\'affiche à l\'écran lorsqu\'un VPN est actif."</string> <string name="legacy_title" msgid="192936250066580964">"VPN connecté"</string> <string name="session" msgid="6470628549473641030">"Session :"</string> <string name="duration" msgid="3584782459928719435">"Durée :"</string> diff --git a/packages/VpnDialogs/res/values-gl/strings.xml b/packages/VpnDialogs/res/values-gl/strings.xml index cd8ee8d89474..8a66d081a71b 100644 --- a/packages/VpnDialogs/res/values-gl/strings.xml +++ b/packages/VpnDialogs/res/values-gl/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"Solicitude de conexión"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> quere configurar unha conexión VPN que lle permite controlar o tráfico da rede. Acepta soamente se confías na fonte. <br /> <br /> <img src=vpn_icon /> aparece na parte superior da pantalla cando se activa a VPN."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"A aplicación <xliff:g id="APP">%s</xliff:g> quere configurar unha conexión VPN que lle permita supervisar o tráfico de rede. Acepta só se confías nela. <br /> <br /> <img src=vpn_icon /> aparece na pantalla cando a VPN está activa."</string> <string name="legacy_title" msgid="192936250066580964">"A VPN está conectada"</string> <string name="session" msgid="6470628549473641030">"Sesión:"</string> <string name="duration" msgid="3584782459928719435">"Duración:"</string> diff --git a/packages/VpnDialogs/res/values-gu/strings.xml b/packages/VpnDialogs/res/values-gu/strings.xml index 5ffdcb1d8079..961711c57c3d 100644 --- a/packages/VpnDialogs/res/values-gu/strings.xml +++ b/packages/VpnDialogs/res/values-gu/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"કનેક્શન વિનંતી"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> VPN કનેક્શન સેટ કરવા માગે છે જે તેને નેટવર્ક ટ્રાફિક મૉનિટર કરવાની મંજૂરી આપે છે. જો તમને સ્રોત પર વિશ્વાસ હોય તો જ સ્વીકારો. <br /> <br /> <img src=vpn_icon /> તમારી સ્ક્રીનની ટોચ પર ત્યારે દેખાય છે જ્યારે VPN સક્રિય હોય છે."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> એક એવું VPN કનેક્શન સેટ કરવા માગે છે કે જે તેને નેટવર્ક ટ્રાફિકનું નિરીક્ષણ કરવાની મંજૂરી આપતું હોય. જો તમને સૉર્સ પર વિશ્વાસ હોય તો જ સ્વીકારો. <br /> <br /> <img src=vpn_icon /> તમારી સ્ક્રીન પર ત્યારે દેખાય છે, જ્યારે VPN સક્રિય હોય છે."</string> <string name="legacy_title" msgid="192936250066580964">"VPN કનેક્ટ કરેલું છે"</string> <string name="session" msgid="6470628549473641030">"સત્ર:"</string> <string name="duration" msgid="3584782459928719435">"અવધિ:"</string> @@ -29,7 +28,7 @@ <string name="always_on_disconnected_message" msgid="555634519845992917">"<xliff:g id="VPN_APP_0">%1$s</xliff:g>ને હંમેશાં જોડાયેલ રહેવા માટે સેટ કરેલ છે, પરંતુ તે હાલમાં કનેક્ટ કરી શકાતું નથી. તમારો ફોન જ્યાં સુધી <xliff:g id="VPN_APP_1">%1$s</xliff:g> સાથે ફરીથી કનેક્ટ ન થાય ત્યાં સુધી તે સાર્વજનિક નેટવર્કનો ઉપયોગ કરશે."</string> <string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"<xliff:g id="VPN_APP">%1$s</xliff:g>ને હંમેશાં જોડાયેલ રહેવા માટે સેટ કરેલ છે, પરંતુ તે હાલમાં કનેક્ટ કરી શકાતું નથી. VPN ફરીથી કનેક્ટ ન થઈ શકે ત્યાં સુધી તમારી પાસે કોઈ કનેક્શન હશે નહીં."</string> <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> - <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"VPN સેટિંગ બદલો"</string> + <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"VPN સેટિંગ્સ બદલો"</string> <string name="configure" msgid="4905518375574791375">"ગોઠવો"</string> <string name="disconnect" msgid="971412338304200056">"ડિસ્કનેક્ટ કરો"</string> <string name="open_app" msgid="3717639178595958667">"ઍપ ખોલો"</string> diff --git a/packages/VpnDialogs/res/values-hi/strings.xml b/packages/VpnDialogs/res/values-hi/strings.xml index c9c65d5ac593..eed0858787d9 100644 --- a/packages/VpnDialogs/res/values-hi/strings.xml +++ b/packages/VpnDialogs/res/values-hi/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"कनेक्शन अनुरोध"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> वीपीएन कनेक्शन सेट अप करना चाहता है, जिससे वह नेटवर्क ट्रैफ़िक पर नज़र रख पाएगा. इसकी मंज़ूरी तभी दें जब आपको इस पर भरोसा हो. वीपीएन चालू होने पर <br /> <br /> <img src=vpn_icon /> आपकी स्क्रीन के सबसे ऊपर दिखाई देता है."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> को वीपीएन कनेक्शन सेट अप करने की अनुमति चाहिए. इससे वह नेटवर्क ट्रैफ़िक पर नज़र रख पाएगा. अनुमति तब दें, जब आपको ऐप्लिकेशन पर भरोसा हो. वीपीएन चालू होने पर, आपकी स्क्रीन पर <br /> <br /> <img src=vpn_icon /> दिखेगा."</string> <string name="legacy_title" msgid="192936250066580964">"VPN कनेक्ट है"</string> <string name="session" msgid="6470628549473641030">"सत्र:"</string> <string name="duration" msgid="3584782459928719435">"अवधि:"</string> diff --git a/packages/VpnDialogs/res/values-hr/strings.xml b/packages/VpnDialogs/res/values-hr/strings.xml index 576d99761571..aa9e436f56e7 100644 --- a/packages/VpnDialogs/res/values-hr/strings.xml +++ b/packages/VpnDialogs/res/values-hr/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"Zahtjev za povezivanje"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> želi postaviti VPN vezu pomoću koje će moći nadzirati mrežni promet. Prihvatite samo ako smatrate izvor pouzdanim. Kada je VPN aktivan, pri vrhu zaslona prikazuje se <br /> <br /> <img src=vpn_icon />."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"Aplikacija <xliff:g id="APP">%s</xliff:g> želi postaviti VPN vezu pomoću koje će moći nadzirati mrežni promet. Prihvatite samo ako smatrate izvor pouzdanim. Kad je VPN aktivan, na zaslonu se prikazuje ikona <br /> <br /> <img src=vpn_icon />."</string> <string name="legacy_title" msgid="192936250066580964">"VPN je spojen"</string> <string name="session" msgid="6470628549473641030">"Sesija"</string> <string name="duration" msgid="3584782459928719435">"Trajanje:"</string> diff --git a/packages/VpnDialogs/res/values-hu/strings.xml b/packages/VpnDialogs/res/values-hu/strings.xml index 69b999fee1e1..703aa792f3c3 100644 --- a/packages/VpnDialogs/res/values-hu/strings.xml +++ b/packages/VpnDialogs/res/values-hu/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"Kapcsolódási kérés"</string> <string name="warning" msgid="809658604548412033">"A(z) <xliff:g id="APP">%s</xliff:g> VPN kapcsolatot akar beállítani, amelynek segítségével figyelheti a hálózati forgalmat. Csak akkor fogadja el, ha megbízik a forrásban. <br /> <br /> Amikor a VPN aktív, <img src=vpn_icon /> ikon jelenik meg a képernyő tetején."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"A(z) <xliff:g id="APP">%s</xliff:g> alkalmazás VPN-kapcsolatot szeretne beállítani, amely segítségével figyelheti a hálózati forgalmat. Csak akkor fogadja el, ha megbízik a forrásban. <br /> <br /> Amikor aktív a VPN, a következő ikon látható a képernyőn: <img src=vpn_icon />."</string> <string name="legacy_title" msgid="192936250066580964">"A VPN csatlakoztatva van"</string> <string name="session" msgid="6470628549473641030">"Munkamenet:"</string> <string name="duration" msgid="3584782459928719435">"Időtartam:"</string> diff --git a/packages/VpnDialogs/res/values-hy/strings.xml b/packages/VpnDialogs/res/values-hy/strings.xml index d2a6d421592c..c296c8547283 100644 --- a/packages/VpnDialogs/res/values-hy/strings.xml +++ b/packages/VpnDialogs/res/values-hy/strings.xml @@ -17,8 +17,7 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"Միացման հայց"</string> - <string name="warning" msgid="809658604548412033">"«<xliff:g id="APP">%s</xliff:g>» հավելվածը ցանկանում է VPN կապ հաստատել՝ ցանցային երթևեկը հսկելու համար: Թույլատրեք, միայն եթե վստահում եք աղբյուրին։ Երբ VPN-ն ակտիվ լինի, ձեր էկրանի վերին հատվածում կհայտնվի <br /> <br /> <img src=vpn_icon /> պատկերը:"</string> - <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> հավելվածն ուզում է միանալ VPN-ի ցանցին՝ թրաֆիկին հետևելու համար։ Թույլատրեք, միայն եթե վստահում եք աղբյուրին։ Երբ VPN-ն ակտիվացված լինի, <br /> <br /> <img src=vpn_icon /> պատկերակը կհայտնվի ձեր էկրանին։"</string> + <string name="warning" msgid="809658604548412033">"«<xliff:g id="APP">%s</xliff:g>» հավելվածը ցանկանում է VPN կապ հաստատել՝ ցանցային երթևեկը հսկելու համար: Թույլատրեք, միայն եթե վստահում եք աղբյուրին: Երբ VPN-ն ակտիվ լինի, ձեր էկրանի վերին հատվածում կհայտնվի <br /> <br /> <img src=vpn_icon /> պատկերը:"</string> <string name="legacy_title" msgid="192936250066580964">"VPN-ը կապակցված է"</string> <string name="session" msgid="6470628549473641030">"Աշխատաշրջան`"</string> <string name="duration" msgid="3584782459928719435">"Տևողությունը՝"</string> @@ -26,7 +25,7 @@ <string name="data_received" msgid="4062776929376067820">"Ստացվել է՝"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> բայթ / <xliff:g id="NUMBER_1">%2$s</xliff:g> փաթեթ"</string> <string name="always_on_disconnected_title" msgid="1906740176262776166">"Չի հաջողվում միանալ միշտ միացված VPN-ին"</string> - <string name="always_on_disconnected_message" msgid="555634519845992917">"<xliff:g id="VPN_APP_0">%1$s</xliff:g>-ն այնպես է կարգավորված, որ միշտ միացած մնա, սակայն ներկայումս կապակցման խնդիր կա: Ձեր հեռախոսը կօգտագործի հանրային ցանցը, մինչև նորից կարողանա միանալ <xliff:g id="VPN_APP_1">%1$s</xliff:g>-ին։"</string> + <string name="always_on_disconnected_message" msgid="555634519845992917">"<xliff:g id="VPN_APP_0">%1$s</xliff:g>-ն այնպես է կարգավորված, որ միշտ միացած մնա, սակայն ներկայումս կապակցման խնդիր կա: Ձեր հեռախոսը կօգտագործի հանրային ցանցը, մինչև նորից կարողանա միանալ <xliff:g id="VPN_APP_1">%1$s</xliff:g>-ին:"</string> <string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"<xliff:g id="VPN_APP">%1$s</xliff:g>-ն այնպես է կարգավորված, որ միշտ միացած մնա, սակայն ներկայումս կապակցման խնդիր կա: Մինչև VPN-ը նորից չմիանա, դուք կապ չեք ունենա:"</string> <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"Փոխել VPN-ի կարգավորումները"</string> diff --git a/packages/VpnDialogs/res/values-in/strings.xml b/packages/VpnDialogs/res/values-in/strings.xml index 88a588c5eddc..18ef372a8cda 100644 --- a/packages/VpnDialogs/res/values-in/strings.xml +++ b/packages/VpnDialogs/res/values-in/strings.xml @@ -18,20 +18,19 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"Permintaan sambungan"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> ingin menyiapkan sambungan VPN yang memungkinkannya memantau traffic jaringan. Terima hanya jika Anda memercayai sumber. <br /> <br /> <img src=vpn_icon /> muncul di bagian atas layar Anda saat VPN aktif."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> ingin menyiapkan koneksi VPN yang memungkinkannya memantau traffic jaringan. Hanya terima jika Anda memercayai sumbernya. <br /> <br /> <img src=vpn_icon /> muncul di layar bila VPN aktif."</string> - <string name="legacy_title" msgid="192936250066580964">"VPN terhubung"</string> + <string name="legacy_title" msgid="192936250066580964">"VPN tersambung"</string> <string name="session" msgid="6470628549473641030">"Sesi:"</string> <string name="duration" msgid="3584782459928719435">"Durasi:"</string> <string name="data_transmitted" msgid="7988167672982199061">"Terkirim:"</string> <string name="data_received" msgid="4062776929376067820">"Diterima:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> bita / <xliff:g id="NUMBER_1">%2$s</xliff:g> paket"</string> - <string name="always_on_disconnected_title" msgid="1906740176262776166">"Tidak dapat terhubung ke VPN yang selalu aktif"</string> - <string name="always_on_disconnected_message" msgid="555634519845992917">"<xliff:g id="VPN_APP_0">%1$s</xliff:g> disiapkan untuk selalu terhubung, tetapi saat ini tidak dapat terhubung. Ponsel akan menggunakan jaringan publik sampai dapat terhubung ulang ke <xliff:g id="VPN_APP_1">%1$s</xliff:g>."</string> - <string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"<xliff:g id="VPN_APP">%1$s</xliff:g> disiapkan untuk selalu terhubung, tetapi saat ini tidak dapat terhubung. Anda akan terhubung jika VPN dapat terhubung ulang."</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"Tidak dapat tersambung ke VPN yang selalu aktif"</string> + <string name="always_on_disconnected_message" msgid="555634519845992917">"<xliff:g id="VPN_APP_0">%1$s</xliff:g> disiapkan untuk selalu tersambung, tetapi saat ini tidak dapat tersambung. Ponsel akan menggunakan jaringan publik sampai dapat tersambung ulang ke <xliff:g id="VPN_APP_1">%1$s</xliff:g>."</string> + <string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"<xliff:g id="VPN_APP">%1$s</xliff:g> disiapkan untuk selalu tersambung, tetapi saat ini tidak dapat tersambung. Anda akan tersambung jika VPN dapat tersambung ulang."</string> <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"Ubah setelan VPN"</string> <string name="configure" msgid="4905518375574791375">"Konfigurasikan"</string> - <string name="disconnect" msgid="971412338304200056">"Putuskan koneksi"</string> + <string name="disconnect" msgid="971412338304200056">"Putuskan sambungan"</string> <string name="open_app" msgid="3717639178595958667">"Buka aplikasi"</string> <string name="dismiss" msgid="6192859333764711227">"Tutup"</string> </resources> diff --git a/packages/VpnDialogs/res/values-is/strings.xml b/packages/VpnDialogs/res/values-is/strings.xml index a75371d77951..70fb40fc467c 100644 --- a/packages/VpnDialogs/res/values-is/strings.xml +++ b/packages/VpnDialogs/res/values-is/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"Beiðni um tengingu"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> vill setja upp VPN-tengingu til þess að geta fylgst með netumferð. Samþykktu þetta aðeins ef þú treystir upprunanum. <br /> <br /> <img src=vpn_icon /> birtist efst á skjánum þegar VPN er virkt."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> vill setja upp VPN-tengingu til að fylgjast með netumferð. Ekki samþykkja þú treystir upprunanum. <br /> <br /> <img src=vpn_icon /> birtist á skjánum hjá þér þegar VPN er virkt."</string> <string name="legacy_title" msgid="192936250066580964">"VPN er tengt"</string> <string name="session" msgid="6470628549473641030">"Lota:"</string> <string name="duration" msgid="3584782459928719435">"Tímalengd:"</string> diff --git a/packages/VpnDialogs/res/values-it/strings.xml b/packages/VpnDialogs/res/values-it/strings.xml index c443c510198e..2602493faf00 100644 --- a/packages/VpnDialogs/res/values-it/strings.xml +++ b/packages/VpnDialogs/res/values-it/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"Richiesta di connessione"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> vuole impostare una connessione VPN che le consenta di monitorare il traffico di rete. Accetta soltanto se ritieni la fonte attendibile. Quando la connessione VPN è attiva, nella parte superiore dello schermo viene visualizzata l\'icona <br /> <br /> <img src=vpn_icon />."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> vuole configurare una connessione VPN che le consenta di monitorare il traffico di rete. Accetta soltanto se ritieni la fonte attendibile. Quando la connessione VPN è attiva, sullo schermo viene visualizzata l\'icona <br /> <br /> <img src=vpn_icon />."</string> <string name="legacy_title" msgid="192936250066580964">"VPN connessa"</string> <string name="session" msgid="6470628549473641030">"Sessione:"</string> <string name="duration" msgid="3584782459928719435">"Durata:"</string> diff --git a/packages/VpnDialogs/res/values-iw/strings.xml b/packages/VpnDialogs/res/values-iw/strings.xml index 81903d2b2442..ebabd4e71aef 100644 --- a/packages/VpnDialogs/res/values-iw/strings.xml +++ b/packages/VpnDialogs/res/values-iw/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"בקשת חיבור"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> רוצה להגדיר חיבור VPN שיאפשר לו לפקח על תעבורת הרשת. אשר את הבקשה רק אם אתה נותן אמון במקור. <br /> <br /> <img src=vpn_icon /> מופיע בחלק העליון של המסך כאשר VPN פעיל."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"האפליקציה <xliff:g id="APP">%s</xliff:g> מבקשת להגדיר חיבור VPN שבאמצעותו היא תנהל מעקב אחר התנועה ברשת. יש לאשר את הבקשה רק אם המקור נראה לך אמין. <br /> <br /> <img src=vpn_icon /> מופיע על המסך כאשר חיבור ה-VPN פעיל."</string> <string name="legacy_title" msgid="192936250066580964">"VPN מחובר"</string> <string name="session" msgid="6470628549473641030">"הפעלה"</string> <string name="duration" msgid="3584782459928719435">"משך:"</string> diff --git a/packages/VpnDialogs/res/values-ja/strings.xml b/packages/VpnDialogs/res/values-ja/strings.xml index e03e9d38087b..8480692e9dd3 100644 --- a/packages/VpnDialogs/res/values-ja/strings.xml +++ b/packages/VpnDialogs/res/values-ja/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"接続リクエスト"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> がネットワーク トラフィックを監視するため VPN 接続をセットアップしようとしています。信頼できるソースである場合にのみ許可してください。<br /> <br /> VPN がアクティブになると画面の上部に <img src=vpn_icon /> が表示されます。"</string> - <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> は、ネットワーク トラフィックを監視できるよう、VPN 接続を設定するよう求めています。ソースを信頼できる場合のみ、許可してください。VPN が有効になると、画面に <br /> <br /> <img src=vpn_icon /> が表示されます。"</string> <string name="legacy_title" msgid="192936250066580964">"VPN接続済み"</string> <string name="session" msgid="6470628549473641030">"セッション:"</string> <string name="duration" msgid="3584782459928719435">"期間:"</string> diff --git a/packages/VpnDialogs/res/values-ka/strings.xml b/packages/VpnDialogs/res/values-ka/strings.xml index 9c4388e0e30e..e5a07532c32e 100644 --- a/packages/VpnDialogs/res/values-ka/strings.xml +++ b/packages/VpnDialogs/res/values-ka/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"კავშირის მოთხოვნა"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> სურს დააყენოს VPN კავშირი, რაც ქსელის ტრაფიკის მონიტორინგის საშუალებას იძლევა. მიიღოთ მხოლოდ ისეთ შემთხვევაში, თუ წყაროს ენდობით. <br /> <br /> <img src=vpn_icon /> თქვენი ეკრანის სიის თავში გამოჩნდება, როდესაც VPN აქტიურია."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g>-ს სურს დააყენოს VPN კავშირი, რაც ქსელის ტრაფიკის მონიტორინგის საშუალებას იძლევა. დათანხმდით მხოლოდ იმ შემთხვევაში, თუ წყაროს ენდობით. <br /> <br /> <img src=vpn_icon /> თქვენს ეკრანზე გამოჩნდება, როდესაც VPN აქტიურია."</string> <string name="legacy_title" msgid="192936250066580964">"VPN დაკავშირებულია"</string> <string name="session" msgid="6470628549473641030">"სესია:"</string> <string name="duration" msgid="3584782459928719435">"ხანგრძლივობა:"</string> diff --git a/packages/VpnDialogs/res/values-kk/strings.xml b/packages/VpnDialogs/res/values-kk/strings.xml index 9a499d346ef7..79f79c34e1b4 100644 --- a/packages/VpnDialogs/res/values-kk/strings.xml +++ b/packages/VpnDialogs/res/values-kk/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"Байланысты сұрау"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> VPN байланысын орнатқысы келеді, бұл оған желілік трафикті бақылауға мүмкіндік береді. Көзге сенсеңіз ғана қабылдаңыз. VPN белсенді болғанда экранның жоғарғы жағында <br /> <br /> <img src=vpn_icon /> көрсетіледі."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> қолданбасы VPN байланысын орнатқысы келеді, бұл оған желі трафигін бақылауға мүмкіндік береді. Сұрауды қабылдамас бұрын, дереккөздің сенімді екеніне көз жеткізіңіз. VPN белсенді болған кезде, экранда <br /> <br /> <img src=vpn_icon /> белгішесі пайда болады."</string> <string name="legacy_title" msgid="192936250066580964">"ВЖЖ қосылған"</string> <string name="session" msgid="6470628549473641030">"Сессия:"</string> <string name="duration" msgid="3584782459928719435">"Ұзақтығы:"</string> diff --git a/packages/VpnDialogs/res/values-km/strings.xml b/packages/VpnDialogs/res/values-km/strings.xml index 0ed2e84b80fa..06f34dbf2733 100644 --- a/packages/VpnDialogs/res/values-km/strings.xml +++ b/packages/VpnDialogs/res/values-km/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"សំណើសុំការតភ្ជាប់"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> ចង់បង្កើតការតភ្ជាប់ VPN ដែលអនុញ្ញាតឲ្យវាត្រួតពិនិត្យចរាចរបណ្ដាញ។ ព្រមទទួល ប្រសិនបើអ្នកទុកចិត្តលើប្រភពតែប៉ុណ្ណោះ។ <br /> <br /> <img src=vpn_icon /> នឹងលេចឡើងនៅផ្នែកខាងលើនៃអេក្រង់របស់អ្នក ពេល VPN សកម្ម។"</string> - <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> ចង់រៀបចំការតភ្ជាប់ VPN ដែលអនុញ្ញាតឱ្យវាត្រួតពិនិត្យចរាចរណ៍បណ្តាញ។ យល់ព្រម ប្រសិនបើអ្នកជឿទុកចិត្តលើប្រភពនេះតែប៉ុណ្ណោះ។ <br /> <br /> <img src=vpn_icon /> បង្ហាញនៅលើអេក្រង់របស់អ្នក នៅពេល VPN កំពុងដំណើរការ។"</string> <string name="legacy_title" msgid="192936250066580964">"បានភ្ជាប់ VPN"</string> <string name="session" msgid="6470628549473641030">"សម័យ៖"</string> <string name="duration" msgid="3584782459928719435">"ថិរវេលា៖"</string> diff --git a/packages/VpnDialogs/res/values-kn/strings.xml b/packages/VpnDialogs/res/values-kn/strings.xml index 6308f1844bfd..040cd6c5aeda 100644 --- a/packages/VpnDialogs/res/values-kn/strings.xml +++ b/packages/VpnDialogs/res/values-kn/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"ಸಂಪರ್ಕ ವಿನಂತಿ"</string> <string name="warning" msgid="809658604548412033">"ನೆಟ್ವರ್ಕ್ ಟ್ರಾಫಿಕ್ ಅನ್ನು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಲು ಅನುಮತಿಸುವಂತಹ VPN ಸಂಪರ್ಕವನ್ನು ಹೊಂದಿಸಲು <xliff:g id="APP">%s</xliff:g> ಬಯಸುತ್ತದೆ. ನೀವು ಮೂಲವನ್ನು ನಂಬಿದರೆ ಮಾತ್ರ ಸಮ್ಮತಿಸಿ. VPN ಸಕ್ರಿಯವಾಗಿರುವಾಗ ನಿಮ್ಮ ಪರದೆಯ ಮೇಲ್ಭಾಗದಲ್ಲಿ <br /> <br /> <img src=vpn_icon /> ಗೋರಿಸುತ್ತದೆ."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"ನೆಟ್ವರ್ಕ್ ಟ್ರಾಫಿಕ್ ಅನ್ನು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಲು ಅನುಮತಿಸುವಂತಹ VPN ಸಂಪರ್ಕವನ್ನು ಹೊಂದಿಸಲು <xliff:g id="APP">%s</xliff:g> ಬಯಸುತ್ತದೆ. ನಿಮಗೆ ಮೂಲದ ಮೇಲೆ ನಂಬಿಕೆ ಇದ್ದರೆ ಮಾತ್ರ ಸ್ವೀಕರಿಸಿ. <br /> <br /> <img src=vpn_icon /> VPN ಸಕ್ರಿಯವಾದ ನಂತರ, ನಿಮ್ಮ ಸ್ಕ್ರೀನ್ ಮೇಲೆ ಗೋಚರಿಸುತ್ತದೆ."</string> <string name="legacy_title" msgid="192936250066580964">"VPN ಸಂಪರ್ಕಗೊಂಡಿದೆ"</string> <string name="session" msgid="6470628549473641030">"ಸೆಷನ್:"</string> <string name="duration" msgid="3584782459928719435">"ಅವಧಿ:"</string> diff --git a/packages/VpnDialogs/res/values-ko/strings.xml b/packages/VpnDialogs/res/values-ko/strings.xml index 6e179bb9bcb0..6ad497680ae7 100644 --- a/packages/VpnDialogs/res/values-ko/strings.xml +++ b/packages/VpnDialogs/res/values-ko/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"연결 요청"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g>에서 네트워크 트래픽을 모니터링하도록 허용하는 VPN 연결을 설정하려고 합니다. 출처를 신뢰할 수 있는 경우에만 수락하세요. VPN이 활성화되면 <br /> <br /> <img src=vpn_icon />이 화면 위에 표시됩니다."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g>에서 네트워크 트래픽을 모니터링할 수 있도록 VPN 연결을 설정하려고 합니다. 소스를 신뢰할 수 있는 경우에만 수락하세요. VPN이 활성 상태일 때는 <br /> <br /> <img src=vpn_icon /> 아이콘이 화면에 표시됩니다."</string> <string name="legacy_title" msgid="192936250066580964">"VPN이 연결되었습니다."</string> <string name="session" msgid="6470628549473641030">"세션:"</string> <string name="duration" msgid="3584782459928719435">"기간:"</string> diff --git a/packages/VpnDialogs/res/values-ky/strings.xml b/packages/VpnDialogs/res/values-ky/strings.xml index 31f9e2da11c7..23c9be8819a8 100644 --- a/packages/VpnDialogs/res/values-ky/strings.xml +++ b/packages/VpnDialogs/res/values-ky/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"Туташуу сурамы"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> тармактык трафикти көзөмөлдөөгө уруксат берген VPN туташуусун орноткусу келет. Аны булакка ишенсеңиз гана кабыл алыңыз. <br /> <br /> <img src=vpn_icon /> VPN иштеп турганда экраныңыздын жогору жагынан көрүнөт."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> тармак трафигин көзөмөлдөөгө уруксат берген VPN байланышын орноткусу келет. Булакка ишенсеңиз гана кабыл алыңыз. VPN иштеп жатканда, экраныңызда <br /> <br /> &It;img src=vpn_icon /> көрүнөт."</string> <string name="legacy_title" msgid="192936250066580964">"VPN байланышта"</string> <string name="session" msgid="6470628549473641030">"Сессия:"</string> <string name="duration" msgid="3584782459928719435">"Узактыгы:"</string> diff --git a/packages/VpnDialogs/res/values-lo/strings.xml b/packages/VpnDialogs/res/values-lo/strings.xml index cec69f0fe9c0..c591308480c1 100644 --- a/packages/VpnDialogs/res/values-lo/strings.xml +++ b/packages/VpnDialogs/res/values-lo/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"ການຮ້ອງຂໍການເຊື່ອມຕໍ່"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> ຕ້ອງການຕັ້ງຄ່າການເຊື່ອມຕໍ່ VPN ທີ່ອະນຸຍາດໃຫ້ຕິດຕາມທຣາບຟິກເຄືອຂ່າຍໄດ້. ທ່ານຄວນຍິນຍອມສະເພາະໃນກໍລະນີທີ່ທ່ານເຊື່ອຖືແຫລ່ງຂໍ້ມູນເທົ່ານັ້ນ. <br /> <br /> <img src=vpn_icon /> ຈະປາກົດຢູ່ດ້ານເທິງຂອງໜ້າຈໍເມື່ອມີການເປີດໃຊ້ VPN."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> ຕ້ອງການຕັ້ງຄ່າການເຊື່ອມຕໍ່ VPN ທີ່ອະນຸຍາດໃຫ້ມັນກວດກາການຈາລະຈອນເຄືອຂ່າຍໄດ້. ໃຫ້ຍອມຮັບສະເພາະໃນກໍລະນີທີ່ທ່ານເຊື່ອຖືແຫຼ່ງທີ່ມາເທົ່ານັ້ນ. <br /> <br /> <img src=vpn_icon /> ຈະປາກົດຢູ່ໜ້າຈໍຂອງທ່ານເມື່ອເປີດໃຊ້ VPN."</string> <string name="legacy_title" msgid="192936250066580964">"ເຊື່ອມຕໍ່ VPN ແລ້ວ"</string> <string name="session" msgid="6470628549473641030">"ເຊສຊັນ:"</string> <string name="duration" msgid="3584782459928719435">"ໄລຍະເວລາ:"</string> diff --git a/packages/VpnDialogs/res/values-lt/strings.xml b/packages/VpnDialogs/res/values-lt/strings.xml index 97abd0d66eb3..8846310730ce 100644 --- a/packages/VpnDialogs/res/values-lt/strings.xml +++ b/packages/VpnDialogs/res/values-lt/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"Ryšio užklausa"</string> <string name="warning" msgid="809658604548412033">"„<xliff:g id="APP">%s</xliff:g>“ nori nustatyti VPN ryšį, kad galėtų stebėti tinklo srautą. Sutikite, tik jei pasitikite šaltiniu. <br /> <br /> <img src=vpn_icon /> rodoma ekrano viršuje, kai VPN aktyvus."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"Programa „<xliff:g id="APP">%s</xliff:g>“ nori nustatyti VPN ryšį, kad galėtų stebėti tinklo srautą. Sutikite, tik jei pasitikite šaltiniu. <br /> <br /> <img src=vpn_icon /> piktograma rodoma ekrane, kai VPN aktyvus."</string> <string name="legacy_title" msgid="192936250066580964">"VPN prijungtas"</string> <string name="session" msgid="6470628549473641030">"Sesija"</string> <string name="duration" msgid="3584782459928719435">"Trukmė:"</string> diff --git a/packages/VpnDialogs/res/values-lv/strings.xml b/packages/VpnDialogs/res/values-lv/strings.xml index 6341fbdf0158..07625b6173c6 100644 --- a/packages/VpnDialogs/res/values-lv/strings.xml +++ b/packages/VpnDialogs/res/values-lv/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"Savienojuma pieprasījums"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> vēlas izveidot VPN savienojumu, kas ļaus pārraudzīt tīkla datplūsmu. Piekrītiet tikai tad, ja uzticaties avotam. <br /> <br /> <img src=vpn_icon /> tiek rādīta ekrāna augšdaļā, kad darbojas VPN."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"Lietotne <xliff:g id="APP">%s</xliff:g> vēlas izveidot VPN savienojumu, kas ļaus pārraudzīt tīkla datplūsmu. Piekrītiet tikai tad, ja uzticaties avotam. <br /> <br /> Ekrānā tiek rādīta ikona <img src=vpn_icon />, kad darbojas VPN."</string> <string name="legacy_title" msgid="192936250066580964">"Ir izveidots savienojums ar VPN"</string> <string name="session" msgid="6470628549473641030">"Sesija:"</string> <string name="duration" msgid="3584782459928719435">"Ilgums:"</string> diff --git a/packages/VpnDialogs/res/values-mk/strings.xml b/packages/VpnDialogs/res/values-mk/strings.xml index 689d028fd724..b5a64f213066 100644 --- a/packages/VpnDialogs/res/values-mk/strings.xml +++ b/packages/VpnDialogs/res/values-mk/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"Барање за поврзување"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> сака да постави поврзување со ВПН коешто му дозволува да го набљудува сообраќајот на мрежата. Прифатете само доколку му верувате на изворот. <br /> <br /> <img src=vpn_icon /> се појавува на врвот на екранот кога ВПН е активна."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> сака да постави поврзување со VPN што ќе дозволи да го набљудува сообраќајот на мрежата. Прифатете само ако му верувате на изворот. <br /> <br /> <img src=vpn_icon /> ќе се појави на екранот кога ќе се активира VPN."</string> <string name="legacy_title" msgid="192936250066580964">"VPN е поврзана"</string> <string name="session" msgid="6470628549473641030">"Сесија:"</string> <string name="duration" msgid="3584782459928719435">"Времетраење:"</string> @@ -31,7 +30,7 @@ <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"Променете ги поставките за VPN"</string> <string name="configure" msgid="4905518375574791375">"Конфигурирај"</string> - <string name="disconnect" msgid="971412338304200056">"Прекини врска"</string> + <string name="disconnect" msgid="971412338304200056">"Исклучи"</string> <string name="open_app" msgid="3717639178595958667">"Отвори ја апликацијата"</string> <string name="dismiss" msgid="6192859333764711227">"Отфрли"</string> </resources> diff --git a/packages/VpnDialogs/res/values-ml/strings.xml b/packages/VpnDialogs/res/values-ml/strings.xml index 8284a78c26f8..680d0ef539b7 100644 --- a/packages/VpnDialogs/res/values-ml/strings.xml +++ b/packages/VpnDialogs/res/values-ml/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"കണക്ഷൻ അഭ്യർത്ഥന"</string> <string name="warning" msgid="809658604548412033">"നെറ്റ്വർക്ക് ട്രാഫിക്ക് നിരീക്ഷിക്കാൻ അനുവദിക്കുന്ന ഒരു VPN കണക്ഷൻ <xliff:g id="APP">%s</xliff:g> സജ്ജീകരിക്കേണ്ടതുണ്ട്. ഉറവിടം പരിചിതമാണെങ്കിൽ മാത്രം അംഗീകരിക്കുക. VPN സജീവമാകുമ്പോൾ <br /> <br /> <img src=vpn_icon /> നിങ്ങളുടെ സ്ക്രീനിന്റെ മുകളിൽ ദൃശ്യമാകുന്നു."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"നെറ്റ്വർക്ക് ട്രാഫിക് നിരീക്ഷിക്കാൻ അനുവദിക്കുന്ന ഒരു VPN കണക്ഷൻ സജ്ജീകരിക്കാൻ <xliff:g id="APP">%s</xliff:g> താൽപ്പര്യപ്പെടുന്നു. നിങ്ങൾ ഉറവിടം വിശ്വസിക്കുന്നുണ്ടെങ്കിൽ മാത്രം അംഗീകരിക്കുക. VPN സജീവമാകുമ്പോൾ <br /> <br /> <img src=vpn_icon /> നിങ്ങളുടെ സ്ക്രീനിൽ ദൃശ്യമാകും."</string> <string name="legacy_title" msgid="192936250066580964">"VPN കണക്റ്റുചെയ്തു"</string> <string name="session" msgid="6470628549473641030">"സെഷൻ:"</string> <string name="duration" msgid="3584782459928719435">"സമയദൈര്ഘ്യം:"</string> diff --git a/packages/VpnDialogs/res/values-mn/strings.xml b/packages/VpnDialogs/res/values-mn/strings.xml index 1dd4c15c43bb..9aa104aff5ab 100644 --- a/packages/VpnDialogs/res/values-mn/strings.xml +++ b/packages/VpnDialogs/res/values-mn/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"Холболтын хүсэлт"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> нь сүлжээний трафикыг хянах боломж бүхий VPN холболт үүсгэхийг хүсэж байна. Та зөвхөн эх үүсвэрт итгэж байгаа бол зөвшөөрнө үү. <br /> <br /> <img src=vpn_icon /> таны дэлгэц дээр VPN идэвхтэй үед гарч ирнэ."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> нь түүнд сүлжээний ачааллыг хянах боломжийг олгодог VPN холболт тохируулахыг хүсэж байна. Зөвхөн та эх сурвалжид итгэдэг тохиолдолд зөвшөөрнө үү. VPN идэвхтэй үед таны дэлгэц дээр <br /> <br /> <img src=vpn_icon /> харагдана."</string> <string name="legacy_title" msgid="192936250066580964">"VPN холбогдов"</string> <string name="session" msgid="6470628549473641030">"Сешн:"</string> <string name="duration" msgid="3584782459928719435">"Үргэлжлэх хугацаа:"</string> diff --git a/packages/VpnDialogs/res/values-mr/strings.xml b/packages/VpnDialogs/res/values-mr/strings.xml index 22fb502129a5..41d74290815d 100644 --- a/packages/VpnDialogs/res/values-mr/strings.xml +++ b/packages/VpnDialogs/res/values-mr/strings.xml @@ -18,19 +18,18 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"कनेक्शन विनंती"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> नेटवर्क रहदारीचे परीक्षण करण्यासाठी त्यास अनुमती देणारे VPN कनेक्शन सेट करू इच्छितो. तुम्हाला स्रोत विश्वसनीय वाटत असेल तरच स्वीकार करा. <br /> <br /> <img src=vpn_icon /> VPN सक्रिय असताना आपल्या स्क्रीनच्या शीर्षावर दिसते."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> ला नेटवर्क ट्रॅफिकवर लक्ष ठेवण्याची अनुमती देणारे VPN कनेक्शन सेट करायचे आहे. तुमचा स्रोतावर विश्वास असेल तरच स्वीकारा. VPN अॅक्टिव्ह असल्यास, तुमच्या स्क्रीनवर <br /> <br /> <img src=vpn_icon /> दिसते."</string> <string name="legacy_title" msgid="192936250066580964">"VPN कनेक्ट केले"</string> <string name="session" msgid="6470628549473641030">"सत्र:"</string> <string name="duration" msgid="3584782459928719435">"कालावधी:"</string> <string name="data_transmitted" msgid="7988167672982199061">"प्रेषित:"</string> <string name="data_received" msgid="4062776929376067820">"प्राप्त झाले:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> बाइट / <xliff:g id="NUMBER_1">%2$s</xliff:g> पॅकेट"</string> - <string name="always_on_disconnected_title" msgid="1906740176262776166">"कायम सुरू असलेल्या VPN शी कनेक्ट करू शकत नाही"</string> + <string name="always_on_disconnected_title" msgid="1906740176262776166">"कायम चालू असलेल्या VPN शी कनेक्ट करू शकत नाही"</string> <string name="always_on_disconnected_message" msgid="555634519845992917">"<xliff:g id="VPN_APP_0">%1$s</xliff:g> हे पूर्ण वेळ कनेक्ट राहण्यासाठी सेट अप केलेले आहे, पण हे आता कनेक्ट होऊ शकत नाही. <xliff:g id="VPN_APP_1">%1$s</xliff:g> शी पुन्हा कनेक्ट होईपर्यंत तुमचा फोन सार्वजनिक नेटवर्क वापरेल."</string> <string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"<xliff:g id="VPN_APP">%1$s</xliff:g> हे पूर्ण वेळ कनेक्ट राहण्यासाठी सेट अप केलेले आहे, पण हे आता कनेक्ट होऊ शकत नाही. VPN पुन्हा कनेक्ट होईपर्यंत तुमच्याकडे कनेक्शन नसेल."</string> <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"VPN सेटिंग्ज बदला"</string> - <string name="configure" msgid="4905518375574791375">"कॉंफिगर करा"</string> + <string name="configure" msgid="4905518375574791375">"कॉन्फिगर करा"</string> <string name="disconnect" msgid="971412338304200056">"डिस्कनेक्ट करा"</string> <string name="open_app" msgid="3717639178595958667">"अॅप उघडा"</string> <string name="dismiss" msgid="6192859333764711227">"डिसमिस करा"</string> diff --git a/packages/VpnDialogs/res/values-ms/strings.xml b/packages/VpnDialogs/res/values-ms/strings.xml index c9961d2654e2..b489f2edabc0 100644 --- a/packages/VpnDialogs/res/values-ms/strings.xml +++ b/packages/VpnDialogs/res/values-ms/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"Permintaan sambungan"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> ingin menyediakan sambungan VPN yang membenarkan apl memantau trafik rangkaian. Terima hanya jika anda mempercayai sumber. <br /> <br /> <img src=vpn_icon /> terpapar pada bahagian atas skrin anda apabila VPN aktif."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> ingin menyediakan sambungan VPN yang membenarkan apl tersebut memantau trafik rangkaian. Hanya terima jika anda mempercayai sumber tersebut. <br /> <br /> <img src=vpn_icon /> muncul pada skrin anda apabila VPN aktif."</string> <string name="legacy_title" msgid="192936250066580964">"VPN telah disambungkan"</string> <string name="session" msgid="6470628549473641030">"Sesi:"</string> <string name="duration" msgid="3584782459928719435">"Tempoh:"</string> diff --git a/packages/VpnDialogs/res/values-my/strings.xml b/packages/VpnDialogs/res/values-my/strings.xml index 36348c8b5c8c..9d60ff42a7cd 100644 --- a/packages/VpnDialogs/res/values-my/strings.xml +++ b/packages/VpnDialogs/res/values-my/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"ချိတ်ဆက်ရန် တောင်းဆိုချက်"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> က ကွန်ရက် လုပ်ငန်းကို စောင့်ကြည့်ခွင့် ပြုမည့် VPN ချိတ်ဆက်မှုကို ထူထောင်လိုသည်။ ရင်းမြစ်ကို သင်က ယုံကြည်မှသာ လက်ခံပါ။ <br /> <br /> <img src=vpn_icon /> မှာ VPN အလုပ်လုပ်နေလျှင် သင်၏ မျက်နှာပြင် ထိပ်မှာ ပေါ်လာမည်။"</string> - <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> က ကွန်ရက်ဒေတာ စီးဆင်းမှုကို စောင့်ကြည့်ရန် ခွင့်ပြုသည့် VPN ချိတ်ဆက်မှုကို စနစ်ထည့်သွင်းလိုသည်။ ဤရင်းမြစ်ကို သင်ယုံကြည်မှသာ လက်ခံပါ။ <br /> <br /> <img src=vpn_icon /> သည် VPN ဖွင့်ထားသောအခါ သင့်ဖန်သားပြင်တွင် ပေါ်ပါသည်။"</string> <string name="legacy_title" msgid="192936250066580964">"VPNနှင့်ချိတ်ဆက်ထားသည်"</string> <string name="session" msgid="6470628549473641030">"သတ်မှတ်ပေးထားသည့်အချိန်:"</string> <string name="duration" msgid="3584782459928719435">"အချိန်ကာလ-"</string> @@ -31,7 +30,7 @@ <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"VPN ဆက်တင်များ ပြောင်းရန်"</string> <string name="configure" msgid="4905518375574791375">"ပုံပေါ်စေသည်"</string> - <string name="disconnect" msgid="971412338304200056">"ချိတ်ဆက်မှုဖြုတ်ရန်"</string> + <string name="disconnect" msgid="971412338304200056">"ချိတ်ဆက်ခြင်းရပ်ရန်"</string> <string name="open_app" msgid="3717639178595958667">"အက်ပ်ကို ဖွင့်ရန်"</string> <string name="dismiss" msgid="6192859333764711227">"ပယ်ရန်"</string> </resources> diff --git a/packages/VpnDialogs/res/values-nb/strings.xml b/packages/VpnDialogs/res/values-nb/strings.xml index 14c84d702712..be572d4408f8 100644 --- a/packages/VpnDialogs/res/values-nb/strings.xml +++ b/packages/VpnDialogs/res/values-nb/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"Tilkoblingsforespørsel"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> ønsker å bruke en VPN-tilkobling som tillater at appen overvåker nettverkstrafikken. Du bør bare godta dette hvis du stoler på kilden. <br /> <br /> <img src=vpn_icon /> vises øverst på skjermen din når VPN er aktivert."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> vil konfigurere en VPN-tilkobling som lar appen overvåke nettverkstrafikk. Du bør bare godta dette hvis du stoler på kilden. <br /> <br /> <img src=vpn_icon /> vises på skjermen når VPN er aktivert."</string> <string name="legacy_title" msgid="192936250066580964">"VPN er tilkoblet"</string> <string name="session" msgid="6470628549473641030">"Økt:"</string> <string name="duration" msgid="3584782459928719435">"Varighet:"</string> diff --git a/packages/VpnDialogs/res/values-ne/strings.xml b/packages/VpnDialogs/res/values-ne/strings.xml index 2a5648d147c1..b716c35cfad4 100644 --- a/packages/VpnDialogs/res/values-ne/strings.xml +++ b/packages/VpnDialogs/res/values-ne/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"जडान अनुरोध"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> ले नेटवर्क यातायात अनुगमन गर्न अनुमति दिने VPN जडान स्थापना गर्न चाहन्छ। तपाईँले स्रोत भरोसा छ भने मात्र स्वीकार गर्नुहोस्। <br /> <br /> <img src=vpn_icon /> जब VPN सक्रिय हुन्छ आफ्नो स्क्रिनको माथि देखा पर्छन्।"</string> - <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> ले कुनै VPN कनेक्सन सेटअप गर्न चाहन्छ। यसको सहायताले यो एप नेटवर्क ट्राफिकको निगरानी राख्न सक्छ। तपाईं यो एपमाथि विश्वास गर्नुहुन्छ भने मात्र स्वीकार गर्नुहोस्। VPN सक्रिय हुँदा तपाईंको स्क्रिनमा <br /> <br /> <img src=vpn_icon /> देखा पर्छ।"</string> <string name="legacy_title" msgid="192936250066580964">"VPN जोडिएको छ"</string> <string name="session" msgid="6470628549473641030">"सत्र:"</string> <string name="duration" msgid="3584782459928719435">"अवधि:"</string> @@ -31,7 +30,7 @@ <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"VPN सम्बन्धी सेटिङहरू परिवर्तन गर्नुहोस्"</string> <string name="configure" msgid="4905518375574791375">"कन्फिगर गर्नुहोस्"</string> - <string name="disconnect" msgid="971412338304200056">"डिस्कनेक्ट गर्नुहोस्"</string> - <string name="open_app" msgid="3717639178595958667">"एप खोल्नुहोस्"</string> + <string name="disconnect" msgid="971412338304200056">"विच्छेदन गर्नुहोस्"</string> + <string name="open_app" msgid="3717639178595958667">"अनुप्रयोग खोल्नुहोस्"</string> <string name="dismiss" msgid="6192859333764711227">"खारेज गर्नुहोस्"</string> </resources> diff --git a/packages/VpnDialogs/res/values-nl/strings.xml b/packages/VpnDialogs/res/values-nl/strings.xml index 33f8a89a1562..8073b09e203c 100644 --- a/packages/VpnDialogs/res/values-nl/strings.xml +++ b/packages/VpnDialogs/res/values-nl/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"Verbindingsverzoek"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> wil een VPN-verbinding opzetten om netwerkverkeer te controleren. Accepteer het verzoek alleen als je de bron vertrouwt. <br /> <br /> <img src=vpn_icon /> wordt boven aan je scherm weergegeven wanneer VPN actief is."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> wil een VPN-verbinding instellen waarmee de app het netwerkverkeer kan bijhouden. Accepteer dit alleen als je de bron vertrouwt. <br /> <br /> <img src=vpn_icon /> verschijnt op je scherm als het VPN actief is."</string> <string name="legacy_title" msgid="192936250066580964">"Verbinding met VPN"</string> <string name="session" msgid="6470628549473641030">"Sessie:"</string> <string name="duration" msgid="3584782459928719435">"Duur:"</string> diff --git a/packages/VpnDialogs/res/values-or/strings.xml b/packages/VpnDialogs/res/values-or/strings.xml index 4c5c2591986f..f1122ebd4386 100644 --- a/packages/VpnDialogs/res/values-or/strings.xml +++ b/packages/VpnDialogs/res/values-or/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"ସଂଯୋଗ ଅନୁରୋଧ"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> ଏକ VPN ସଂଯୋଗ ସେଟ୍ ଅପ୍ କରିବାକୁ ଚାହେଁ, ଯାହା ଏହି ନେଟ୍ୱର୍କର ଟ୍ରାଫିକକୁ ମନିଟର୍ କରିବାକୁ ଅନୁମତି ଦିଏ। ଆପଣ ସୋର୍ସ ଉପରେ ବିଶ୍ୱାସ କରିବା ବଦଳରେ କେବଳ ସ୍ୱୀକାର କରନ୍ତୁ। <br /> <br /> <img src=vpn_icon /> VPN ସକ୍ରିୟ ଥିବାବେଳେ ଏହା ଆପଣଙ୍କ ସ୍କ୍ରୀନ୍ର ଉପରେ ଦେଖାଯାଏ।"</string> - <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> ଏକ VPN ସଂଯୋଗ ସେଟ୍ ଅପ୍ କରିବାକୁ ଚାହେଁ, ଯାହା ଏହାକୁ ନେଟୱାର୍କ ଟ୍ରାଫିକ ମନିଟର୍ କରିବାକୁ ଅନୁମତି ଦେଇଥାଏ। ଯଦି ଆପଣ ସୋର୍ସରେ ବିଶ୍ୱାସ କରୁଛନ୍ତି, ତେବେ ହିଁ କେବଳ ସ୍ୱୀକାର କରନ୍ତୁ। <br /> <br /> <img src=vpn_icon /> VPN ସକ୍ରିୟ ଥିବା ସମୟରେ ଆପଣଙ୍କ ସ୍କ୍ରିନ୍ ଉପରେ ଦେଖାଯାଏ।"</string> <string name="legacy_title" msgid="192936250066580964">"VPN ସଂଯୋଗ ହେଲା"</string> <string name="session" msgid="6470628549473641030">"ସେସନ୍:"</string> <string name="duration" msgid="3584782459928719435">"ଅବଧି:"</string> @@ -29,7 +28,7 @@ <string name="always_on_disconnected_message" msgid="555634519845992917">"<xliff:g id="VPN_APP_0">%1$s</xliff:g> ସବୁ ସମୟରେ କନେକ୍ଟ ହୋଇ ରହିବା ପାଇଁ ସେଟଅପ୍ କରାଯାଇଛି। ଆପଣଙ୍କ ଫୋନ୍, <xliff:g id="VPN_APP_1">%1$s</xliff:g> ସହ କନେକ୍ଟ ନହେବା ପର୍ଯ୍ୟନ୍ତ ଏକ ପବ୍ଲିକ୍ ନେଟ୍ୱର୍କ ବ୍ୟବହାର କରିବ।"</string> <string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"<xliff:g id="VPN_APP">%1$s</xliff:g> ସବୁ ସମୟରେ କନେକ୍ଟ ହୋଇରହିବାକୁ ସେଟଅପ୍ କରାଯାଇଛି, କିନ୍ତୁ ଏହା ବର୍ତ୍ତମାନ କନେକ୍ଟ କରିପାରୁ ନାହିଁ। VPN ପୁଣି କନେକ୍ଟ ନହେବା ପର୍ଯ୍ୟନ୍ତ ଆପଣଙ୍କର କୌଣସି କନେକ୍ସନ୍ ରହିବନାହିଁ।"</string> <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> - <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"VPN ସେଟିଂସ ବଦଳାନ୍ତୁ"</string> + <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"VPN ସେଟିଙ୍ଗ ବଦଳାନ୍ତୁ"</string> <string name="configure" msgid="4905518375574791375">"କନଫିଗର୍ କରନ୍ତୁ"</string> <string name="disconnect" msgid="971412338304200056">"ବିଚ୍ଛିନ୍ନ କରନ୍ତୁ"</string> <string name="open_app" msgid="3717639178595958667">"ଆପ୍ ଖୋଲନ୍ତୁ"</string> diff --git a/packages/VpnDialogs/res/values-pa/strings.xml b/packages/VpnDialogs/res/values-pa/strings.xml index d2eba0f52005..1815f4fb0d25 100644 --- a/packages/VpnDialogs/res/values-pa/strings.xml +++ b/packages/VpnDialogs/res/values-pa/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"ਕਨੈਕਸ਼ਨ ਬੇਨਤੀ"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> ਇੱਕ VPN ਕਨੈਕਸ਼ਨ ਸੈਟ ਅਪ ਕਰਨਾ ਚਾਹੁੰਦਾ ਹੈ ਜੋ ਇਸਨੂੰ ਨੈੱਟਵਰਕ ਟ੍ਰੈਫਿਕ ਦਾ ਨਿਰੀਖਣ ਕਰਨ ਦੀ ਆਗਿਆ ਦਿੰਦਾ ਹੈ। ਕੇਵਲ ਤਾਂ ਹੀ ਸਵੀਕਾਰ ਕਰੋ ਜੇਕਰ ਤੁਸੀਂ ਸਰੋਤ ਤੇ ਭਰੋਸਾ ਕਰਦੇ ਹੋ। <br /> <br /> <img src=vpn_icon /> ਤੁਹਾਡੀ ਸਕ੍ਰੀਨ ਦੇ ਟੌਪ ਤੇ ਪ੍ਰਗਟ ਹੁੰਦਾ ਹੈ ਜਦੋਂ VPN ਸਕਿਰਿਆ ਹੁੰਦਾ ਹੈ।"</string> - <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> ਕਿਸੇ ਅਜਿਹੇ VPN ਕਨੈਕਸ਼ਨ ਦਾ ਸੈੱਟਅੱਪ ਕਰਨਾ ਚਾਹੁੰਦੀ ਹੈ ਜੋ ਇਸਨੂੰ ਨੈੱਟਵਰਕ ਟਰੈਫ਼ਿਕ ਦੀ ਨਿਗਰਾਨੀ ਕਰਨ ਦੀ ਇਜਾਜ਼ਤ ਦਿੰਦਾ ਹੈ। ਸਿਰਫ਼ ਉਦੋਂ ਹੀ ਸਵੀਕਾਰ ਕਰੋ ਜੇ ਤੁਹਾਨੂੰ ਸਰੋਤ \'ਤੇ ਭਰੋਸਾ ਹੈ। VPN ਦੇ ਕਿਰਿਆਸ਼ੀਲ ਹੋਣ \'ਤੇ <br /> <br /> <img src=vpn_icon /> ਤੁਹਾਡੀ ਸਕ੍ਰੀਨ \'ਤੇ ਦਿਸਦਾ ਹੈ।"</string> <string name="legacy_title" msgid="192936250066580964">"VPN ਕਨੈਕਟ ਕੀਤਾ ਗਿਆ ਹੈ"</string> <string name="session" msgid="6470628549473641030">"ਸੈਸ਼ਨ:"</string> <string name="duration" msgid="3584782459928719435">"ਮਿਆਦ:"</string> diff --git a/packages/VpnDialogs/res/values-pl/strings.xml b/packages/VpnDialogs/res/values-pl/strings.xml index 82161d389368..d5201d7fbdf5 100644 --- a/packages/VpnDialogs/res/values-pl/strings.xml +++ b/packages/VpnDialogs/res/values-pl/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"Żądanie połączenia"</string> <string name="warning" msgid="809658604548412033">"Aplikacja <xliff:g id="APP">%s</xliff:g> chce utworzyć połączenie VPN, które pozwoli jej na monitorowanie ruchu sieciowego. Zaakceptuj, tylko jeśli masz zaufanie do źródła. <br /> <br />Gdy sieć VPN jest aktywna, u góry ekranu pojawia się <img src=vpn_icon />."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"Aplikacja <xliff:g id="APP">%s</xliff:g> chce utworzyć połączenie VPN, które pozwoli jej na monitorowanie ruchu w sieci. Zaakceptuj, jeśli masz zaufanie do źródła. <br /> <br Gdy sieć VPN jest aktywna, na ekranie pojawia się ikona /> <img src=vpn_icon />."</string> <string name="legacy_title" msgid="192936250066580964">"Połączono z VPN"</string> <string name="session" msgid="6470628549473641030">"Sesja:"</string> <string name="duration" msgid="3584782459928719435">"Czas trwania:"</string> diff --git a/packages/VpnDialogs/res/values-pt-rBR/strings.xml b/packages/VpnDialogs/res/values-pt-rBR/strings.xml index 0d6dd0b136e9..75c140617cf5 100644 --- a/packages/VpnDialogs/res/values-pt-rBR/strings.xml +++ b/packages/VpnDialogs/res/values-pt-rBR/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"Solicitação de conexão"</string> <string name="warning" msgid="809658604548412033">"O <xliff:g id="APP">%s</xliff:g> quer configurar uma conexão VPN que permite monitorar o tráfego da rede. Aceite somente se confiar na origem. <br /> <br /> <img src=vpn_icon /> é exibido na parte superior da tela quando a rede VPN estiver ativa."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"O app <xliff:g id="APP">%s</xliff:g> quer definir uma conexão VPN para monitorar o tráfego da rede. Aceite apenas se você confiar na fonte. O ícone <br /> <br /> <img src=vpn_icon /> aparecerá na tela quando a VPN estiver ativa."</string> <string name="legacy_title" msgid="192936250066580964">"O VPN está conectado"</string> <string name="session" msgid="6470628549473641030">"Sessão:"</string> <string name="duration" msgid="3584782459928719435">"Duração:"</string> diff --git a/packages/VpnDialogs/res/values-pt-rPT/strings.xml b/packages/VpnDialogs/res/values-pt-rPT/strings.xml index a310104555a2..01beddbab4e4 100644 --- a/packages/VpnDialogs/res/values-pt-rPT/strings.xml +++ b/packages/VpnDialogs/res/values-pt-rPT/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"Pedido de ligação"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> pretende configurar uma ligação VPN que lhe permita monitorizar o tráfego de rede. Aceite apenas se confiar na fonte. <br /> <br /> <img src=vpn_icon /> aparece na parte superior do seu ecrã quando a VPN está ativa."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"A app <xliff:g id="APP">%s</xliff:g> pretende configurar uma ligação VPN que lhe permita monitorizar o tráfego de rede. Aceite apenas se confiar na origem. <br /> <br /> <img src=vpn_icon /> aparece no ecrã quando a VPN está ativa."</string> <string name="legacy_title" msgid="192936250066580964">"A VPN está ligada"</string> <string name="session" msgid="6470628549473641030">"Sessão"</string> <string name="duration" msgid="3584782459928719435">"Duração:"</string> @@ -26,12 +25,12 @@ <string name="data_received" msgid="4062776929376067820">"Recebidos:"</string> <string name="data_value_format" msgid="2192466557826897580">"<xliff:g id="NUMBER_0">%1$s</xliff:g> bytes / <xliff:g id="NUMBER_1">%2$s</xliff:g> pacotes"</string> <string name="always_on_disconnected_title" msgid="1906740176262776166">"Não é possível estabelecer ligação à VPN sempre ativada"</string> - <string name="always_on_disconnected_message" msgid="555634519845992917">"A app <xliff:g id="VPN_APP_0">%1$s</xliff:g> está configurada para se manter sempre ligada, mas, neste momento, não é possível estabelecer ligação. O seu telemóvel irá utilizar uma rede pública até conseguir restabelecer ligação à app <xliff:g id="VPN_APP_1">%1$s</xliff:g>."</string> - <string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"A app <xliff:g id="VPN_APP">%1$s</xliff:g> está configurada para se manter sempre ligada, mas, neste momento, não é possível estabelecer ligação. Não terá ligação até que a VPN a consiga restabelecer."</string> + <string name="always_on_disconnected_message" msgid="555634519845992917">"A aplicação <xliff:g id="VPN_APP_0">%1$s</xliff:g> está configurada para se manter sempre ligada, mas, neste momento, não é possível estabelecer ligação. O seu telemóvel irá utilizar uma rede pública até conseguir restabelecer ligação à aplicação <xliff:g id="VPN_APP_1">%1$s</xliff:g>."</string> + <string name="always_on_disconnected_message_lockdown" msgid="4232225539869452120">"A aplicação <xliff:g id="VPN_APP">%1$s</xliff:g> está configurada para se manter sempre ligada, mas, neste momento, não é possível estabelecer ligação. Não terá ligação até que a VPN a consiga restabelecer."</string> <string name="always_on_disconnected_message_separator" msgid="3310614409322581371">" "</string> <string name="always_on_disconnected_message_settings_link" msgid="6172280302829992412">"Alterar as definições da VPN"</string> <string name="configure" msgid="4905518375574791375">"Configurar"</string> <string name="disconnect" msgid="971412338304200056">"Desligar"</string> - <string name="open_app" msgid="3717639178595958667">"Abrir app"</string> + <string name="open_app" msgid="3717639178595958667">"Abrir aplicação"</string> <string name="dismiss" msgid="6192859333764711227">"Ignorar"</string> </resources> diff --git a/packages/VpnDialogs/res/values-pt/strings.xml b/packages/VpnDialogs/res/values-pt/strings.xml index 0d6dd0b136e9..75c140617cf5 100644 --- a/packages/VpnDialogs/res/values-pt/strings.xml +++ b/packages/VpnDialogs/res/values-pt/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"Solicitação de conexão"</string> <string name="warning" msgid="809658604548412033">"O <xliff:g id="APP">%s</xliff:g> quer configurar uma conexão VPN que permite monitorar o tráfego da rede. Aceite somente se confiar na origem. <br /> <br /> <img src=vpn_icon /> é exibido na parte superior da tela quando a rede VPN estiver ativa."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"O app <xliff:g id="APP">%s</xliff:g> quer definir uma conexão VPN para monitorar o tráfego da rede. Aceite apenas se você confiar na fonte. O ícone <br /> <br /> <img src=vpn_icon /> aparecerá na tela quando a VPN estiver ativa."</string> <string name="legacy_title" msgid="192936250066580964">"O VPN está conectado"</string> <string name="session" msgid="6470628549473641030">"Sessão:"</string> <string name="duration" msgid="3584782459928719435">"Duração:"</string> diff --git a/packages/VpnDialogs/res/values-ro/strings.xml b/packages/VpnDialogs/res/values-ro/strings.xml index 5bda87e5c257..4e60df2eca8e 100644 --- a/packages/VpnDialogs/res/values-ro/strings.xml +++ b/packages/VpnDialogs/res/values-ro/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"Solicitare de conexiune"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> dorește să configureze o conexiune VPN care să îi permită să monitorizeze traficul în rețea. Acceptați numai dacă aveți încredere în sursă. Atunci când conexiunea VPN este activă, <br /> <br /> <img src=vpn_icon /> se afișează în partea de sus a ecranului."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> solicită permisiunea de a configura o conexiune VPN care să îi permită să monitorizeze traficul de rețea. Acceptați numai dacă aveți încredere în sursă. <br /> <br /> <img src=vpn_icon /> va apărea pe ecran atunci când conexiunea VPN este activă."</string> <string name="legacy_title" msgid="192936250066580964">"VPN este conectat"</string> <string name="session" msgid="6470628549473641030">"Sesiune:"</string> <string name="duration" msgid="3584782459928719435">"Durată:"</string> diff --git a/packages/VpnDialogs/res/values-ru/strings.xml b/packages/VpnDialogs/res/values-ru/strings.xml index ce099562f854..f8fcfb83aa9a 100644 --- a/packages/VpnDialogs/res/values-ru/strings.xml +++ b/packages/VpnDialogs/res/values-ru/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"Запрос на подключение"</string> <string name="warning" msgid="809658604548412033">"Приложение \"<xliff:g id="APP">%s</xliff:g>\" пытается подключиться к сети VPN, чтобы отслеживать трафик. Этот запрос следует принимать, только если вы доверяете источнику. <br /><br />Когда подключение к сети VPN активно, в верхней части экрана появляется значок <img src=vpn_icon />."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"Приложение \"<xliff:g id="APP">%s</xliff:g>\" пытается подключиться к сети VPN, чтобы отслеживать трафик. Этот запрос следует принимать, только если вы доверяете источнику. Когда подключение к сети VPN активно, на экране появляется значок <br /> <br /> <img src=vpn_icon />."</string> <string name="legacy_title" msgid="192936250066580964">"VPN-подключение установлено"</string> <string name="session" msgid="6470628549473641030">"Сеанс:"</string> <string name="duration" msgid="3584782459928719435">"Продолжительность:"</string> diff --git a/packages/VpnDialogs/res/values-si/strings.xml b/packages/VpnDialogs/res/values-si/strings.xml index a836baef545c..bb97a5d86c5f 100644 --- a/packages/VpnDialogs/res/values-si/strings.xml +++ b/packages/VpnDialogs/res/values-si/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"සම්බන්ධතා ඉල්ලීම"</string> <string name="warning" msgid="809658604548412033">"ජාල තදබදය නිරීක්ෂණය කිරීමට ඉඩ දෙන VPN සම්බන්ධතාවක් සැකසීමට <xliff:g id="APP">%s</xliff:g> අවශ්යය වේ. ප්රභවය ඔබ විශ්වාස කරන්නේ නම් පමණක් පිළිගන්න. VPN සක්රිය විට <br /> <br /> <img src=vpn_icon />."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"ජාල තදබදය නිරීක්ෂණය කිරීමට ඉඩ දෙන VPN සම්බන්ධතාවක් සැකසීමට <xliff:g id="APP">%s</xliff:g> හට අවශ්ය වේ. ඔබ මූලාශ්රය විශ්වාස කරන්නේ නම් පමණක් පිළිගන්න. <br /> <br /> <img src=vpn_icon /> VPN සක්රිය විට ඔබගේ තිරයෙහි දිස් වේ."</string> <string name="legacy_title" msgid="192936250066580964">"VPN සම්බන්ධිතයි"</string> <string name="session" msgid="6470628549473641030">"සැසිය:"</string> <string name="duration" msgid="3584782459928719435">"කාල සීමාව:"</string> diff --git a/packages/VpnDialogs/res/values-sk/strings.xml b/packages/VpnDialogs/res/values-sk/strings.xml index 766c1393b524..a08117adfac1 100644 --- a/packages/VpnDialogs/res/values-sk/strings.xml +++ b/packages/VpnDialogs/res/values-sk/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"Žiadosť o pripojenie"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> žiada o nastavenie pripojenia VPN, pomocou ktorého bude môcť sledovať sieťové prenosy. Povoľte iba v prípade, že zdroju dôverujete. <br /> <br /> <img src=vpn_icon /> sa zobrazuje v hornej časti obrazovky, keď je pripojenie VPN aktívne."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"Aplikácia <xliff:g id="APP">%s</xliff:g> chce nastaviť pripojenie k sieti VPN, ktoré jej umožňuje sledovať sieťovú premávku. Povoľte to iba v prípade, ak zdroju dôverujete. <br /> <br /> Keď je sieť VPN aktívna, na obrazovke sa zobrazí ikona <img src=vpn_icon />."</string> <string name="legacy_title" msgid="192936250066580964">"Sieť VPN je pripojená"</string> <string name="session" msgid="6470628549473641030">"Relácia"</string> <string name="duration" msgid="3584782459928719435">"Trvanie:"</string> diff --git a/packages/VpnDialogs/res/values-sl/strings.xml b/packages/VpnDialogs/res/values-sl/strings.xml index 361a5fa2f1fa..d5014fa34394 100644 --- a/packages/VpnDialogs/res/values-sl/strings.xml +++ b/packages/VpnDialogs/res/values-sl/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"Zahteva za povezavo"</string> <string name="warning" msgid="809658604548412033">"Aplikacija <xliff:g id="APP">%s</xliff:g> želi nastaviti povezavo VPN, ki omogoča nadzor omrežnega prometa. To sprejmite samo, če zaupate viru. Ko je povezava VPN aktivna, se na vrhu zaslona prikaže ikona <br /> <br /> <img src=vpn_icon />."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"Aplikacija <xliff:g id="APP">%s</xliff:g> želi nastaviti povezavo VPN, ki ji omogoča nadzor omrežnega prometa. To sprejmite samo, če zaupate viru. Ko je povezava VPN aktivna, je na zaslonu prikazana ikona <br /> <br /> <img src=vpn_icon />."</string> <string name="legacy_title" msgid="192936250066580964">"Povezava z navideznim zasebnim omrežjem je vzpostavljena"</string> <string name="session" msgid="6470628549473641030">"Seja:"</string> <string name="duration" msgid="3584782459928719435">"Trajanje:"</string> diff --git a/packages/VpnDialogs/res/values-sq/strings.xml b/packages/VpnDialogs/res/values-sq/strings.xml index 0b4ce4df9514..4a96e7b92212 100644 --- a/packages/VpnDialogs/res/values-sq/strings.xml +++ b/packages/VpnDialogs/res/values-sq/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"Kërkesë për lidhje"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> kërkon të vendosë një lidhje VPN-je që e lejon të monitorojë trafikun e rrjetit. Prano vetëm nëse i beson burimit. <br /> <br /> <img src=vpn_icon /> shfaqet në krye të ekranit kur VPN-ja është aktive."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> kërkon të vendosë një lidhje VPN që i lejon të monitorojë trafikun e rrjetit. Pranoje vetëm nëse i beson burimit. <br /> <br /> <img src=vpn_icon /> shfaqet në ekranin tënd kur është aktive VPN."</string> <string name="legacy_title" msgid="192936250066580964">"VPN-ja është e lidhur"</string> <string name="session" msgid="6470628549473641030">"Sesioni:"</string> <string name="duration" msgid="3584782459928719435">"Kohëzgjatja:"</string> diff --git a/packages/VpnDialogs/res/values-sr/strings.xml b/packages/VpnDialogs/res/values-sr/strings.xml index 01bd4df700a7..8ce8060e333d 100644 --- a/packages/VpnDialogs/res/values-sr/strings.xml +++ b/packages/VpnDialogs/res/values-sr/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"Захтев за повезивање"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> жели да подеси VPN везу која омогућава праћење саобраћаја на мрежи. Прихватите само ако верујете извору. <br /> <br /> <img src=vpn_icon /> се приказује у врху екрана када је VPN активан."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"Апликација <xliff:g id="APP">%s</xliff:g> жели да подеси VPN везу која јој омогућава да прати мрежни саобраћај. Прихватите ово само ако имате поверења у извор. <br /> <br /> <img src=vpn_icon /> се приказује на екрану када је VPN активан."</string> <string name="legacy_title" msgid="192936250066580964">"VPN је повезан"</string> <string name="session" msgid="6470628549473641030">"Сесија:"</string> <string name="duration" msgid="3584782459928719435">"Трајање:"</string> diff --git a/packages/VpnDialogs/res/values-sv/strings.xml b/packages/VpnDialogs/res/values-sv/strings.xml index 60ed75250856..16b6a31d7d1a 100644 --- a/packages/VpnDialogs/res/values-sv/strings.xml +++ b/packages/VpnDialogs/res/values-sv/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"Anslutningsförfrågan"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> vill starta en VPN-anslutning som tillåter att appen övervakar nätverkstrafiken. Godkänn endast detta om du litar på källan. <br /> <br /> <img src=vpn_icon /> visas längst upp på skärmen när VPN-anslutningen är aktiv."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> vill skapa en VPN-anslutning så att den kan övervaka nätverkstrafik. Godkänn bara om du litar på källan. <br /> <br /> <img src=vpn_icon /> visas på skärmen när VPN-anslutningen är aktiv."</string> <string name="legacy_title" msgid="192936250066580964">"VPN är anslutet"</string> <string name="session" msgid="6470628549473641030">"Session:"</string> <string name="duration" msgid="3584782459928719435">"Längd:"</string> diff --git a/packages/VpnDialogs/res/values-sw/strings.xml b/packages/VpnDialogs/res/values-sw/strings.xml index c4f46628f8bc..ea2688438b7a 100644 --- a/packages/VpnDialogs/res/values-sw/strings.xml +++ b/packages/VpnDialogs/res/values-sw/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"Ombi la muunganisho"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> inataka kusanidi muunganisho wa VPN utakaoiruhusu kufuatilia shughuli kwenye mtandao. Kubali ikiwa tu unakiamini chanzo. <br /> <br /> <img src=vpn_icon /> huonekana sehemu ya juu ya skrini yako VPN inapofanya kazi."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> inagependa kuweka mipangilio ya muunganisho wa VPN inayoiruhusu kufuatilia trafiki ya mtandao. Kubali tu iwapo unaamini chanzo. <br /> <br /> <img src=vpn_icon /> huonekana kwenye skrini yako VPN inapotumika."</string> <string name="legacy_title" msgid="192936250066580964">"VPN imeunganishwa"</string> <string name="session" msgid="6470628549473641030">"Kipindi:"</string> <string name="duration" msgid="3584782459928719435">"Muda:"</string> diff --git a/packages/VpnDialogs/res/values-ta/strings.xml b/packages/VpnDialogs/res/values-ta/strings.xml index 1385bdc401c3..3b4cc571d860 100644 --- a/packages/VpnDialogs/res/values-ta/strings.xml +++ b/packages/VpnDialogs/res/values-ta/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"இணைப்புக் கோரிக்கை"</string> <string name="warning" msgid="809658604548412033">"நெட்வொர்க் டிராஃபிக்கைக் கண்காணிக்க வசதியாக VPN இணைப்பை அமைக்க <xliff:g id="APP">%s</xliff:g> கோருகிறது. நம்பகமான மூலத்தை மட்டுமே ஏற்கவும். <br /> <br /> VPN இயக்கத்தில் உள்ளபோது திரையின் மேல் பகுதியில் <img src=vpn_icon /> தோன்றும்."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"நெட்வொர்க் டிராஃபிக்கைக் கண்காணிக்க அனுமதிக்கும் VPN இணைப்பை அமைக்க <xliff:g id="APP">%s</xliff:g> விரும்புகிறது. நம்பகமான VPN ஆப்ஸாக இருந்தால் மட்டுமே ஏற்கவும். <br /> <br /> VPN இயங்கும்போது உங்கள் திரையில் <img src=vpn_icon /> தோன்றும்."</string> <string name="legacy_title" msgid="192936250066580964">"VPN இணைக்கப்பட்டது"</string> <string name="session" msgid="6470628549473641030">"அமர்வு:"</string> <string name="duration" msgid="3584782459928719435">"காலஅளவு:"</string> diff --git a/packages/VpnDialogs/res/values-te/strings.xml b/packages/VpnDialogs/res/values-te/strings.xml index 8f8ff0778d06..864c926bc615 100644 --- a/packages/VpnDialogs/res/values-te/strings.xml +++ b/packages/VpnDialogs/res/values-te/strings.xml @@ -16,9 +16,8 @@ <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="prompt" msgid="3183836924226407828">"కనెక్షన్ రిక్వెస్ట్"</string> + <string name="prompt" msgid="3183836924226407828">"కనెక్షన్ అభ్యర్థన"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> నెట్వర్క్ ట్రాఫిక్ని పర్యవేక్షించగలగడానికి VPN కనెక్షన్ను సెటప్ చేయాలనుకుంటోంది. మీరు మూలాన్ని విశ్వసిస్తే మాత్రమే ఆమోదించండి. VPN సక్రియంగా ఉన్నప్పుడు మీ స్క్రీన్ ఎగువన <br /> <br /> <img src=vpn_icon /> కనిపిస్తుంది."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"నెట్వర్క్ ట్రాఫిక్ను పర్యవేక్షించగలగడానికి, <xliff:g id="APP">%s</xliff:g> VPN కనెక్షన్ను సెటప్ చేయాలనుకుంటోంది. మీరు సోర్స్ను విశ్వసిస్తే మాత్రమే ఆమోదించండి. <br /> <br /> <img src=vpn_icon /> VPN యాక్టివ్గా ఉన్నప్పుడు మీ స్క్రీన్ పై కనిపిస్తుంది."</string> <string name="legacy_title" msgid="192936250066580964">"VPN కనెక్ట్ చేయబడింది"</string> <string name="session" msgid="6470628549473641030">"సెషన్:"</string> <string name="duration" msgid="3584782459928719435">"వ్యవధి:"</string> diff --git a/packages/VpnDialogs/res/values-th/strings.xml b/packages/VpnDialogs/res/values-th/strings.xml index 2e174cd7b296..333ff5fefacc 100644 --- a/packages/VpnDialogs/res/values-th/strings.xml +++ b/packages/VpnDialogs/res/values-th/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"ขอการเชื่อมต่อ"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> ต้องการสร้างการเชื่อมต่อ VPN เพื่อให้แอปสามารถตรวจสอบการเข้าใช้งานเครือข่าย โปรดยอมรับหากคุณเชื่อถือแหล่งที่มานี้เท่านั้น <br /> <br /> <img src=vpn_icon /> จะปรากฏที่ด้านบนหน้าจอเมื่อมีการใช้งาน VPN อยู่"</string> - <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> ต้องการตั้งค่าการเชื่อมต่อ VPN เพื่อให้ตรวจสอบการจราจรของข้อมูลในเครือข่ายได้ ยอมรับต่อเมื่อคุณไว้วางใจแหล่งที่มานี้เท่านั้น <br /> <br /> <img src=vpn_icon /> จะปรากฏบนหน้าจอเมื่อใช้งาน VPN อยู่"</string> <string name="legacy_title" msgid="192936250066580964">"เชื่อมต่อ VPN แล้ว"</string> <string name="session" msgid="6470628549473641030">"เซสชัน"</string> <string name="duration" msgid="3584782459928719435">"ระยะเวลา:"</string> diff --git a/packages/VpnDialogs/res/values-tl/strings.xml b/packages/VpnDialogs/res/values-tl/strings.xml index ea69fba45f1e..9c01c32d0d0d 100644 --- a/packages/VpnDialogs/res/values-tl/strings.xml +++ b/packages/VpnDialogs/res/values-tl/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"Kahilingan sa koneksyon"</string> <string name="warning" msgid="809658604548412033">"Gusto ng <xliff:g id="APP">%s</xliff:g> na mag-set up ng koneksyon sa VPN na nagbibigay-daan ditong masubaybayan ang trapiko ng network. Tanggapin lang kung pinagkakatiwalaan mo ang pinagmulan. Lalabas ang <br /> <br /> <img src=vpn_icon /> sa itaas ng iyong screen kapag aktibo ang VPN."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"Gusto ng <xliff:g id="APP">%s</xliff:g> na mag-set up ng koneksyon sa VPN na nagbibigay-daan ditong masubaybayan ang trapiko sa network. Tanggapin lang kung pinagkakatiwalaan mo ang pinagmulan. Lalabas ang <br /> <br /> <img src=vpn_icon /> sa iyong screen kapag aktibo ang VPN."</string> <string name="legacy_title" msgid="192936250066580964">"Nakakonekta ang VPN"</string> <string name="session" msgid="6470628549473641030">"Session:"</string> <string name="duration" msgid="3584782459928719435">"Tagal:"</string> diff --git a/packages/VpnDialogs/res/values-tr/strings.xml b/packages/VpnDialogs/res/values-tr/strings.xml index 7ffa4bc1e4e9..8665a47e6633 100644 --- a/packages/VpnDialogs/res/values-tr/strings.xml +++ b/packages/VpnDialogs/res/values-tr/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"Bağlantı isteği"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> ağ trafiğini izlemesine olanak veren bir VPN bağlantısı oluşturmak istiyor. Sadece, ilgili kaynağa güveniyorsanız kabul edin. <br /> <br /> VPN aktif olduğunda ekranınızın üst tarafında <img src=vpn_icon /> simgesi görünür."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g>, ağ trafiğini izlemesine izin veren bir VPN bağlantısı oluşturmak istiyor. Yalnızca kaynağa güveniyorsanız kabul edin. VPN etkin olduğunda ekranınızda <br /> <br /> <img src=vpn_icon /> görünür."</string> <string name="legacy_title" msgid="192936250066580964">"VPN bağlı"</string> <string name="session" msgid="6470628549473641030">"Oturum:"</string> <string name="duration" msgid="3584782459928719435">"Süre:"</string> diff --git a/packages/VpnDialogs/res/values-uk/strings.xml b/packages/VpnDialogs/res/values-uk/strings.xml index 6411d7cf9d76..8f91abf990b3 100644 --- a/packages/VpnDialogs/res/values-uk/strings.xml +++ b/packages/VpnDialogs/res/values-uk/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"Запит на під’єднання"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> хоче під’єднатися до мережі VPN, щоб контролювати мережевий трафік. Дозволяйте, якщо довіряєте джерелу. Коли мережа VPN активна, угорі екрана відображається значок <br /> <br /> <img src=vpn_icon />."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> хоче під’єднатися до мережі VPN, щоб контролювати мережевий трафік. Надавайте дозвіл, лише якщо довіряєте джерелу. Коли мережа VPN активна, на екрані з’являється значок <br /> <br /> <img src=vpn_icon />."</string> <string name="legacy_title" msgid="192936250066580964">"Мережу VPN під’єднано"</string> <string name="session" msgid="6470628549473641030">"Сеанс:"</string> <string name="duration" msgid="3584782459928719435">"Тривалість:"</string> diff --git a/packages/VpnDialogs/res/values-ur/strings.xml b/packages/VpnDialogs/res/values-ur/strings.xml index 3a23e940d9e9..db0c2971a64c 100644 --- a/packages/VpnDialogs/res/values-ur/strings.xml +++ b/packages/VpnDialogs/res/values-ur/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"کنکشن کی درخواست"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> ایک ایسا VPN کنکشن ترتیب دینا چاہتی ہے جو اسے نیٹ ورک ٹریفک کو مانیٹر کرنے کی اجازت دیتا ہے۔ اگر آپ کو ماخذ پر بھروسہ ہے تبھی قبول کریں۔ <br /> <br /> <img src=vpn_icon /> آپ کی اسکرین کے اوپر اس وقت ظاہر ہوتا ہے جب VPN فعال ہوتا ہے۔"</string> - <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> ایک ایسا VPN کنکشن سیٹ اپ کرنا چاہتی ہے جو اسے نیٹ ورک ٹریفک کو مانیٹر کرنے کی اجازت دیتا ہو۔ آپ کو ماخذ پر اعتماد ہونے پر ہی قبول کریں۔ <br /> <br /> <img src=vpn_icon /> VPN کے فعال ہونے پر آپ کی اسکرین پر ظاہر ہوتا ہے۔"</string> <string name="legacy_title" msgid="192936250066580964">"VPN مربوط ہے"</string> <string name="session" msgid="6470628549473641030">"سیشن:"</string> <string name="duration" msgid="3584782459928719435">"دورانیہ:"</string> diff --git a/packages/VpnDialogs/res/values-uz/strings.xml b/packages/VpnDialogs/res/values-uz/strings.xml index a3256e7bb927..5a348a0610d3 100644 --- a/packages/VpnDialogs/res/values-uz/strings.xml +++ b/packages/VpnDialogs/res/values-uz/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"Ulanish uchun so‘rov"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> ilovasi trafikni kuzatish uchun VPN tarmog‘iga ulanmoqchi. Agar ilovaga ishonsangiz, so‘rovga rozi bo‘ling.<br /> <br />VPN faol bo‘lsa, ekranning yuqori qismida <img src=vpn_icon /> belgisi paydo bo‘ladi."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> ilovasi tarmoqdagi trafikni kuzatish uchun VPN aloqasini sozlamoqchi. Agar unga ishonsangiz, ruxsat bering. VPN aloqa faolligida ekranda <br /> <br /> <img src=vpn_icon /> chiqadi."</string> <string name="legacy_title" msgid="192936250066580964">"VPN ulangan"</string> <string name="session" msgid="6470628549473641030">"Seans:"</string> <string name="duration" msgid="3584782459928719435">"Davomiyligi:"</string> diff --git a/packages/VpnDialogs/res/values-vi/strings.xml b/packages/VpnDialogs/res/values-vi/strings.xml index 184d08d7d665..097c9aeee013 100644 --- a/packages/VpnDialogs/res/values-vi/strings.xml +++ b/packages/VpnDialogs/res/values-vi/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"Yêu cầu kết nối"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> muốn thiết lập kết nối VPN cho phép ứng dụng giám sát lưu lượng truy cập mạng. Chỉ chấp nhận nếu bạn tin tưởng nguồn. <br /> <br /> Biểu tượng <img src=vpn_icon /> xuất hiện ở đầu màn hình của bạn khi VPN đang hoạt động."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"<xliff:g id="APP">%s</xliff:g> muốn thiết lập kết nối VPN cho phép ứng dụng giám sát lưu lượng truy cập mạng. Bạn chỉ nên chấp nhận nếu tin tưởng nguồn đó. <br /> <br /> <img src=vpn_icon /> sẽ xuất hiện trên màn hình khi VPN đang hoạt động."</string> <string name="legacy_title" msgid="192936250066580964">"VPN được kết nối"</string> <string name="session" msgid="6470628549473641030">"Phiên"</string> <string name="duration" msgid="3584782459928719435">"Thời lượng:"</string> diff --git a/packages/VpnDialogs/res/values-zh-rCN/strings.xml b/packages/VpnDialogs/res/values-zh-rCN/strings.xml index a7262bedce96..7e528bdfb04a 100644 --- a/packages/VpnDialogs/res/values-zh-rCN/strings.xml +++ b/packages/VpnDialogs/res/values-zh-rCN/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"网络连接请求"</string> <string name="warning" msgid="809658604548412033">"“<xliff:g id="APP">%s</xliff:g>”想要设置一个 VPN 连接,以便监控网络流量。除非您信任该来源,否则请勿接受此请求。<br /> <br />启用 VPN 后,屏幕顶部会出现一个 <img src=vpn_icon /> 图标。"</string> - <string name="warning" product="tv" msgid="5188957997628124947">"“<xliff:g id="APP">%s</xliff:g>”想要建立一个 VPN 连接,以便监控网络流量。除非您信任该来源,否则请不要接受。VPN 处于启用状态时,屏幕上会显示 <br /> <br /> <img src=vpn_icon />。"</string> <string name="legacy_title" msgid="192936250066580964">"已连接VPN"</string> <string name="session" msgid="6470628549473641030">"会话:"</string> <string name="duration" msgid="3584782459928719435">"时长:"</string> diff --git a/packages/VpnDialogs/res/values-zh-rHK/strings.xml b/packages/VpnDialogs/res/values-zh-rHK/strings.xml index e4e643234143..49605b08cdee 100644 --- a/packages/VpnDialogs/res/values-zh-rHK/strings.xml +++ b/packages/VpnDialogs/res/values-zh-rHK/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"連線要求"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> 要求設定 VPN 連線以監控網絡流量。除非您信任要求來源,否則請勿隨意接受要求。<br /> <br />VPN 啟用時,畫面頂端會顯示 <img src=vpn_icon />。"</string> - <string name="warning" product="tv" msgid="5188957997628124947">"「<xliff:g id="APP">%s</xliff:g>」要求設定 VPN 連線以監控網絡流量。除非您信任要求來源,否則請勿隨意接受要求。VPN 啟用時,畫面會顯示 <br /> <br /> <img src=vpn_icon />。"</string> <string name="legacy_title" msgid="192936250066580964">"VPN 已連線"</string> <string name="session" msgid="6470628549473641030">"時段:"</string> <string name="duration" msgid="3584782459928719435">"持續時間︰"</string> diff --git a/packages/VpnDialogs/res/values-zh-rTW/strings.xml b/packages/VpnDialogs/res/values-zh-rTW/strings.xml index f54ca4a7a576..edd8e61d5555 100644 --- a/packages/VpnDialogs/res/values-zh-rTW/strings.xml +++ b/packages/VpnDialogs/res/values-zh-rTW/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"連線要求"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> 要求設定 VPN 連線,允許此要求即開放該來源監控網路流量。除非你信任該來源,否則請勿任意接受要求。<br /> <br />VPN 啟用時,畫面頂端會顯示 <img src=vpn_icon />。"</string> - <string name="warning" product="tv" msgid="5188957997628124947">"「<xliff:g id="APP">%s</xliff:g>」要求設定 VPN 連線,以便監控網路流量。除非你信任該來源,否則請勿接受要求。<br /> <br /> VPN 啟用時,畫面上會顯示 <img src=vpn_icon />。"</string> <string name="legacy_title" msgid="192936250066580964">"VPN 已連線"</string> <string name="session" msgid="6470628549473641030">"工作階段:"</string> <string name="duration" msgid="3584782459928719435">"持續時間:"</string> diff --git a/packages/VpnDialogs/res/values-zu/strings.xml b/packages/VpnDialogs/res/values-zu/strings.xml index c224b13b06da..4ab1225e6fc6 100644 --- a/packages/VpnDialogs/res/values-zu/strings.xml +++ b/packages/VpnDialogs/res/values-zu/strings.xml @@ -18,7 +18,6 @@ xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <string name="prompt" msgid="3183836924226407828">"Isicelo soxhumo"</string> <string name="warning" msgid="809658604548412033">"<xliff:g id="APP">%s</xliff:g> ifuna ukusetha uxhumo lwe-VPN eyivumela ukwengamela ithrafikhi yenethiwekhi. Yamukela kuphela uma wethemba umthombo. <br /> <br /> <img src=vpn_icon /> ibonakala phezu kwesikrini sakho uma i-VPN isebenza."</string> - <string name="warning" product="tv" msgid="5188957997628124947">"I-<xliff:g id="APP">%s</xliff:g> ifuna ukusetha uxhumano lwe-VPN oluyivumela ukuthi igade ithrafikhi yenethiwekhi. Yamukela kuphela uma wethemba umthombo. <br /> <br /> <img src=vpn_icon /> ivela kusikrini sakho lapho i-VPN isebenza."</string> <string name="legacy_title" msgid="192936250066580964">"I-VPN ixhunyiwe"</string> <string name="session" msgid="6470628549473641030">"Iseshini:"</string> <string name="duration" msgid="3584782459928719435">"Ubude besikhathi:"</string> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-af/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-af/strings.xml deleted file mode 100644 index adc308600ebb..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-af/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Lewer programme onder uitsnede-area"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-am/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-am/strings.xml deleted file mode 100644 index 648e1d4cf383..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-am/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"ከተቆረጠው አከባቢ በታች የመተግበሪያዎች ምስልን ስራ"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ar/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ar/strings.xml deleted file mode 100644 index 2d3b506d8cad..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ar/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"عرض التطبيقات أسفل منطقة الصورة المقطوعة للشاشة"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-as/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-as/strings.xml deleted file mode 100644 index db2b15a142c3..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-as/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"এপ্সমূহ কাটআউট অঞ্চলৰ তলত দেখুৱাওক"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-az/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-az/strings.xml deleted file mode 100644 index a6b7c4346e7e..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-az/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Tətbiqləri kəsilmə sahəsinin aşağısında göstərin"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-b+sr+Latn/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-b+sr+Latn/strings.xml deleted file mode 100644 index f80fa8d14054..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-b+sr+Latn/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Prikazuj aplikacije ispod oblasti izreza"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-be/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-be/strings.xml deleted file mode 100644 index 0e5c8bcb55a2..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-be/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Візуалізацыя праграм ніжэй месца выраза"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-bg/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-bg/strings.xml deleted file mode 100644 index e97bb57068ca..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-bg/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Изобразяване на приложенията под областта на прореза"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-bn/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-bn/strings.xml deleted file mode 100644 index d13c777fe468..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-bn/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"কাটআউট এরিয়ার নিচে অ্যাপ রেন্ডার করুন"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-bs/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-bs/strings.xml deleted file mode 100644 index 9c9f43779b66..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-bs/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Renderovanje aplikacija ispod izrezanog područja"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ca/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ca/strings.xml deleted file mode 100644 index e0a577e5290f..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ca/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Renderitza les aplicacions per sota de l\'àrea de retallada"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-cs/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-cs/strings.xml deleted file mode 100644 index 0f64473c7260..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-cs/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Vykreslovat aplikace pod oblastí výseče"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-da/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-da/strings.xml deleted file mode 100644 index d0cc43e8025f..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-da/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Gengiv apps under skærmhakkets område"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-de/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-de/strings.xml deleted file mode 100644 index a7759ea6175a..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-de/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Apps unterhalb des Aussparungs-Bereichs darstellen"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-el/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-el/strings.xml deleted file mode 100644 index b71679a1912f..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-el/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Απόδοση εφαρμογών κάτω από την περιοχή εγκοπής"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-en-rAU/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-en-rAU/strings.xml deleted file mode 100644 index 8c85cbdebb92..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-en-rAU/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Render apps below cutout area"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-en-rCA/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-en-rCA/strings.xml deleted file mode 100644 index 8c85cbdebb92..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-en-rCA/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Render apps below cutout area"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-en-rGB/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-en-rGB/strings.xml deleted file mode 100644 index 8c85cbdebb92..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-en-rGB/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Render apps below cutout area"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-en-rIN/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-en-rIN/strings.xml deleted file mode 100644 index 8c85cbdebb92..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-en-rIN/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Render apps below cutout area"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-en-rXC/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-en-rXC/strings.xml deleted file mode 100644 index 8b72d9f77c49..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-en-rXC/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Render apps below cutout area"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-es-rUS/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-es-rUS/strings.xml deleted file mode 100644 index 359cdd0eab52..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-es-rUS/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Renderizar apps debajo del área de recorte"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-es/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-es/strings.xml deleted file mode 100644 index 47f525ec1d28..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-es/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Renderizar aplicaciones por debajo de la zona de recorte"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-et/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-et/strings.xml deleted file mode 100644 index 0cc5a25868c2..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-et/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Väljalõikeala all olevate rakenduste renderdamine"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-eu/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-eu/strings.xml deleted file mode 100644 index 15d7d6045361..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-eu/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Errendatu mozketa-eremutik kanpo geratzen diren aplikazioak"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-fa/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-fa/strings.xml deleted file mode 100644 index 0865f7559ef9..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-fa/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"پرداز زدن برنامهها در زیر ناحیه بریدهشده"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-fi/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-fi/strings.xml deleted file mode 100644 index 1a6bf7a16839..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-fi/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Renderöi sovellukset lovialueen alle"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-fr-rCA/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-fr-rCA/strings.xml deleted file mode 100644 index ea0a27b069da..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-fr-rCA/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Rendre les applications sous la zone de découpe"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-fr/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-fr/strings.xml deleted file mode 100644 index 6d91a9d603f4..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-fr/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Afficher les applis sous la zone d\'encoche"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-gl/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-gl/strings.xml deleted file mode 100644 index 382497b1caf0..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-gl/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Renderizar aplicacións que aparezan na zona recortada"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-gu/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-gu/strings.xml deleted file mode 100644 index d578d9286d4c..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-gu/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"ઍપને કટઆઉટ ક્ષેત્રની નીચે રેન્ડર કરો"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-hi/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-hi/strings.xml deleted file mode 100644 index e1f09f249bda..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-hi/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"ऐप्लिकेशन को कटआउट एरिया के नीचे दिखाएं"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-hr/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-hr/strings.xml deleted file mode 100644 index db734e8254e5..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-hr/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Renderiraj aplikacije ispod područja ureza"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-hu/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-hu/strings.xml deleted file mode 100644 index 264095b6f4e2..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-hu/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Alkalmazások megjelenítése a kivágási terület alatt"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-hy/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-hy/strings.xml deleted file mode 100644 index 72e67ec1c424..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-hy/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Արտապատկերել հավելվածները էկրանի կտրված հատվածի ներքևում"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-in/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-in/strings.xml deleted file mode 100644 index c49bf0ca939a..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-in/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Render aplikasi di bawah area potongan"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-is/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-is/strings.xml deleted file mode 100644 index 0b90991b0b1e..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-is/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Birta forrit fyrir neðan útklippta svæðið"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-it/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-it/strings.xml deleted file mode 100644 index 2a0f026b39a6..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-it/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Visualizza le app sotto l\'area di ritaglio"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-iw/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-iw/strings.xml deleted file mode 100644 index cc7a0a486c54..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-iw/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"עיבוד האפליקציות שמתחת לאזור המגרעת"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ja/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ja/strings.xml deleted file mode 100644 index 9e99482e5e2a..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ja/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"カットアウト領域の下でアプリをレンダリング"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ka/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ka/strings.xml deleted file mode 100644 index 5464a5699449..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ka/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"აპების ასახვა ჭრილის ქვემოთ"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-kk/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-kk/strings.xml deleted file mode 100644 index 6a2623f8696f..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-kk/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Экран ойығының астындағы қолданбаларды көрсету"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-km/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-km/strings.xml deleted file mode 100644 index 4b4d169cc738..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-km/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"បំប្លែងកម្មវិធីខាងក្រោមផ្នែកឆក"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-kn/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-kn/strings.xml deleted file mode 100644 index 7a929d13d83f..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-kn/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"ಕಟೌಟ್ ಪ್ರದೇಶದ ಕೆಳಗಿನ ಆ್ಯಪ್ಗಳನ್ನು ರೆಂಡರ್ ಮಾಡಿ"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ko/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ko/strings.xml deleted file mode 100644 index 4b9e64020eee..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ko/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"컷아웃 영역 아래에 앱 렌더링"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ky/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ky/strings.xml deleted file mode 100644 index 1ac6a8bb9c1f..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ky/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Колдонмолорду кесилген аймактын ылдый жагында көрсөтүү"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-lo/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-lo/strings.xml deleted file mode 100644 index 4c38580169af..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-lo/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"ສະແດງພາບແອັບຢູ່ທາງລຸ່ມພື້ນທີ່ຮອຍເສັ້ນ"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-lt/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-lt/strings.xml deleted file mode 100644 index c43736d006dd..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-lt/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Pateikti programas po išpjovos sritimi"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-lv/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-lv/strings.xml deleted file mode 100644 index f95abb69abf5..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-lv/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Atveidot lietotnes zem izgriezuma apgabala"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-mk/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-mk/strings.xml deleted file mode 100644 index ff236be46b14..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-mk/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Прикажувај апликации под отсечената област"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ml/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ml/strings.xml deleted file mode 100644 index ef728ab64ab5..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ml/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"കട്ടൗട്ട് ഭാഗത്തിന് താഴെ ആപ്പുകൾ റെൻഡർ ചെയ്യുക"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-mn/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-mn/strings.xml deleted file mode 100644 index 23dbe0c822f0..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-mn/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Аппуудыг тасалж авсан хэсгийн доор буулгах"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-mr/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-mr/strings.xml deleted file mode 100644 index 42f09cb1a1f0..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-mr/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"कटआउट क्षेत्राच्या खाली असलेली ॲप्स रेंडर करा"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ms/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ms/strings.xml deleted file mode 100644 index e348630e0447..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ms/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Serahkan apl di bawah kawasan potongan"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-my/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-my/strings.xml deleted file mode 100644 index 90cb0a5f56a4..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-my/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"ဖြတ်ထုတ်ထားသော နေရာအောက်ရှိ အက်ပ်များ ပြသရန်"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-nb/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-nb/strings.xml deleted file mode 100644 index b8b4e7526ab2..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-nb/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Gjengi apper under utklippsområdet"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ne/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ne/strings.xml deleted file mode 100644 index bd213bb64a0d..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ne/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"कटआउट गरिएको क्षेत्रभन्दा तल पर्ने एपहरू रेन्डर गर्नुहोस्"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-nl/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-nl/strings.xml deleted file mode 100644 index 68f5c0701beb..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-nl/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Apps renderen onder display-cutout"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-or/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-or/strings.xml deleted file mode 100644 index 162a29e8968c..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-or/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"ଆପଗୁଡ଼ିକୁ କଟଆଉଟ୍ ଏରିଆ ନିମ୍ନରେ ରେଣ୍ଡର୍ କରନ୍ତୁ"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-pa/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-pa/strings.xml deleted file mode 100644 index 908393b1abb0..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-pa/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"ਕੱਟਆਊਟ ਖੇਤਰ ਹੇਠ ਐਪਾਂ ਨੂੰ ਰੈਂਡਰ ਕਰੋ"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-pl/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-pl/strings.xml deleted file mode 100644 index c027d5266928..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-pl/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Renderuj aplikacje pod obszarem wycięcia"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-pt-rBR/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-pt-rBR/strings.xml deleted file mode 100644 index d09ed97121fa..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-pt-rBR/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Renderizar apps abaixo da área de corte"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-pt-rPT/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-pt-rPT/strings.xml deleted file mode 100644 index d38ce43204d2..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-pt-rPT/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Renderizar apps abaixo da área de recorte"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-pt/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-pt/strings.xml deleted file mode 100644 index d09ed97121fa..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-pt/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Renderizar apps abaixo da área de corte"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ro/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ro/strings.xml deleted file mode 100644 index 6e5947c0d753..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ro/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Redați aplicațiile sub zona de decupaj"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ru/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ru/strings.xml deleted file mode 100644 index c7f54bbff6a7..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ru/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Отображать приложения под вырезом"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-si/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-si/strings.xml deleted file mode 100644 index 4a14a360e857..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-si/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"කටවුට් ප්රදේශයට පහළින් යෙදුම් විදහන්න"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-sk/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-sk/strings.xml deleted file mode 100644 index 98b82e636392..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-sk/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Vykresľovať aplikácie pod oblasťou výrezu"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-sl/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-sl/strings.xml deleted file mode 100644 index dcf0c842cd36..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-sl/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Upodobitev aplikacij pod predelom zareze zaslona"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-sq/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-sq/strings.xml deleted file mode 100644 index d7b0676970b8..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-sq/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Paraqiti aplikacionet poshtë zonës së prerjes"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-sr/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-sr/strings.xml deleted file mode 100644 index c2b611e70da9..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-sr/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Приказуј апликације испод области изреза"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-sv/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-sv/strings.xml deleted file mode 100644 index 3007ffb99e10..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-sv/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Visa appar under skärmutskärningens område"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-sw/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-sw/strings.xml deleted file mode 100644 index b605554b46f3..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-sw/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Usionyeshe programu chini ya eneo lenye pengo"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ta/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ta/strings.xml deleted file mode 100644 index c4d06fb68564..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ta/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"கட் அவுட் பகுதிக்குள்ளாக ஆப்ஸை ரெண்டர் செய்"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-te/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-te/strings.xml deleted file mode 100644 index 08fa4ae7669b..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-te/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"కట్అవుట్ ఏరియా కింద యాప్లను రెండర్ చేయండి"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-th/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-th/strings.xml deleted file mode 100644 index 9a302507411a..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-th/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"แสดงผลแอปใต้บริเวณรอยบาก"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-tl/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-tl/strings.xml deleted file mode 100644 index a3d4a3afe376..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-tl/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"I-render ang mga app sa ibaba ng lugar ng cutout"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-tr/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-tr/strings.xml deleted file mode 100644 index 12e0f3019814..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-tr/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Uygulamaları kesme alanının altında oluşturun"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-uk/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-uk/strings.xml deleted file mode 100644 index 08b1521a12a0..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-uk/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Відображати додатки під областю вирізу екрана"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ur/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ur/strings.xml deleted file mode 100644 index 711b5389b26c..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-ur/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"کٹ آؤٹ ایریا کے نیچے رینڈر ایپس"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-uz/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-uz/strings.xml deleted file mode 100644 index 7f6f2b45fbd2..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-uz/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Ekran kesimi quyidagi ilovalarni renderlash"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-vi/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-vi/strings.xml deleted file mode 100644 index a7d54fbae9f5..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-vi/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Hiển thị các ứng dụng bên dưới khu vực có vết cắt"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-zh-rCN/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-zh-rCN/strings.xml deleted file mode 100644 index f596520fad30..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-zh-rCN/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"在刘海区域下方呈现应用"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-zh-rHK/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-zh-rHK/strings.xml deleted file mode 100644 index ddb1df77b00c..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-zh-rHK/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"在凹口區域下方輸出應用程式"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-zh-rTW/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-zh-rTW/strings.xml deleted file mode 100644 index 7aad79c11bf2..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-zh-rTW/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"在螢幕凹口底下顯示應用程式畫面"</string> -</resources> diff --git a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-zu/strings.xml b/packages/overlays/AvoidAppsInCutoutOverlay/res/values-zu/strings.xml deleted file mode 100644 index d861c5e60708..000000000000 --- a/packages/overlays/AvoidAppsInCutoutOverlay/res/values-zu/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="3814493834951357513">"Nikezela ngama-app angaphansi kwendawo yokukhipha"</string> -</resources> diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values/config.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values/config.xml index c340432b9b8c..67d405d1e01e 100644 --- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values/config.xml +++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values/config.xml @@ -44,6 +44,9 @@ --> <bool name="config_fillMainBuiltInDisplayCutout">true</bool> + <!-- Height of the status bar --> + <dimen name="status_bar_height_portrait">48dp</dimen> + <dimen name="status_bar_height_landscape">28dp</dimen> </resources> diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values/config.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values/config.xml index 928d9dfa3ce1..e08c32fc4d4b 100644 --- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values/config.xml +++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values/config.xml @@ -56,6 +56,9 @@ --> <bool name="config_fillMainBuiltInDisplayCutout">true</bool> + <!-- Height of the status bar --> + <dimen name="status_bar_height_portrait">48dp</dimen> + <dimen name="status_bar_height_landscape">28dp</dimen> </resources> diff --git a/packages/overlays/DisplayCutoutEmulationHoleOverlay/res/values/config.xml b/packages/overlays/DisplayCutoutEmulationHoleOverlay/res/values/config.xml index 62f0535a1746..68916cc3494c 100644 --- a/packages/overlays/DisplayCutoutEmulationHoleOverlay/res/values/config.xml +++ b/packages/overlays/DisplayCutoutEmulationHoleOverlay/res/values/config.xml @@ -48,6 +48,9 @@ --> <bool name="config_fillMainBuiltInDisplayCutout">true</bool> + <!-- Height of the status bar --> + <dimen name="status_bar_height_portrait">136px</dimen> + <dimen name="status_bar_height_landscape">28dp</dimen> </resources> diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values/config.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values/config.xml index a9f8b4bc6329..605059b27f37 100644 --- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values/config.xml +++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values/config.xml @@ -47,6 +47,9 @@ --> <bool name="config_fillMainBuiltInDisplayCutout">true</bool> + <!-- Height of the status bar --> + <dimen name="status_bar_height_portrait">48dp</dimen> + <dimen name="status_bar_height_landscape">28dp</dimen> </resources> diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values/config.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values/config.xml index be7d0e48fa3f..370d73019669 100644 --- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values/config.xml +++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values/config.xml @@ -47,6 +47,9 @@ --> <bool name="config_fillMainBuiltInDisplayCutout">true</bool> + <!-- Height of the status bar --> + <dimen name="status_bar_height_portrait">48dp</dimen> + <dimen name="status_bar_height_landscape">28dp</dimen> </resources> diff --git a/packages/overlays/DisplayCutoutEmulationWaterfallOverlay/res/values/config.xml b/packages/overlays/DisplayCutoutEmulationWaterfallOverlay/res/values/config.xml index cc51ebee270c..98779f0b3bc1 100644 --- a/packages/overlays/DisplayCutoutEmulationWaterfallOverlay/res/values/config.xml +++ b/packages/overlays/DisplayCutoutEmulationWaterfallOverlay/res/values/config.xml @@ -19,6 +19,12 @@ <string translatable="false" name="config_mainBuiltInDisplayCutout"></string> <string translatable="false" name="config_mainBuiltInDisplayCutoutRectApproximation"></string> + <!-- Height of the status bar in portrait. The height should be + Max((status bar content height + waterfall top size), top cutout size) --> + <dimen name="status_bar_height_portrait">28dp</dimen> + <!-- Max((28 + 20), 0) = 48 --> + <dimen name="status_bar_height_landscape">48dp</dimen> + <dimen name="waterfall_display_left_edge_size">20dp</dimen> <dimen name="waterfall_display_top_edge_size">0dp</dimen> <dimen name="waterfall_display_right_edge_size">20dp</dimen> diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values/config.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values/config.xml index 78cc7e04c7a0..176f1dc46b0c 100644 --- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values/config.xml +++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values/config.xml @@ -47,6 +47,9 @@ --> <bool name="config_fillMainBuiltInDisplayCutout">true</bool> + <!-- Height of the status bar --> + <dimen name="status_bar_height_portrait">48dp</dimen> + <dimen name="status_bar_height_landscape">28dp</dimen> </resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-af/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-af/strings.xml deleted file mode 100644 index b021da75878d..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-af/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Versteek"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-am/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-am/strings.xml deleted file mode 100644 index 0ca6135776b5..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-am/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"ደብቅ"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-ar/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-ar/strings.xml deleted file mode 100644 index 7e41cb1935b9..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-ar/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"إخفاء"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-as/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-as/strings.xml deleted file mode 100644 index d2399fffc8c3..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-as/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"লুকুৱাওক"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-az/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-az/strings.xml deleted file mode 100644 index 420c5133cbd1..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-az/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Gizlədin"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-b+sr+Latn/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-b+sr+Latn/strings.xml deleted file mode 100644 index 082e5864065f..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-b+sr+Latn/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Sakrij"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-be/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-be/strings.xml deleted file mode 100644 index ce75c4584dac..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-be/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Схаваць"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-bg/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-bg/strings.xml deleted file mode 100644 index 7c3170c73355..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-bg/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Скриване"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-bn/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-bn/strings.xml deleted file mode 100644 index 1e627256d943..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-bn/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"লুকান"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-bs/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-bs/strings.xml deleted file mode 100644 index 082e5864065f..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-bs/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Sakrij"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-ca/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-ca/strings.xml deleted file mode 100644 index 6ae5ffd32bf8..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-ca/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Amaga"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-cs/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-cs/strings.xml deleted file mode 100644 index 068bb9463c33..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-cs/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Skrýt"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-da/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-da/strings.xml deleted file mode 100644 index 6ecb7674d65b..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-da/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Skjul"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-de/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-de/strings.xml deleted file mode 100644 index 44278e800c5a..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-de/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Ausblenden"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-el/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-el/strings.xml deleted file mode 100644 index 96b1b86dd4bc..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-el/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Απόκρυψη"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-en-rAU/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-en-rAU/strings.xml deleted file mode 100644 index 1ab9b2d49ee1..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-en-rAU/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Hide"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-en-rCA/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-en-rCA/strings.xml deleted file mode 100644 index 1ab9b2d49ee1..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-en-rCA/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Hide"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-en-rGB/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-en-rGB/strings.xml deleted file mode 100644 index 1ab9b2d49ee1..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-en-rGB/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Hide"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-en-rIN/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-en-rIN/strings.xml deleted file mode 100644 index 1ab9b2d49ee1..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-en-rIN/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Hide"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-en-rXC/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-en-rXC/strings.xml deleted file mode 100644 index a20e59446fcb..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-en-rXC/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Hide"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-es-rUS/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-es-rUS/strings.xml deleted file mode 100644 index 351c1cdf3084..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-es-rUS/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Ocultar"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-es/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-es/strings.xml deleted file mode 100644 index 351c1cdf3084..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-es/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Ocultar"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-et/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-et/strings.xml deleted file mode 100644 index 4e5428dc59b8..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-et/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Peida"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-eu/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-eu/strings.xml deleted file mode 100644 index f33bb5005cb3..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-eu/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Ezkutatu"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-fa/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-fa/strings.xml deleted file mode 100644 index 8de756085a84..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-fa/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"پنهان کردن"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-fi/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-fi/strings.xml deleted file mode 100644 index c42e52d1aaaf..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-fi/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Piilota"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-fr-rCA/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-fr-rCA/strings.xml deleted file mode 100644 index 31fa56766ebc..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-fr-rCA/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Masquer"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-fr/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-fr/strings.xml deleted file mode 100644 index 31fa56766ebc..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-fr/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Masquer"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-gl/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-gl/strings.xml deleted file mode 100644 index 351c1cdf3084..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-gl/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Ocultar"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-gu/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-gu/strings.xml deleted file mode 100644 index 7e4b33a8749c..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-gu/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"છુપાવો"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-hi/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-hi/strings.xml deleted file mode 100644 index 1513f2a8ffe5..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-hi/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"छिपाएं"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-hr/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-hr/strings.xml deleted file mode 100644 index 082e5864065f..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-hr/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Sakrij"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-hu/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-hu/strings.xml deleted file mode 100644 index 2b9717fca1cf..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-hu/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Elrejtés"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-hy/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-hy/strings.xml deleted file mode 100644 index 3407bb499645..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-hy/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Թաքցնել"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-in/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-in/strings.xml deleted file mode 100644 index 6c017b390aa2..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-in/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Sembunyikan"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-is/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-is/strings.xml deleted file mode 100644 index 229c113bbdb3..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-is/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Fela"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-it/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-it/strings.xml deleted file mode 100644 index 07444aa372f6..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-it/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Nascondi"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-iw/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-iw/strings.xml deleted file mode 100644 index 221a129317f9..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-iw/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"הסתרה"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-ja/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-ja/strings.xml deleted file mode 100644 index 3bf17fb81abe..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-ja/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"非表示"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-ka/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-ka/strings.xml deleted file mode 100644 index 160052841a7c..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-ka/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"დამალვა"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-kk/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-kk/strings.xml deleted file mode 100644 index 23d02b81c62e..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-kk/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Жасыру"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-km/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-km/strings.xml deleted file mode 100644 index 624b81fa6dcc..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-km/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"លាក់"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-kn/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-kn/strings.xml deleted file mode 100644 index 9cd6da7fb314..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-kn/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"ಮರೆಮಾಡಿ"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-ko/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-ko/strings.xml deleted file mode 100644 index efb656860724..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-ko/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"숨기기"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-ky/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-ky/strings.xml deleted file mode 100644 index 419132513fad..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-ky/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Жашыруу"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-lo/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-lo/strings.xml deleted file mode 100644 index 8850dfb2d244..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-lo/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"ເຊື່ອງ"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-lt/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-lt/strings.xml deleted file mode 100644 index 6364b96096e0..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-lt/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Slėpti"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-lv/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-lv/strings.xml deleted file mode 100644 index 61f2ad3d51fb..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-lv/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Paslēpt"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-mk/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-mk/strings.xml deleted file mode 100644 index 505c2059f5ac..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-mk/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Сокриј"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-ml/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-ml/strings.xml deleted file mode 100644 index 1c30dec6bc83..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-ml/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"മറയ്ക്കുക"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-mn/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-mn/strings.xml deleted file mode 100644 index 7e2719b719fe..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-mn/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Нуух"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-mr/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-mr/strings.xml deleted file mode 100644 index 46f0ab889226..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-mr/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"लपवा"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-ms/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-ms/strings.xml deleted file mode 100644 index 6c017b390aa2..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-ms/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Sembunyikan"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-my/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-my/strings.xml deleted file mode 100644 index 84be3f9a0986..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-my/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"ဝှက်ရန်"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-nb/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-nb/strings.xml deleted file mode 100644 index 6ecb7674d65b..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-nb/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Skjul"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-ne/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-ne/strings.xml deleted file mode 100644 index ff920b290dbb..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-ne/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"लुकाइयोस्"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-nl/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-nl/strings.xml deleted file mode 100644 index 00900f8c6f6f..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-nl/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Verbergen"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-or/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-or/strings.xml deleted file mode 100644 index fcfd7252a8bf..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-or/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"ଲୁଚାନ୍ତୁ"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-pa/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-pa/strings.xml deleted file mode 100644 index 9f37e0bce721..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-pa/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"ਲੁਕਾਓ"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-pl/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-pl/strings.xml deleted file mode 100644 index 3d65546bf794..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-pl/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Ukryj"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-pt-rBR/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-pt-rBR/strings.xml deleted file mode 100644 index 351c1cdf3084..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-pt-rBR/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Ocultar"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-pt-rPT/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-pt-rPT/strings.xml deleted file mode 100644 index 351c1cdf3084..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-pt-rPT/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Ocultar"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-pt/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-pt/strings.xml deleted file mode 100644 index 351c1cdf3084..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-pt/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Ocultar"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-ro/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-ro/strings.xml deleted file mode 100644 index e6281fd09b1a..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-ro/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Ascundeți"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-ru/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-ru/strings.xml deleted file mode 100644 index 901839684a9b..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-ru/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Скрыть"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-si/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-si/strings.xml deleted file mode 100644 index b06a52cfc90c..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-si/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"සඟවන්න"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-sk/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-sk/strings.xml deleted file mode 100644 index 965d95b0f389..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-sk/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Skryť"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-sl/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-sl/strings.xml deleted file mode 100644 index e8adb9810303..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-sl/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Skrij"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-sq/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-sq/strings.xml deleted file mode 100644 index 85fb95a1f283..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-sq/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Fshih"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-sr/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-sr/strings.xml deleted file mode 100644 index 26afbf962495..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-sr/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Сакриј"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-sv/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-sv/strings.xml deleted file mode 100644 index 193c1798fc87..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-sv/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Dölj"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-sw/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-sw/strings.xml deleted file mode 100644 index 58e35e2eadfd..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-sw/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Ficha"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-ta/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-ta/strings.xml deleted file mode 100644 index b743c660f183..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-ta/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"மறை"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-te/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-te/strings.xml deleted file mode 100644 index de04152a4e20..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-te/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"దాచండి"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-th/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-th/strings.xml deleted file mode 100644 index 1c8bd9d01818..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-th/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"ซ่อน"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-tl/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-tl/strings.xml deleted file mode 100644 index cc45f6335271..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-tl/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Itago"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-tr/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-tr/strings.xml deleted file mode 100644 index b20f1f7d3120..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-tr/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Gizle"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-uk/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-uk/strings.xml deleted file mode 100644 index 938b0e222af1..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-uk/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Сховати"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-ur/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-ur/strings.xml deleted file mode 100644 index 0f081705f6f1..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-ur/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"چھپائیں"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-uz/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-uz/strings.xml deleted file mode 100644 index 5d22045d9cdc..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-uz/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Berkitish"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-vi/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-vi/strings.xml deleted file mode 100644 index fc83d257fdba..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-vi/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Ẩn"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-zh-rCN/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-zh-rCN/strings.xml deleted file mode 100644 index acdfd1c2e4a5..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-zh-rCN/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"隐藏"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-zh-rHK/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-zh-rHK/strings.xml deleted file mode 100644 index abb8e81fbca4..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-zh-rHK/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"隱藏"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-zh-rTW/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-zh-rTW/strings.xml deleted file mode 100644 index abb8e81fbca4..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-zh-rTW/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"隱藏"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values-zu/strings.xml b/packages/overlays/NoCutoutOverlay/res/values-zu/strings.xml deleted file mode 100644 index 11842d91a53a..000000000000 --- a/packages/overlays/NoCutoutOverlay/res/values-zu/strings.xml +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ~ Copyright (C) 2021 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. - --> - -<resources xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> - <string name="display_cutout_emulation_overlay" msgid="9031691255599853162">"Fihla"</string> -</resources> diff --git a/packages/overlays/NoCutoutOverlay/res/values/config.xml b/packages/overlays/NoCutoutOverlay/res/values/config.xml index 84b91b85350d..ed0340b11229 100644 --- a/packages/overlays/NoCutoutOverlay/res/values/config.xml +++ b/packages/overlays/NoCutoutOverlay/res/values/config.xml @@ -25,4 +25,7 @@ by shrinking the display such that it does not overlap the cutout area. --> <bool name="config_maskMainBuiltInDisplayCutout">true</bool> + <!-- Height of the status bar --> + <dimen name="status_bar_height_portrait">28dp</dimen> + <dimen name="status_bar_height_landscape">28dp</dimen> </resources> diff --git a/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java b/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java index 5718bdfc4971..9298b1e7efbf 100644 --- a/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java +++ b/services/backup/java/com/android/server/backup/restore/FullRestoreEngine.java @@ -25,8 +25,10 @@ import static com.android.server.backup.UserBackupManagerService.OP_TYPE_RESTORE import static com.android.server.backup.UserBackupManagerService.SHARED_BACKUP_AGENT_PACKAGE; import static com.android.server.backup.internal.BackupHandler.MSG_RESTORE_OPERATION_TIMEOUT; +import android.annotation.NonNull; import android.app.ApplicationThreadConstants; import android.app.IBackupAgent; +import android.app.backup.BackupAgent; import android.app.backup.BackupManager; import android.app.backup.FullBackup; import android.app.backup.IBackupManagerMonitor; @@ -39,10 +41,12 @@ import android.content.pm.Signature; import android.os.ParcelFileDescriptor; import android.os.RemoteException; import android.provider.Settings; +import android.system.OsConstants; import android.text.TextUtils; import android.util.Slog; import com.android.internal.annotations.GuardedBy; +import com.android.internal.annotations.VisibleForTesting; import com.android.server.LocalServices; import com.android.server.backup.BackupAgentTimeoutParameters; import com.android.server.backup.BackupRestoreTask; @@ -56,6 +60,7 @@ import com.android.server.backup.utils.FullBackupRestoreObserverUtils; import com.android.server.backup.utils.RestoreUtils; import com.android.server.backup.utils.TarBackupReader; +import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; @@ -132,6 +137,7 @@ public class FullRestoreEngine extends RestoreEngine { @GuardedBy("mPipesLock") private boolean mPipesClosed; private final BackupEligibilityRules mBackupEligibilityRules; + private FileMetadata mReadOnlyParent = null; public FullRestoreEngine(UserBackupManagerService backupManagerService, BackupRestoreTask monitorTask, IFullBackupRestoreObserver observer, @@ -154,6 +160,21 @@ public class FullRestoreEngine extends RestoreEngine { mBackupEligibilityRules = backupEligibilityRules; } + @VisibleForTesting + FullRestoreEngine() { + mIsAdbRestore = false; + mAllowApks = false; + mEphemeralOpToken = 0; + mUserId = 0; + mBackupEligibilityRules = null; + mAgentTimeoutParameters = null; + mBuffer = null; + mBackupManagerService = null; + mMonitor = null; + mMonitorTask = null; + mOnlyPackage = null; + } + public IBackupAgent getAgent() { return mAgent; } @@ -393,6 +414,11 @@ public class FullRestoreEngine extends RestoreEngine { okay = false; } + if (shouldSkipReadOnlyDir(info)) { + // b/194894879: We don't support restore of read-only dirs. + okay = false; + } + // At this point we have an agent ready to handle the full // restore data as well as a pipe for sending data to // that agent. Tell the agent to start reading from the @@ -569,6 +595,45 @@ public class FullRestoreEngine extends RestoreEngine { return (info != null); } + boolean shouldSkipReadOnlyDir(FileMetadata info) { + if (isValidParent(mReadOnlyParent, info)) { + // This file has a read-only parent directory, we shouldn't + // restore it. + return true; + } else { + // We're now in a different branch of the file tree, update the parent + // value. + if (isReadOnlyDir(info)) { + // Current directory is read-only. Remember it so that we can skip all + // of its contents. + mReadOnlyParent = info; + Slog.w(TAG, "Skipping restore of " + info.path + " and its contents as " + + "read-only dirs are currently not supported."); + return true; + } else { + mReadOnlyParent = null; + } + } + + return false; + } + + private static boolean isValidParent(FileMetadata parentDir, @NonNull FileMetadata childDir) { + return parentDir != null + && childDir.packageName.equals(parentDir.packageName) + && childDir.domain.equals(parentDir.domain) + && childDir.path.startsWith(getPathWithTrailingSeparator(parentDir.path)); + } + + private static String getPathWithTrailingSeparator(String path) { + return path.endsWith(File.separator) ? path : path + File.separator; + } + + private static boolean isReadOnlyDir(FileMetadata file) { + // Check if owner has 'write' bit in the file's mode value (see 'man -7 inode' for details). + return file.type == BackupAgent.TYPE_DIRECTORY && (file.mode & OsConstants.S_IWUSR) == 0; + } + private void setUpPipes() throws IOException { synchronized (mPipesLock) { mPipes = ParcelFileDescriptor.createPipe(); diff --git a/services/core/java/com/android/server/FactoryResetter.java b/services/core/java/com/android/server/FactoryResetter.java new file mode 100644 index 000000000000..30314a3683a6 --- /dev/null +++ b/services/core/java/com/android/server/FactoryResetter.java @@ -0,0 +1,54 @@ +/* + * 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.server; + +import android.content.Context; +import android.content.pm.PackageManager; + +import com.android.internal.util.Preconditions; + +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * TODO(b/225012970): add javadoc from {@code com.android.server.devicepolicy.FactoryResetter} + */ +public final class FactoryResetter { + + private static final AtomicBoolean sFactoryResetting = new AtomicBoolean(false); + + /** + * Checks whether a factory reset is in progress. + */ + public static boolean isFactoryResetting() { + return sFactoryResetting.get(); + } + + /** + * @deprecated called by {@code com.android.server.devicepolicy.FactoryResetter}, won't be + * needed once that class logic is moved into this. + */ + @Deprecated + public static void setFactoryResetting(Context context) { + Preconditions.checkCallAuthorization(context.checkCallingOrSelfPermission( + android.Manifest.permission.MASTER_CLEAR) == PackageManager.PERMISSION_GRANTED); + sFactoryResetting.set(true); + } + + private FactoryResetter() { + throw new UnsupportedOperationException("Provides only static methods"); + } +} diff --git a/services/core/java/com/android/server/GestureLauncherService.java b/services/core/java/com/android/server/GestureLauncherService.java index d04698cb5aeb..ab8b6ab491f1 100644 --- a/services/core/java/com/android/server/GestureLauncherService.java +++ b/services/core/java/com/android/server/GestureLauncherService.java @@ -83,6 +83,20 @@ public class GestureLauncherService extends SystemService { private static final int EMERGENCY_GESTURE_POWER_TAP_COUNT_THRESHOLD = 5; /** + * Default value of the power button "cooldown" period after the Emergency gesture is triggered. + * See {@link Settings.Global#EMERGENCY_GESTURE_POWER_BUTTON_COOLDOWN_PERIOD_MS} + */ + private static final int EMERGENCY_GESTURE_POWER_BUTTON_COOLDOWN_PERIOD_MS_DEFAULT = 3000; + + /** + * Maximum value of the power button "cooldown" period after the Emergency gesture is triggered. + * The value read from {@link Settings.Global#EMERGENCY_GESTURE_POWER_BUTTON_COOLDOWN_PERIOD_MS} + * is capped at this maximum. + */ + @VisibleForTesting + static final int EMERGENCY_GESTURE_POWER_BUTTON_COOLDOWN_PERIOD_MS_MAX = 5000; + + /** * Number of taps required to launch camera shortcut. */ private static final int CAMERA_POWER_TAP_COUNT_THRESHOLD = 2; @@ -145,7 +159,14 @@ public class GestureLauncherService extends SystemService { */ private boolean mEmergencyGestureEnabled; + /** + * Power button cooldown period in milliseconds, after emergency gesture is triggered. A zero + * value means the cooldown period is disabled. + */ + private int mEmergencyGesturePowerButtonCooldownPeriodMs; + private long mLastPowerDown; + private long mLastEmergencyGestureTriggered; private int mPowerButtonConsecutiveTaps; private int mPowerButtonSlowConsecutiveTaps; private final UiEventLogger mUiEventLogger; @@ -210,6 +231,7 @@ public class GestureLauncherService extends SystemService { updateCameraRegistered(); updateCameraDoubleTapPowerEnabled(); updateEmergencyGestureEnabled(); + updateEmergencyGesturePowerButtonCooldownPeriodMs(); mUserId = ActivityManager.getCurrentUser(); mContext.registerReceiver(mUserReceiver, new IntentFilter(Intent.ACTION_USER_SWITCHED)); @@ -230,6 +252,10 @@ public class GestureLauncherService extends SystemService { mContext.getContentResolver().registerContentObserver( Settings.Secure.getUriFor(Settings.Secure.EMERGENCY_GESTURE_ENABLED), false, mSettingObserver, mUserId); + mContext.getContentResolver().registerContentObserver( + Settings.Global.getUriFor( + Settings.Global.EMERGENCY_GESTURE_POWER_BUTTON_COOLDOWN_PERIOD_MS), + false, mSettingObserver, mUserId); } private void updateCameraRegistered() { @@ -263,6 +289,14 @@ public class GestureLauncherService extends SystemService { } } + @VisibleForTesting + void updateEmergencyGesturePowerButtonCooldownPeriodMs() { + int cooldownPeriodMs = getEmergencyGesturePowerButtonCooldownPeriodMs(mContext, mUserId); + synchronized (this) { + mEmergencyGesturePowerButtonCooldownPeriodMs = cooldownPeriodMs; + } + } + private void unregisterCameraLaunchGesture() { if (mCameraLaunchRegistered) { mCameraLaunchRegistered = false; @@ -398,6 +432,21 @@ public class GestureLauncherService extends SystemService { } /** + * Gets power button cooldown period in milliseconds after emergency gesture is triggered. The + * value is capped at a maximum + * {@link GestureLauncherService#EMERGENCY_GESTURE_POWER_BUTTON_COOLDOWN_PERIOD_MS_MAX}. If the + * value is zero, it means the cooldown period is disabled. + */ + @VisibleForTesting + static int getEmergencyGesturePowerButtonCooldownPeriodMs(Context context, int userId) { + int cooldown = Settings.Global.getInt(context.getContentResolver(), + Settings.Global.EMERGENCY_GESTURE_POWER_BUTTON_COOLDOWN_PERIOD_MS, + EMERGENCY_GESTURE_POWER_BUTTON_COOLDOWN_PERIOD_MS_DEFAULT); + + return Math.min(cooldown, EMERGENCY_GESTURE_POWER_BUTTON_COOLDOWN_PERIOD_MS_MAX); + } + + /** * Whether to enable the camera launch gesture. */ private static boolean isCameraLaunchEnabled(Resources resources) { @@ -445,10 +494,24 @@ public class GestureLauncherService extends SystemService { */ public boolean interceptPowerKeyDown(KeyEvent event, boolean interactive, MutableBoolean outLaunched) { + if (mEmergencyGestureEnabled && mEmergencyGesturePowerButtonCooldownPeriodMs >= 0 + && event.getEventTime() - mLastEmergencyGestureTriggered + < mEmergencyGesturePowerButtonCooldownPeriodMs) { + Slog.i(TAG, String.format( + "Suppressing power button: within %dms cooldown period after Emergency " + + "Gesture. Begin=%dms, end=%dms.", + mEmergencyGesturePowerButtonCooldownPeriodMs, + mLastEmergencyGestureTriggered, + mLastEmergencyGestureTriggered + mEmergencyGesturePowerButtonCooldownPeriodMs)); + outLaunched.value = false; + return true; + } + if (event.isLongPress()) { // Long presses are sent as a second key down. If the long press threshold is set lower // than the double tap of sequence interval thresholds, this could cause false double // taps or consecutive taps, so we want to ignore the long press event. + outLaunched.value = false; return false; } boolean launchCamera = false; @@ -509,6 +572,12 @@ public class GestureLauncherService extends SystemService { Slog.i(TAG, "Emergency gesture detected, launching."); launchEmergencyGesture = handleEmergencyGesture(); mUiEventLogger.log(GestureLauncherEvent.GESTURE_EMERGENCY_TAP_POWER); + // Record emergency trigger time if emergency UI was launched + if (launchEmergencyGesture) { + synchronized (this) { + mLastEmergencyGestureTriggered = event.getEventTime(); + } + } } mMetricsLogger.histogram("power_consecutive_short_tap_count", mPowerButtonSlowConsecutiveTaps); @@ -600,6 +669,7 @@ public class GestureLauncherService extends SystemService { updateCameraRegistered(); updateCameraDoubleTapPowerEnabled(); updateEmergencyGestureEnabled(); + updateEmergencyGesturePowerButtonCooldownPeriodMs(); } } }; @@ -610,6 +680,7 @@ public class GestureLauncherService extends SystemService { updateCameraRegistered(); updateCameraDoubleTapPowerEnabled(); updateEmergencyGestureEnabled(); + updateEmergencyGesturePowerButtonCooldownPeriodMs(); } } }; diff --git a/services/core/java/com/android/server/TEST_MAPPING b/services/core/java/com/android/server/TEST_MAPPING index 9e8b9c62ff51..3288ca837c1f 100644 --- a/services/core/java/com/android/server/TEST_MAPPING +++ b/services/core/java/com/android/server/TEST_MAPPING @@ -23,21 +23,6 @@ "file_patterns": ["NotificationManagerService\\.java"] }, { - "name": "CtsContentTestCases", - "options": [ - { - "include-filter": "android.content.cts.ClipboardManagerTest" - }, - { - "include-filter": "android.content.cts.ClipDataTest" - }, - { - "include-filter": "android.content.cts.ClipDescriptionTest" - } - ], - "file_patterns": ["ClipboardService\\.java"] - }, - { "name": "FrameworksMockingServicesTests", "options": [ { @@ -59,6 +44,21 @@ { "name": "CtsScopedStorageDeviceOnlyTest", "file_patterns": ["StorageManagerService\\.java"] + }, + { + "name": "CtsContentTestCases", + "options": [ + { + "include-filter": "android.content.cts.ClipboardManagerTest" + }, + { + "include-filter": "android.content.cts.ClipDataTest" + }, + { + "include-filter": "android.content.cts.ClipDescriptionTest" + } + ], + "file_patterns": ["ClipboardService\\.java"] } ] } diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index fd109ff12ba6..e28170f63795 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -551,6 +551,7 @@ public class ActivityManagerService extends IActivityManager.Stub static final String EXTRA_TITLE = "android.intent.extra.TITLE"; static final String EXTRA_DESCRIPTION = "android.intent.extra.DESCRIPTION"; static final String EXTRA_BUGREPORT_TYPE = "android.intent.extra.BUGREPORT_TYPE"; + static final String EXTRA_BUGREPORT_NONCE = "android.intent.extra.BUGREPORT_NONCE"; /** * The maximum number of bytes that {@link #setProcessStateSummary} accepts. @@ -6607,7 +6608,7 @@ public class ActivityManagerService extends IActivityManager.Stub */ @Override public void requestBugReport(@BugreportParams.BugreportMode int bugreportType) { - requestBugReportWithDescription(null, null, bugreportType); + requestBugReportWithDescription(null, null, bugreportType, 0L); } /** @@ -6617,6 +6618,15 @@ public class ActivityManagerService extends IActivityManager.Stub @Override public void requestBugReportWithDescription(@Nullable String shareTitle, @Nullable String shareDescription, int bugreportType) { + requestBugReportWithDescription(shareTitle, shareDescription, bugreportType, /*nonce*/ 0L); + } + + /** + * Takes a bugreport using bug report API ({@code BugreportManager}) which gets + * triggered by sending a broadcast to Shell. + */ + public void requestBugReportWithDescription(@Nullable String shareTitle, + @Nullable String shareDescription, int bugreportType, long nonce) { String type = null; switch (bugreportType) { case BugreportParams.BUGREPORT_MODE_FULL: @@ -6667,6 +6677,7 @@ public class ActivityManagerService extends IActivityManager.Stub triggerShellBugreport.setAction(INTENT_BUGREPORT_REQUESTED); triggerShellBugreport.setPackage(SHELL_APP_PACKAGE); triggerShellBugreport.putExtra(EXTRA_BUGREPORT_TYPE, bugreportType); + triggerShellBugreport.putExtra(EXTRA_BUGREPORT_NONCE, nonce); triggerShellBugreport.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); triggerShellBugreport.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND); if (shareTitle != null) { @@ -6733,8 +6744,8 @@ public class ActivityManagerService extends IActivityManager.Stub * Takes a bugreport remotely */ @Override - public void requestRemoteBugReport() { - requestBugReportWithDescription(null, null, BugreportParams.BUGREPORT_MODE_REMOTE); + public void requestRemoteBugReport(long nonce) { + requestBugReportWithDescription(null, null, BugreportParams.BUGREPORT_MODE_REMOTE, nonce); } /** @@ -13825,14 +13836,26 @@ public class ActivityManagerService extends IActivityManager.Stub return false; } - if (!Build.IS_DEBUGGABLE) { - int match = mContext.getPackageManager().checkSignatures( - ii.targetPackage, ii.packageName); - if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) { + int match = mContext.getPackageManager().checkSignatures( + ii.targetPackage, ii.packageName); + if (match < 0 && match != PackageManager.SIGNATURE_FIRST_NOT_SIGNED) { + if (Build.IS_DEBUGGABLE) { + String message = "Instrumentation test " + ii.packageName + + " doesn't have a signature matching the target " + + ii.targetPackage + + ", which would not be allowed on the production Android builds"; + if (callingUid != Process.ROOT_UID) { + Slog.e(TAG, message + + ". THIS WILL BE DISALLOWED ON FUTURE ANDROID VERSIONS" + + " unless from a rooted ADB shell."); + } else { + Slog.w(TAG, message); + } + } else { String msg = "Permission Denial: starting instrumentation " + className + " from pid=" + Binder.getCallingPid() - + ", uid=" + Binder.getCallingPid() + + ", uid=" + Binder.getCallingUid() + " not allowed because package " + ii.packageName + " does not have a signature matching the target " + ii.targetPackage; diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java index 5a43f4d6c3dc..c465be149ac2 100644 --- a/services/core/java/com/android/server/am/UserController.java +++ b/services/core/java/com/android/server/am/UserController.java @@ -106,6 +106,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; import com.android.internal.util.FrameworkStatsLog; import com.android.internal.widget.LockPatternUtils; +import com.android.server.FactoryResetter; import com.android.server.FgThread; import com.android.server.LocalServices; import com.android.server.SystemServiceManager; @@ -1756,6 +1757,10 @@ class UserController implements Handler.Callback { Slogf.w(TAG, "Cannot switch to User #" + targetUserId + ": not a full user"); return false; } + if (FactoryResetter.isFactoryResetting()) { + Slogf.w(TAG, "Cannot switch to User #" + targetUserId + ": factory reset in progress"); + return false; + } boolean userSwitchUiEnabled; synchronized (mLock) { if (!mInitialized) { diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java index a81699fa82c3..6ce7b1ae1ef3 100644 --- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java +++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java @@ -251,8 +251,8 @@ import java.util.concurrent.atomic.AtomicBoolean; return; } } - setCommunicationRouteForClient( - cb, pid, device, BtHelper.SCO_MODE_UNDEFINED, eventSource); + postSetCommunicationRouteForClient(new CommunicationClientInfo( + cb, pid, device, BtHelper.SCO_MODE_UNDEFINED, eventSource)); } } } @@ -282,8 +282,8 @@ import java.util.concurrent.atomic.AtomicBoolean; return false; } } - setCommunicationRouteForClient( - cb, pid, deviceAttr, BtHelper.SCO_MODE_UNDEFINED, eventSource); + postSetCommunicationRouteForClient(new CommunicationClientInfo( + cb, pid, deviceAttr, BtHelper.SCO_MODE_UNDEFINED, eventSource)); } } return true; @@ -347,26 +347,35 @@ import java.util.concurrent.atomic.AtomicBoolean; } /** - * Returns the device currently requested for communication use case. - * If the current audio mode owner is in the communication route client list, - * use this preference. - * Otherwise use first client's preference (first client corresponds to latest request). - * null is returned if no client is in the list. - * @return AudioDeviceAttributes the requested device for communication. + * Returns the communication client with the highest priority: + * - 1) the client which is currently also controlling the audio mode + * - 2) the first client in the stack if there is no audio mode owner + * - 3) no client otherwise + * @return CommunicationRouteClient the client driving the communication use case routing. */ - @GuardedBy("mDeviceStateLock") - private AudioDeviceAttributes requestedCommunicationDevice() { - AudioDeviceAttributes device = null; - for (CommunicationRouteClient cl : mCommunicationRouteClients) { - if (cl.getPid() == mModeOwnerPid) { - device = cl.getDevice(); + private CommunicationRouteClient topCommunicationRouteClient() { + for (CommunicationRouteClient crc : mCommunicationRouteClients) { + if (crc.getPid() == mModeOwnerPid) { + return crc; } } if (!mCommunicationRouteClients.isEmpty() && mModeOwnerPid == 0) { - device = mCommunicationRouteClients.get(0).getDevice(); + return mCommunicationRouteClients.get(0); } + return null; + } + /** + * Returns the device currently requested for communication use case. + * Use the device requested by the communication route client selected by + * {@link #topCommunicationRouteClient()} if any or none otherwise. + * @return AudioDeviceAttributes the requested device for communication. + */ + @GuardedBy("mDeviceStateLock") + private AudioDeviceAttributes requestedCommunicationDevice() { + CommunicationRouteClient crc = topCommunicationRouteClient(); + AudioDeviceAttributes device = crc != null ? crc.getDevice() : null; if (AudioService.DEBUG_COMM_RTE) { Log.v(TAG, "requestedCommunicationDevice, device: " + device + " mode owner pid: " + mModeOwnerPid); @@ -696,7 +705,7 @@ import java.util.concurrent.atomic.AtomicBoolean; } synchronized (mDeviceStateLock) { mBluetoothScoOn = on; - sendLMsgNoDelay(MSG_L_UPDATE_COMMUNICATION_ROUTE, SENDMSG_QUEUE, eventSource); + postUpdateCommunicationRouteClient(eventSource); } } @@ -756,7 +765,9 @@ import java.util.concurrent.atomic.AtomicBoolean; synchronized (mDeviceStateLock) { AudioDeviceAttributes device = new AudioDeviceAttributes(AudioSystem.DEVICE_OUT_BLUETOOTH_SCO, ""); - setCommunicationRouteForClient(cb, pid, device, scoAudioMode, eventSource); + + postSetCommunicationRouteForClient(new CommunicationClientInfo( + cb, pid, device, scoAudioMode, eventSource)); } } } @@ -774,8 +785,8 @@ import java.util.concurrent.atomic.AtomicBoolean; if (client == null || !client.requestsBluetoothSco()) { return; } - setCommunicationRouteForClient( - cb, pid, null, BtHelper.SCO_MODE_UNDEFINED, eventSource); + postSetCommunicationRouteForClient(new CommunicationClientInfo( + cb, pid, null, BtHelper.SCO_MODE_UNDEFINED, eventSource)); } } } @@ -976,6 +987,61 @@ import java.util.concurrent.atomic.AtomicBoolean; MSG_I_SAVE_CLEAR_PREF_DEVICES_FOR_CAPTURE_PRESET, SENDMSG_QUEUE, capturePreset); } + /*package*/ void postUpdateCommunicationRouteClient(String eventSource) { + sendLMsgNoDelay(MSG_L_UPDATE_COMMUNICATION_ROUTE_CLIENT, SENDMSG_QUEUE, eventSource); + } + + /*package*/ void postSetCommunicationRouteForClient(CommunicationClientInfo info) { + sendLMsgNoDelay(MSG_L_SET_COMMUNICATION_ROUTE_FOR_CLIENT, SENDMSG_QUEUE, info); + } + + /*package*/ void postScoAudioStateChanged(int state) { + sendIMsgNoDelay(MSG_I_SCO_AUDIO_STATE_CHANGED, SENDMSG_QUEUE, state); + } + + /*package*/ static final class CommunicationClientInfo { + final @NonNull IBinder mCb; + final int mPid; + final @NonNull AudioDeviceAttributes mDevice; + final int mScoAudioMode; + final @NonNull String mEventSource; + + CommunicationClientInfo(@NonNull IBinder cb, int pid, @NonNull AudioDeviceAttributes device, + int scoAudioMode, @NonNull String eventSource) { + mCb = cb; + mPid = pid; + mDevice = device; + mScoAudioMode = scoAudioMode; + mEventSource = eventSource; + } + + // redefine equality op so we can match messages intended for this client + @Override + public boolean equals(Object o) { + if (o == null) { + return false; + } + if (this == o) { + return true; + } + if (!(o instanceof CommunicationClientInfo)) { + return false; + } + + return mCb.equals(((CommunicationClientInfo) o).mCb) + && mPid == ((CommunicationClientInfo) o).mPid; + } + + @Override + public String toString() { + return "CommunicationClientInfo mCb=" + mCb.toString() + +"mPid=" + mPid + +"mDevice=" + mDevice.toString() + +"mScoAudioMode=" + mScoAudioMode + +"mEventSource=" + mEventSource; + } + } + //--------------------------------------------------------------------- // Method forwarding between the helper classes (BtHelper, AudioDeviceInventory) // only call from a "handle"* method or "on"* method @@ -1255,18 +1321,30 @@ import java.util.concurrent.atomic.AtomicBoolean; synchronized (mDeviceStateLock) { mModeOwnerPid = msg.arg1; if (msg.arg2 != AudioSystem.MODE_RINGTONE) { - onUpdateCommunicationRoute("setNewModeOwner"); + onUpdateCommunicationRouteClient("setNewModeOwner"); } } } break; - case MSG_L_COMMUNICATION_ROUTE_CLIENT_DIED: + + case MSG_L_SET_COMMUNICATION_ROUTE_FOR_CLIENT: synchronized (mSetModeLock) { synchronized (mDeviceStateLock) { - onCommunicationRouteClientDied((CommunicationRouteClient) msg.obj); + CommunicationClientInfo info = (CommunicationClientInfo) msg.obj; + setCommunicationRouteForClient(info.mCb, info.mPid, info.mDevice, + info.mScoAudioMode, info.mEventSource); + } + } + break; + + case MSG_L_UPDATE_COMMUNICATION_ROUTE_CLIENT: + synchronized (mSetModeLock) { + synchronized (mDeviceStateLock) { + onUpdateCommunicationRouteClient((String) msg.obj); } } break; + case MSG_L_UPDATE_COMMUNICATION_ROUTE: synchronized (mSetModeLock) { synchronized (mDeviceStateLock) { @@ -1274,6 +1352,23 @@ import java.util.concurrent.atomic.AtomicBoolean; } } break; + + case MSG_L_COMMUNICATION_ROUTE_CLIENT_DIED: + synchronized (mSetModeLock) { + synchronized (mDeviceStateLock) { + onCommunicationRouteClientDied((CommunicationRouteClient) msg.obj); + } + } + break; + + case MSG_I_SCO_AUDIO_STATE_CHANGED: + synchronized (mSetModeLock) { + synchronized (mDeviceStateLock) { + mBtHelper.onScoAudioStateChanged(msg.arg1); + } + } + break; + case MSG_TOGGLE_HDMI: synchronized (mDeviceStateLock) { mDeviceInventory.onToggleHdmi(); @@ -1427,6 +1522,9 @@ import java.util.concurrent.atomic.AtomicBoolean; private static final int MSG_L_UPDATE_COMMUNICATION_ROUTE = 39; private static final int MSG_IL_SET_PREF_DEVICES_FOR_STRATEGY = 40; private static final int MSG_I_REMOVE_PREF_DEVICES_FOR_STRATEGY = 41; + private static final int MSG_L_SET_COMMUNICATION_ROUTE_FOR_CLIENT = 42; + private static final int MSG_L_UPDATE_COMMUNICATION_ROUTE_CLIENT = 43; + private static final int MSG_I_SCO_AUDIO_STATE_CHANGED = 44; private static final int MSG_L_BT_ACTIVE_DEVICE_CHANGE_EXT = 45; // @@ -1645,9 +1743,8 @@ import java.util.concurrent.atomic.AtomicBoolean; return; } Log.w(TAG, "Communication client died"); - setCommunicationRouteForClient( - client.getBinder(), client.getPid(), null, BtHelper.SCO_MODE_UNDEFINED, - "onCommunicationRouteClientDied"); + removeCommunicationRouteClient(client.getBinder(), true); + onUpdateCommunicationRouteClient("onCommunicationRouteClientDied"); } /** @@ -1701,11 +1798,31 @@ import java.util.concurrent.atomic.AtomicBoolean; AudioSystem.setParameters("BT_SCO=on"); } if (preferredCommunicationDevice == null) { - postRemovePreferredDevicesForStrategy(mCommunicationStrategyId); + removePreferredDevicesForStrategySync(mCommunicationStrategyId); } else { - postSetPreferredDevicesForStrategy( + setPreferredDevicesForStrategySync( mCommunicationStrategyId, Arrays.asList(preferredCommunicationDevice)); } + onUpdatePhoneStrategyDevice(preferredCommunicationDevice); + } + + /** + * Select new communication device from communication route client at the top of the stack + * and restore communication route including restarting SCO audio if needed. + */ + // @GuardedBy("mSetModeLock") + @GuardedBy("mDeviceStateLock") + private void onUpdateCommunicationRouteClient(String eventSource) { + onUpdateCommunicationRoute(eventSource); + CommunicationRouteClient crc = topCommunicationRouteClient(); + if (AudioService.DEBUG_COMM_RTE) { + Log.v(TAG, "onUpdateCommunicationRouteClient, crc: " + + crc + " eventSource: " + eventSource); + } + if (crc != null) { + setCommunicationRouteForClient(crc.getBinder(), crc.getPid(), crc.getDevice(), + BtHelper.SCO_MODE_UNDEFINED, eventSource); + } } private void onUpdatePhoneStrategyDevice(AudioDeviceAttributes device) { diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java index 4485c5b6d61a..7d9173d0561e 100644 --- a/services/core/java/com/android/server/audio/BtHelper.java +++ b/services/core/java/com/android/server/audio/BtHelper.java @@ -103,7 +103,7 @@ public class BtHelper { // SCO audio mode is virtual voice call (BluetoothHeadset.startScoUsingVirtualVoiceCall()) /*package*/ static final int SCO_MODE_VIRTUAL_CALL = 0; // SCO audio mode is Voice Recognition (BluetoothHeadset.startVoiceRecognition()) - private static final int SCO_MODE_VR = 2; + private static final int SCO_MODE_VR = 2; // max valid SCO audio mode values private static final int SCO_MODE_MAX = 2; @@ -304,68 +304,76 @@ public class BtHelper { BluetoothDevice btDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); setBtScoActiveDevice(btDevice); } else if (action.equals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)) { - boolean broadcast = false; - int scoAudioState = AudioManager.SCO_AUDIO_STATE_ERROR; int btState = intent.getIntExtra(BluetoothProfile.EXTRA_STATE, -1); - Log.i(TAG, "receiveBtEvent ACTION_AUDIO_STATE_CHANGED: " + btState); - switch (btState) { - case BluetoothHeadset.STATE_AUDIO_CONNECTED: - scoAudioState = AudioManager.SCO_AUDIO_STATE_CONNECTED; - if (mScoAudioState != SCO_STATE_ACTIVE_INTERNAL - && mScoAudioState != SCO_STATE_DEACTIVATE_REQ) { - mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL; - } else if (mDeviceBroker.isBluetoothScoRequested()) { - // broadcast intent if the connection was initated by AudioService - broadcast = true; - } - mDeviceBroker.setBluetoothScoOn(true, "BtHelper.receiveBtEvent"); - break; - case BluetoothHeadset.STATE_AUDIO_DISCONNECTED: - mDeviceBroker.setBluetoothScoOn(false, "BtHelper.receiveBtEvent"); - scoAudioState = AudioManager.SCO_AUDIO_STATE_DISCONNECTED; - // There are two cases where we want to immediately reconnect audio: - // 1) If a new start request was received while disconnecting: this was - // notified by requestScoState() setting state to SCO_STATE_ACTIVATE_REQ. - // 2) If audio was connected then disconnected via Bluetooth APIs and - // we still have pending activation requests by apps: this is indicated by - // state SCO_STATE_ACTIVE_EXTERNAL and BT SCO is requested. - if (mScoAudioState == SCO_STATE_ACTIVATE_REQ - || (mScoAudioState == SCO_STATE_ACTIVE_EXTERNAL - && mDeviceBroker.isBluetoothScoRequested())) { - if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null - && connectBluetoothScoAudioHelper(mBluetoothHeadset, - mBluetoothHeadsetDevice, mScoAudioMode)) { - mScoAudioState = SCO_STATE_ACTIVE_INTERNAL; - scoAudioState = AudioManager.SCO_AUDIO_STATE_CONNECTING; - broadcast = true; - break; - } - } - if (mScoAudioState != SCO_STATE_ACTIVE_EXTERNAL) { + Log.i(TAG,"receiveBtEvent ACTION_AUDIO_STATE_CHANGED: "+btState); + mDeviceBroker.postScoAudioStateChanged(btState); + } + } + + /** + * Exclusively called from AudioDeviceBroker when handling MSG_I_SCO_AUDIO_STATE_CHANGED + * as part of the serialization of the communication route selection + */ + // @GuardedBy("AudioDeviceBroker.mSetModeLock") + @GuardedBy("AudioDeviceBroker.mDeviceStateLock") + void onScoAudioStateChanged(int state) { + boolean broadcast = false; + int scoAudioState = AudioManager.SCO_AUDIO_STATE_ERROR; + switch (state) { + case BluetoothHeadset.STATE_AUDIO_CONNECTED: + scoAudioState = AudioManager.SCO_AUDIO_STATE_CONNECTED; + if (mScoAudioState != SCO_STATE_ACTIVE_INTERNAL + && mScoAudioState != SCO_STATE_DEACTIVATE_REQ) { + mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL; + } else if (mDeviceBroker.isBluetoothScoRequested()) { + // broadcast intent if the connection was initated by AudioService + broadcast = true; + } + mDeviceBroker.setBluetoothScoOn(true, "BtHelper.receiveBtEvent"); + break; + case BluetoothHeadset.STATE_AUDIO_DISCONNECTED: + mDeviceBroker.setBluetoothScoOn(false, "BtHelper.receiveBtEvent"); + scoAudioState = AudioManager.SCO_AUDIO_STATE_DISCONNECTED; + // There are two cases where we want to immediately reconnect audio: + // 1) If a new start request was received while disconnecting: this was + // notified by requestScoState() setting state to SCO_STATE_ACTIVATE_REQ. + // 2) If audio was connected then disconnected via Bluetooth APIs and + // we still have pending activation requests by apps: this is indicated by + // state SCO_STATE_ACTIVE_EXTERNAL and BT SCO is requested. + if (mScoAudioState == SCO_STATE_ACTIVATE_REQ) { + if (mBluetoothHeadset != null && mBluetoothHeadsetDevice != null + && connectBluetoothScoAudioHelper(mBluetoothHeadset, + mBluetoothHeadsetDevice, mScoAudioMode)) { + mScoAudioState = SCO_STATE_ACTIVE_INTERNAL; + scoAudioState = AudioManager.SCO_AUDIO_STATE_CONNECTING; broadcast = true; + break; } - mScoAudioState = SCO_STATE_INACTIVE; - break; - case BluetoothHeadset.STATE_AUDIO_CONNECTING: - if (mScoAudioState != SCO_STATE_ACTIVE_INTERNAL - && mScoAudioState != SCO_STATE_DEACTIVATE_REQ) { - mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL; - } - break; - default: - break; - } - if (broadcast) { - broadcastScoConnectionState(scoAudioState); - //FIXME: this is to maintain compatibility with deprecated intent - // AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED. Remove when appropriate. - Intent newIntent = new Intent(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED); - newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, scoAudioState); - sendStickyBroadcastToAll(newIntent); - } + } + if (mScoAudioState != SCO_STATE_ACTIVE_EXTERNAL) { + broadcast = true; + } + mScoAudioState = SCO_STATE_INACTIVE; + break; + case BluetoothHeadset.STATE_AUDIO_CONNECTING: + if (mScoAudioState != SCO_STATE_ACTIVE_INTERNAL + && mScoAudioState != SCO_STATE_DEACTIVATE_REQ) { + mScoAudioState = SCO_STATE_ACTIVE_EXTERNAL; + } + break; + default: + break; + } + if(broadcast) { + broadcastScoConnectionState(scoAudioState); + //FIXME: this is to maintain compatibility with deprecated intent + // AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED. Remove when appropriate. + Intent newIntent = new Intent(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED); + newIntent.putExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, scoAudioState); + sendStickyBroadcastToAll(newIntent); } - } + } /** * * @return false if SCO isn't connected @@ -744,6 +752,15 @@ public class BtHelper { case SCO_STATE_ACTIVE_INTERNAL: Log.w(TAG, "requestScoState: already in ACTIVE mode, simply return"); break; + case SCO_STATE_ACTIVE_EXTERNAL: + /* Confirm SCO Audio connection to requesting app as it is already connected + * externally (i.e. through SCO APIs by Telecom service). + * Once SCO Audio is disconnected by the external owner, we will reconnect it + * automatically on behalf of the requesting app and the state will move to + * SCO_STATE_ACTIVE_INTERNAL. + */ + broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_CONNECTED); + break; default: Log.w(TAG, "requestScoState: failed to connect in state " + mScoAudioState + ", scoAudioMode=" + scoAudioMode); diff --git a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java index 55d0728d803e..47c73822ed46 100644 --- a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java +++ b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java @@ -225,6 +225,9 @@ public final class PlaybackActivityMonitor AudioAttributes.FLAG_BYPASS_MUTE; private void checkVolumeForPrivilegedAlarm(AudioPlaybackConfiguration apc, int event) { + if (event == AudioPlaybackConfiguration.PLAYER_UPDATE_DEVICE_ID) { + return; + } if (event == AudioPlaybackConfiguration.PLAYER_STATE_STARTED || apc.getPlayerState() == AudioPlaybackConfiguration.PLAYER_STATE_STARTED) { if ((apc.getAudioAttributes().getAllFlags() & FLAGS_FOR_SILENCE_OVERRIDE) diff --git a/services/core/java/com/android/server/audio/SpatializerHelper.java b/services/core/java/com/android/server/audio/SpatializerHelper.java index b47ea4f7a4b8..d4dc288fbece 100644 --- a/services/core/java/com/android/server/audio/SpatializerHelper.java +++ b/services/core/java/com/android/server/audio/SpatializerHelper.java @@ -90,6 +90,7 @@ public class SpatializerHelper { private @Nullable SpatializerCallback mSpatCallback; private @Nullable SpatializerHeadTrackingCallback mSpatHeadTrackingCallback; private @Nullable HelperDynamicSensorCallback mDynSensorCallback; + private boolean mIsHeadTrackingSupported = false; // default attributes and format that determine basic availability of spatialization private static final AudioAttributes DEFAULT_ATTRIBUTES = new AudioAttributes.Builder() @@ -176,6 +177,7 @@ public class SpatializerHelper { */ synchronized void reset(boolean featureEnabled) { Log.i(TAG, "Resetting"); + releaseSpat(); mState = STATE_UNINITIALIZED; mSpatLevel = Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_NONE; mCapableSpatLevel = Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_NONE; @@ -496,8 +498,9 @@ public class SpatializerHelper { mSpat = AudioSystem.getSpatializer(mSpatCallback); try { mSpat.setLevel((byte) Spatializer.SPATIALIZER_IMMERSIVE_LEVEL_MULTICHANNEL); + mIsHeadTrackingSupported = mSpat.isHeadTrackingSupported(); //TODO: register heatracking callback only when sensors are registered - if (mSpat.isHeadTrackingSupported()) { + if (mIsHeadTrackingSupported) { mSpat.registerHeadTrackingCallback(mSpatHeadTrackingCallback); } } catch (RemoteException e) { @@ -515,12 +518,15 @@ public class SpatializerHelper { if (mSpat != null) { mSpatCallback = null; try { - mSpat.registerHeadTrackingCallback(null); + if (mIsHeadTrackingSupported) { + mSpat.registerHeadTrackingCallback(null); + } mSpat.release(); - mSpat = null; } catch (RemoteException e) { Log.e(TAG, "Can't set release spatializer cleanly", e); } + mIsHeadTrackingSupported = false; + mSpat = null; } } @@ -686,7 +692,6 @@ public class SpatializerHelper { mDesiredHeadTrackingMode = mode; dispatchDesiredHeadTrackingMode(mode); } - } catch (RemoteException e) { Log.e(TAG, "Error calling setDesiredHeadTrackingMode", e); } @@ -707,7 +712,7 @@ public class SpatializerHelper { } break; } - return true; + return mIsHeadTrackingSupported; } private void dispatchActualHeadTrackingMode(int newMode) { @@ -881,13 +886,8 @@ public class SpatializerHelper { Log.e(TAG, "not " + action + " sensors, null spatializer"); return; } - try { - if (!mSpat.isHeadTrackingSupported()) { - Log.e(TAG, "not " + action + " sensors, spatializer doesn't support headtracking"); - return; - } - } catch (RemoteException e) { - Log.e(TAG, "not " + action + " sensors, error querying headtracking", e); + if (!mIsHeadTrackingSupported) { + Log.e(TAG, "not " + action + " sensors, spatializer doesn't support headtracking"); return; } int headHandle = -1; diff --git a/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java b/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java index b73e91173a43..26bbb403f39f 100644 --- a/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java +++ b/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java @@ -16,6 +16,8 @@ package com.android.server.biometrics.sensors; +import static com.android.internal.annotations.VisibleForTesting.Visibility; + import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; @@ -48,7 +50,6 @@ public abstract class BaseClientMonitor extends LoggableMonitor * Interface that ClientMonitor holders should use to receive callbacks. */ public interface Callback { - /** * Invoked when the ClientMonitor operation has been started (e.g. reached the head of * the queue and becomes the current operation). @@ -203,7 +204,8 @@ public abstract class BaseClientMonitor extends LoggableMonitor } /** Signals this operation has completed its lifecycle and should no longer be used. */ - void destroy() { + @VisibleForTesting(visibility = Visibility.PACKAGE) + public void destroy() { mAlreadyDone = true; if (mToken != null) { try { diff --git a/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java b/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java index a358bc2bad55..39c5944d65c7 100644 --- a/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java +++ b/services/core/java/com/android/server/biometrics/sensors/BiometricScheduler.java @@ -17,10 +17,10 @@ package com.android.server.biometrics.sensors; import android.annotation.IntDef; +import android.annotation.MainThread; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; -import android.hardware.biometrics.BiometricConstants; import android.hardware.biometrics.IBiometricService; import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; import android.os.Handler; @@ -55,6 +55,7 @@ import java.util.Locale; * We currently assume (and require) that each biometric sensor have its own instance of a * {@link BiometricScheduler}. See {@link CoexCoordinator}. */ +@MainThread public class BiometricScheduler { private static final String BASE_TAG = "BiometricScheduler"; @@ -110,123 +111,6 @@ public class BiometricScheduler { } } - /** - * Contains all the necessary information for a HAL operation. - */ - @VisibleForTesting - static final class Operation { - - /** - * The operation is added to the list of pending operations and waiting for its turn. - */ - static final int STATE_WAITING_IN_QUEUE = 0; - - /** - * The operation is added to the list of pending operations, but a subsequent operation - * has been added. This state only applies to {@link Interruptable} operations. When this - * operation reaches the head of the queue, it will send ERROR_CANCELED and finish. - */ - static final int STATE_WAITING_IN_QUEUE_CANCELING = 1; - - /** - * The operation has reached the front of the queue and has started. - */ - static final int STATE_STARTED = 2; - - /** - * The operation was started, but is now canceling. Operations should wait for the HAL to - * acknowledge that the operation was canceled, at which point it finishes. - */ - static final int STATE_STARTED_CANCELING = 3; - - /** - * The operation has reached the head of the queue but is waiting for BiometricService - * to acknowledge and start the operation. - */ - static final int STATE_WAITING_FOR_COOKIE = 4; - - /** - * The {@link BaseClientMonitor.Callback} has been invoked and the client is finished. - */ - static final int STATE_FINISHED = 5; - - @IntDef({STATE_WAITING_IN_QUEUE, - STATE_WAITING_IN_QUEUE_CANCELING, - STATE_STARTED, - STATE_STARTED_CANCELING, - STATE_WAITING_FOR_COOKIE, - STATE_FINISHED}) - @Retention(RetentionPolicy.SOURCE) - @interface OperationState {} - - @NonNull final BaseClientMonitor mClientMonitor; - @Nullable final BaseClientMonitor.Callback mClientCallback; - @OperationState int mState; - - Operation( - @NonNull BaseClientMonitor clientMonitor, - @Nullable BaseClientMonitor.Callback callback - ) { - this(clientMonitor, callback, STATE_WAITING_IN_QUEUE); - } - - protected Operation( - @NonNull BaseClientMonitor clientMonitor, - @Nullable BaseClientMonitor.Callback callback, - @OperationState int state - ) { - mClientMonitor = clientMonitor; - mClientCallback = callback; - mState = state; - } - - public boolean isHalOperation() { - return mClientMonitor instanceof HalClientMonitor<?>; - } - - /** - * @return true if the operation requires the HAL, and the HAL is null. - */ - public boolean isUnstartableHalOperation() { - if (isHalOperation()) { - final HalClientMonitor<?> client = (HalClientMonitor<?>) mClientMonitor; - if (client.getFreshDaemon() == null) { - return true; - } - } - return false; - } - - @Override - public String toString() { - return mClientMonitor + ", State: " + mState; - } - } - - /** - * Monitors an operation's cancellation. If cancellation takes too long, the watchdog will - * kill the current operation and forcibly start the next. - */ - private static final class CancellationWatchdog implements Runnable { - static final int DELAY_MS = 3000; - - final String tag; - final Operation operation; - CancellationWatchdog(String tag, Operation operation) { - this.tag = tag; - this.operation = operation; - } - - @Override - public void run() { - if (operation.mState != Operation.STATE_FINISHED) { - Slog.e(tag, "[Watchdog Triggered]: " + operation); - operation.mClientMonitor.mCallback - .onClientFinished(operation.mClientMonitor, false /* success */); - } - } - } - private static final class CrashState { static final int NUM_ENTRIES = 10; final String timestamp; @@ -263,10 +147,9 @@ public class BiometricScheduler { private final @SensorType int mSensorType; @Nullable private final GestureAvailabilityDispatcher mGestureAvailabilityDispatcher; @NonNull private final IBiometricService mBiometricService; - @NonNull protected final Handler mHandler = new Handler(Looper.getMainLooper()); - @NonNull private final InternalCallback mInternalCallback; - @VisibleForTesting @NonNull final Deque<Operation> mPendingOperations; - @VisibleForTesting @Nullable Operation mCurrentOperation; + @NonNull protected final Handler mHandler; + @VisibleForTesting @NonNull final Deque<BiometricSchedulerOperation> mPendingOperations; + @VisibleForTesting @Nullable BiometricSchedulerOperation mCurrentOperation; @NonNull private final ArrayDeque<CrashState> mCrashStates; private int mTotalOperationsHandled; @@ -277,7 +160,7 @@ public class BiometricScheduler { // Internal callback, notified when an operation is complete. Notifies the requester // that the operation is complete, before performing internal scheduler work (such as // starting the next client). - public class InternalCallback implements BaseClientMonitor.Callback { + private final BaseClientMonitor.Callback mInternalCallback = new BaseClientMonitor.Callback() { @Override public void onClientStarted(@NonNull BaseClientMonitor clientMonitor) { Slog.d(getTag(), "[Started] " + clientMonitor); @@ -286,16 +169,11 @@ public class BiometricScheduler { mCoexCoordinator.addAuthenticationClient(mSensorType, (AuthenticationClient<?>) clientMonitor); } - - if (mCurrentOperation.mClientCallback != null) { - mCurrentOperation.mClientCallback.onClientStarted(clientMonitor); - } } @Override public void onClientFinished(@NonNull BaseClientMonitor clientMonitor, boolean success) { mHandler.post(() -> { - clientMonitor.destroy(); if (mCurrentOperation == null) { Slog.e(getTag(), "[Finishing] " + clientMonitor + " but current operation is null, success: " + success @@ -303,9 +181,9 @@ public class BiometricScheduler { return; } - if (clientMonitor != mCurrentOperation.mClientMonitor) { + if (!mCurrentOperation.isFor(clientMonitor)) { Slog.e(getTag(), "[Ignoring Finish] " + clientMonitor + " does not match" - + " current: " + mCurrentOperation.mClientMonitor); + + " current: " + mCurrentOperation); return; } @@ -315,36 +193,33 @@ public class BiometricScheduler { (AuthenticationClient<?>) clientMonitor); } - mCurrentOperation.mState = Operation.STATE_FINISHED; - - if (mCurrentOperation.mClientCallback != null) { - mCurrentOperation.mClientCallback.onClientFinished(clientMonitor, success); - } - if (mGestureAvailabilityDispatcher != null) { mGestureAvailabilityDispatcher.markSensorActive( - mCurrentOperation.mClientMonitor.getSensorId(), false /* active */); + mCurrentOperation.getSensorId(), false /* active */); } if (mRecentOperations.size() >= mRecentOperationsLimit) { mRecentOperations.remove(0); } - mRecentOperations.add(mCurrentOperation.mClientMonitor.getProtoEnum()); + mRecentOperations.add(mCurrentOperation.getProtoEnum()); mCurrentOperation = null; mTotalOperationsHandled++; startNextOperationIfIdle(); }); } - } + }; @VisibleForTesting - BiometricScheduler(@NonNull String tag, @SensorType int sensorType, + BiometricScheduler(@NonNull String tag, + @NonNull Handler handler, + @SensorType int sensorType, @Nullable GestureAvailabilityDispatcher gestureAvailabilityDispatcher, - @NonNull IBiometricService biometricService, int recentOperationsLimit, + @NonNull IBiometricService biometricService, + int recentOperationsLimit, @NonNull CoexCoordinator coexCoordinator) { mBiometricTag = tag; + mHandler = handler; mSensorType = sensorType; - mInternalCallback = new InternalCallback(); mGestureAvailabilityDispatcher = gestureAvailabilityDispatcher; mPendingOperations = new ArrayDeque<>(); mBiometricService = biometricService; @@ -356,6 +231,7 @@ public class BiometricScheduler { /** * Creates a new scheduler. + * * @param tag for the specific instance of the scheduler. Should be unique. * @param sensorType the sensorType that this scheduler is handling. * @param gestureAvailabilityDispatcher may be null if the sensor does not support gestures @@ -364,16 +240,14 @@ public class BiometricScheduler { public BiometricScheduler(@NonNull String tag, @SensorType int sensorType, @Nullable GestureAvailabilityDispatcher gestureAvailabilityDispatcher) { - this(tag, sensorType, gestureAvailabilityDispatcher, IBiometricService.Stub.asInterface( - ServiceManager.getService(Context.BIOMETRIC_SERVICE)), LOG_NUM_RECENT_OPERATIONS, - CoexCoordinator.getInstance()); + this(tag, new Handler(Looper.getMainLooper()), sensorType, gestureAvailabilityDispatcher, + IBiometricService.Stub.asInterface( + ServiceManager.getService(Context.BIOMETRIC_SERVICE)), + LOG_NUM_RECENT_OPERATIONS, CoexCoordinator.getInstance()); } - /** - * @return A reference to the internal callback that should be invoked whenever the scheduler - * needs to (e.g. client started, client finished). - */ - @NonNull protected InternalCallback getInternalCallback() { + @VisibleForTesting + public BaseClientMonitor.Callback getInternalCallback() { return mInternalCallback; } @@ -392,72 +266,46 @@ public class BiometricScheduler { } mCurrentOperation = mPendingOperations.poll(); - final BaseClientMonitor currentClient = mCurrentOperation.mClientMonitor; Slog.d(getTag(), "[Polled] " + mCurrentOperation); // If the operation at the front of the queue has been marked for cancellation, send // ERROR_CANCELED. No need to start this client. - if (mCurrentOperation.mState == Operation.STATE_WAITING_IN_QUEUE_CANCELING) { + if (mCurrentOperation.isMarkedCanceling()) { Slog.d(getTag(), "[Now Cancelling] " + mCurrentOperation); - if (!(currentClient instanceof Interruptable)) { - throw new IllegalStateException("Mis-implemented client or scheduler, " - + "trying to cancel non-interruptable operation: " + mCurrentOperation); - } - - final Interruptable interruptable = (Interruptable) currentClient; - interruptable.cancelWithoutStarting(getInternalCallback()); + mCurrentOperation.cancel(mHandler, mInternalCallback); // Now we wait for the client to send its FinishCallback, which kicks off the next // operation. return; } - if (mGestureAvailabilityDispatcher != null - && mCurrentOperation.mClientMonitor instanceof AcquisitionClient) { + if (mGestureAvailabilityDispatcher != null && mCurrentOperation.isAcquisitionOperation()) { mGestureAvailabilityDispatcher.markSensorActive( - mCurrentOperation.mClientMonitor.getSensorId(), - true /* active */); + mCurrentOperation.getSensorId(), true /* active */); } // Not all operations start immediately. BiometricPrompt waits for its operation // to arrive at the head of the queue, before pinging it to start. - final boolean shouldStartNow = currentClient.getCookie() == 0; - if (shouldStartNow) { - if (mCurrentOperation.isUnstartableHalOperation()) { - final HalClientMonitor<?> halClientMonitor = - (HalClientMonitor<?>) mCurrentOperation.mClientMonitor; + final int cookie = mCurrentOperation.isReadyToStart(); + if (cookie == 0) { + if (!mCurrentOperation.start(mInternalCallback)) { // Note down current length of queue final int pendingOperationsLength = mPendingOperations.size(); - final Operation lastOperation = mPendingOperations.peekLast(); + final BiometricSchedulerOperation lastOperation = mPendingOperations.peekLast(); Slog.e(getTag(), "[Unable To Start] " + mCurrentOperation + ". Last pending operation: " + lastOperation); - // For current operations, 1) unableToStart, which notifies the caller-side, then - // 2) notify operation's callback, to notify applicable system service that the - // operation failed. - halClientMonitor.unableToStart(); - if (mCurrentOperation.mClientCallback != null) { - mCurrentOperation.mClientCallback.onClientFinished( - mCurrentOperation.mClientMonitor, false /* success */); - } - // Then for each operation currently in the pending queue at the time of this // failure, do the same as above. Otherwise, it's possible that something like // setActiveUser fails, but then authenticate (for the wrong user) is invoked. for (int i = 0; i < pendingOperationsLength; i++) { - final Operation operation = mPendingOperations.pollFirst(); - if (operation == null) { + final BiometricSchedulerOperation operation = mPendingOperations.pollFirst(); + if (operation != null) { + Slog.w(getTag(), "[Aborting Operation] " + operation); + operation.abort(); + } else { Slog.e(getTag(), "Null operation, index: " + i + ", expected length: " + pendingOperationsLength); - break; - } - if (operation.isHalOperation()) { - ((HalClientMonitor<?>) operation.mClientMonitor).unableToStart(); - } - if (operation.mClientCallback != null) { - operation.mClientCallback.onClientFinished(operation.mClientMonitor, - false /* success */); } - Slog.w(getTag(), "[Aborted Operation] " + operation); } // It's possible that during cleanup a new set of operations came in. We can try to @@ -465,25 +313,20 @@ public class BiometricScheduler { // actually be multiple operations (i.e. updateActiveUser + authenticate). mCurrentOperation = null; startNextOperationIfIdle(); - } else { - Slog.d(getTag(), "[Starting] " + mCurrentOperation); - currentClient.start(getInternalCallback()); - mCurrentOperation.mState = Operation.STATE_STARTED; } } else { try { - mBiometricService.onReadyForAuthentication(currentClient.getCookie()); + mBiometricService.onReadyForAuthentication(cookie); } catch (RemoteException e) { Slog.e(getTag(), "Remote exception when contacting BiometricService", e); } Slog.d(getTag(), "Waiting for cookie before starting: " + mCurrentOperation); - mCurrentOperation.mState = Operation.STATE_WAITING_FOR_COOKIE; } } /** * Starts the {@link #mCurrentOperation} if - * 1) its state is {@link Operation#STATE_WAITING_FOR_COOKIE} and + * 1) its state is {@link BiometricSchedulerOperation#STATE_WAITING_FOR_COOKIE} and * 2) its cookie matches this cookie * * This is currently only used by {@link com.android.server.biometrics.BiometricService}, which @@ -499,45 +342,13 @@ public class BiometricScheduler { Slog.e(getTag(), "Current operation is null"); return; } - if (mCurrentOperation.mState != Operation.STATE_WAITING_FOR_COOKIE) { - if (mCurrentOperation.mState == Operation.STATE_WAITING_IN_QUEUE_CANCELING) { - Slog.d(getTag(), "Operation was marked for cancellation, cancelling now: " - + mCurrentOperation); - // This should trigger the internal onClientFinished callback, which clears the - // operation and starts the next one. - final ErrorConsumer errorConsumer = - (ErrorConsumer) mCurrentOperation.mClientMonitor; - errorConsumer.onError(BiometricConstants.BIOMETRIC_ERROR_CANCELED, - 0 /* vendorCode */); - return; - } else { - Slog.e(getTag(), "Operation is in the wrong state: " + mCurrentOperation - + ", expected STATE_WAITING_FOR_COOKIE"); - return; - } - } - if (mCurrentOperation.mClientMonitor.getCookie() != cookie) { - Slog.e(getTag(), "Mismatched cookie for operation: " + mCurrentOperation - + ", received: " + cookie); - return; - } - if (mCurrentOperation.isUnstartableHalOperation()) { + if (mCurrentOperation.startWithCookie(mInternalCallback, cookie)) { + Slog.d(getTag(), "[Started] Prepared client: " + mCurrentOperation); + } else { Slog.e(getTag(), "[Unable To Start] Prepared client: " + mCurrentOperation); - // This is BiometricPrompt trying to auth but something's wrong with the HAL. - final HalClientMonitor<?> halClientMonitor = - (HalClientMonitor<?>) mCurrentOperation.mClientMonitor; - halClientMonitor.unableToStart(); - if (mCurrentOperation.mClientCallback != null) { - mCurrentOperation.mClientCallback.onClientFinished(mCurrentOperation.mClientMonitor, - false /* success */); - } mCurrentOperation = null; startNextOperationIfIdle(); - } else { - Slog.d(getTag(), "[Starting] Prepared client: " + mCurrentOperation); - mCurrentOperation.mState = Operation.STATE_STARTED; - mCurrentOperation.mClientMonitor.start(getInternalCallback()); } } @@ -562,17 +373,14 @@ public class BiometricScheduler { // pending clients as canceling. Once they reach the head of the queue, the scheduler will // send ERROR_CANCELED and skip the operation. if (clientMonitor.interruptsPrecedingClients()) { - for (Operation operation : mPendingOperations) { - if (operation.mClientMonitor instanceof Interruptable - && operation.mState != Operation.STATE_WAITING_IN_QUEUE_CANCELING) { - Slog.d(getTag(), "New client incoming, marking pending client as canceling: " - + operation.mClientMonitor); - operation.mState = Operation.STATE_WAITING_IN_QUEUE_CANCELING; + for (BiometricSchedulerOperation operation : mPendingOperations) { + if (operation.markCanceling()) { + Slog.d(getTag(), "New client, marking pending op as canceling: " + operation); } } } - mPendingOperations.add(new Operation(clientMonitor, clientCallback)); + mPendingOperations.add(new BiometricSchedulerOperation(clientMonitor, clientCallback)); Slog.d(getTag(), "[Added] " + clientMonitor + ", new queue size: " + mPendingOperations.size()); @@ -580,67 +388,34 @@ public class BiometricScheduler { // cancellable, start the cancellation process. if (clientMonitor.interruptsPrecedingClients() && mCurrentOperation != null - && mCurrentOperation.mClientMonitor instanceof Interruptable - && mCurrentOperation.mState == Operation.STATE_STARTED) { + && mCurrentOperation.isInterruptable() + && mCurrentOperation.isStarted()) { Slog.d(getTag(), "[Cancelling Interruptable]: " + mCurrentOperation); - cancelInternal(mCurrentOperation); - } - - startNextOperationIfIdle(); - } - - private void cancelInternal(Operation operation) { - if (operation != mCurrentOperation) { - Slog.e(getTag(), "cancelInternal invoked on non-current operation: " + operation); - return; - } - if (!(operation.mClientMonitor instanceof Interruptable)) { - Slog.w(getTag(), "Operation not interruptable: " + operation); - return; - } - if (operation.mState == Operation.STATE_STARTED_CANCELING) { - Slog.w(getTag(), "Cancel already invoked for operation: " + operation); - return; - } - if (operation.mState == Operation.STATE_WAITING_FOR_COOKIE) { - Slog.w(getTag(), "Skipping cancellation for non-started operation: " + operation); - // We can set it to null immediately, since the HAL was never notified to start. - if (mCurrentOperation != null) { - mCurrentOperation.mClientMonitor.destroy(); - } - mCurrentOperation = null; + mCurrentOperation.cancel(mHandler, mInternalCallback); + } else { startNextOperationIfIdle(); - return; } - Slog.d(getTag(), "[Cancelling] Current client: " + operation.mClientMonitor); - final Interruptable interruptable = (Interruptable) operation.mClientMonitor; - interruptable.cancel(); - operation.mState = Operation.STATE_STARTED_CANCELING; - - // Add a watchdog. If the HAL does not acknowledge within the timeout, we will - // forcibly finish this client. - mHandler.postDelayed(new CancellationWatchdog(getTag(), operation), - CancellationWatchdog.DELAY_MS); } /** * Requests to cancel enrollment. * @param token from the caller, should match the token passed in when requesting enrollment */ - public void cancelEnrollment(IBinder token) { - if (mCurrentOperation == null) { - Slog.e(getTag(), "Unable to cancel enrollment, null operation"); - return; - } - final boolean isEnrolling = mCurrentOperation.mClientMonitor instanceof EnrollClient; - final boolean tokenMatches = mCurrentOperation.mClientMonitor.getToken() == token; - if (!isEnrolling || !tokenMatches) { - Slog.w(getTag(), "Not cancelling enrollment, isEnrolling: " + isEnrolling - + " tokenMatches: " + tokenMatches); - return; - } + public void cancelEnrollment(IBinder token, long requestId) { + Slog.d(getTag(), "cancelEnrollment, requestId: " + requestId); - cancelInternal(mCurrentOperation); + if (mCurrentOperation != null + && canCancelEnrollOperation(mCurrentOperation, token, requestId)) { + Slog.d(getTag(), "Cancelling enrollment op: " + mCurrentOperation); + mCurrentOperation.cancel(mHandler, mInternalCallback); + } else { + for (BiometricSchedulerOperation operation : mPendingOperations) { + if (canCancelEnrollOperation(operation, token, requestId)) { + Slog.d(getTag(), "Cancelling pending enrollment op: " + operation); + operation.markCanceling(); + } + } + } } /** @@ -649,62 +424,42 @@ public class BiometricScheduler { * @param requestId the id returned when requesting authentication */ public void cancelAuthenticationOrDetection(IBinder token, long requestId) { - Slog.d(getTag(), "cancelAuthenticationOrDetection, requestId: " + requestId - + " current: " + mCurrentOperation - + " stack size: " + mPendingOperations.size()); + Slog.d(getTag(), "cancelAuthenticationOrDetection, requestId: " + requestId); if (mCurrentOperation != null && canCancelAuthOperation(mCurrentOperation, token, requestId)) { - Slog.d(getTag(), "Cancelling: " + mCurrentOperation); - cancelInternal(mCurrentOperation); + Slog.d(getTag(), "Cancelling auth/detect op: " + mCurrentOperation); + mCurrentOperation.cancel(mHandler, mInternalCallback); } else { - // Look through the current queue for all authentication clients for the specified - // token, and mark them as STATE_WAITING_IN_QUEUE_CANCELING. Note that we're marking - // all of them, instead of just the first one, since the API surface currently doesn't - // allow us to distinguish between multiple authentication requests from the same - // process. However, this generally does not happen anyway, and would be a class of - // bugs on its own. - for (Operation operation : mPendingOperations) { + for (BiometricSchedulerOperation operation : mPendingOperations) { if (canCancelAuthOperation(operation, token, requestId)) { - Slog.d(getTag(), "Marking " + operation - + " as STATE_WAITING_IN_QUEUE_CANCELING"); - operation.mState = Operation.STATE_WAITING_IN_QUEUE_CANCELING; + Slog.d(getTag(), "Cancelling pending auth/detect op: " + operation); + operation.markCanceling(); } } } } - private static boolean canCancelAuthOperation(Operation operation, IBinder token, - long requestId) { - // TODO: restrict callers that can cancel without requestId (negative value)? - return isAuthenticationOrDetectionOperation(operation) - && operation.mClientMonitor.getToken() == token - && isMatchingRequestId(operation, requestId); - } - - // By default, monitors are not associated with a request id to retain the original - // behavior (i.e. if no requestId is explicitly set then assume it matches) - private static boolean isMatchingRequestId(Operation operation, long requestId) { - return !operation.mClientMonitor.hasRequestId() - || operation.mClientMonitor.getRequestId() == requestId; + private static boolean canCancelEnrollOperation(BiometricSchedulerOperation operation, + IBinder token, long requestId) { + return operation.isEnrollOperation() + && operation.isMatchingToken(token) + && operation.isMatchingRequestId(requestId); } - private static boolean isAuthenticationOrDetectionOperation(@NonNull Operation operation) { - final boolean isAuthentication = - operation.mClientMonitor instanceof AuthenticationConsumer; - final boolean isDetection = - operation.mClientMonitor instanceof DetectionConsumer; - return isAuthentication || isDetection; + private static boolean canCancelAuthOperation(BiometricSchedulerOperation operation, + IBinder token, long requestId) { + // TODO: restrict callers that can cancel without requestId (negative value)? + return operation.isAuthenticationOrDetectionOperation() + && operation.isMatchingToken(token) + && operation.isMatchingRequestId(requestId); } /** * @return the current operation */ public BaseClientMonitor getCurrentClient() { - if (mCurrentOperation == null) { - return null; - } - return mCurrentOperation.mClientMonitor; + return mCurrentOperation != null ? mCurrentOperation.getClientMonitor() : null; } public int getCurrentPendingCount() { @@ -719,7 +474,7 @@ public class BiometricScheduler { new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS", Locale.US); final String timestamp = dateFormat.format(new Date(System.currentTimeMillis())); final List<String> pendingOperations = new ArrayList<>(); - for (Operation operation : mPendingOperations) { + for (BiometricSchedulerOperation operation : mPendingOperations) { pendingOperations.add(operation.toString()); } @@ -735,7 +490,7 @@ public class BiometricScheduler { pw.println("Type: " + mSensorType); pw.println("Current operation: " + mCurrentOperation); pw.println("Pending operations: " + mPendingOperations.size()); - for (Operation operation : mPendingOperations) { + for (BiometricSchedulerOperation operation : mPendingOperations) { pw.println("Pending operation: " + operation); } for (CrashState crashState : mCrashStates) { @@ -746,7 +501,7 @@ public class BiometricScheduler { public byte[] dumpProtoState(boolean clearSchedulerBuffer) { final ProtoOutputStream proto = new ProtoOutputStream(); proto.write(BiometricSchedulerProto.CURRENT_OPERATION, mCurrentOperation != null - ? mCurrentOperation.mClientMonitor.getProtoEnum() : BiometricsProto.CM_NONE); + ? mCurrentOperation.getProtoEnum() : BiometricsProto.CM_NONE); proto.write(BiometricSchedulerProto.TOTAL_OPERATIONS, mTotalOperationsHandled); if (!mRecentOperations.isEmpty()) { @@ -771,6 +526,7 @@ public class BiometricScheduler { * HAL dies. */ public void reset() { + Slog.d(getTag(), "Resetting scheduler"); mPendingOperations.clear(); mCurrentOperation = null; } diff --git a/services/core/java/com/android/server/biometrics/sensors/BiometricSchedulerOperation.java b/services/core/java/com/android/server/biometrics/sensors/BiometricSchedulerOperation.java new file mode 100644 index 000000000000..e8b50d90b586 --- /dev/null +++ b/services/core/java/com/android/server/biometrics/sensors/BiometricSchedulerOperation.java @@ -0,0 +1,421 @@ +/* + * Copyright (C) 2021 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.server.biometrics.sensors; + +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.hardware.biometrics.BiometricConstants; +import android.os.Handler; +import android.os.IBinder; +import android.util.Slog; + +import com.android.internal.annotations.VisibleForTesting; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Contains all the necessary information for a HAL operation. + */ +public class BiometricSchedulerOperation { + protected static final String TAG = "BiometricSchedulerOperation"; + + /** + * The operation is added to the list of pending operations and waiting for its turn. + */ + protected static final int STATE_WAITING_IN_QUEUE = 0; + + /** + * The operation is added to the list of pending operations, but a subsequent operation + * has been added. This state only applies to {@link Interruptable} operations. When this + * operation reaches the head of the queue, it will send ERROR_CANCELED and finish. + */ + protected static final int STATE_WAITING_IN_QUEUE_CANCELING = 1; + + /** + * The operation has reached the front of the queue and has started. + */ + protected static final int STATE_STARTED = 2; + + /** + * The operation was started, but is now canceling. Operations should wait for the HAL to + * acknowledge that the operation was canceled, at which point it finishes. + */ + protected static final int STATE_STARTED_CANCELING = 3; + + /** + * The operation has reached the head of the queue but is waiting for BiometricService + * to acknowledge and start the operation. + */ + protected static final int STATE_WAITING_FOR_COOKIE = 4; + + /** + * The {@link BaseClientMonitor.Callback} has been invoked and the client is finished. + */ + protected static final int STATE_FINISHED = 5; + + @IntDef({STATE_WAITING_IN_QUEUE, + STATE_WAITING_IN_QUEUE_CANCELING, + STATE_STARTED, + STATE_STARTED_CANCELING, + STATE_WAITING_FOR_COOKIE, + STATE_FINISHED}) + @Retention(RetentionPolicy.SOURCE) + protected @interface OperationState {} + + private static final int CANCEL_WATCHDOG_DELAY_MS = 3000; + + @NonNull + private final BaseClientMonitor mClientMonitor; + @Nullable + private final BaseClientMonitor.Callback mClientCallback; + @OperationState + private int mState; + @VisibleForTesting + @NonNull + final Runnable mCancelWatchdog; + + BiometricSchedulerOperation( + @NonNull BaseClientMonitor clientMonitor, + @Nullable BaseClientMonitor.Callback callback + ) { + this(clientMonitor, callback, STATE_WAITING_IN_QUEUE); + } + + protected BiometricSchedulerOperation( + @NonNull BaseClientMonitor clientMonitor, + @Nullable BaseClientMonitor.Callback callback, + @OperationState int state + ) { + mClientMonitor = clientMonitor; + mClientCallback = callback; + mState = state; + mCancelWatchdog = () -> { + if (!isFinished()) { + Slog.e(TAG, "[Watchdog Triggered]: " + this); + getWrappedCallback().onClientFinished(mClientMonitor, false /* success */); + } + }; + } + + /** + * Zero if this operation is ready to start or has already started. A non-zero cookie + * is returned if the operation has not started and is waiting on + * {@link android.hardware.biometrics.IBiometricService#onReadyForAuthentication(int)}. + * + * @return cookie or 0 if ready/started + */ + public int isReadyToStart() { + if (mState == STATE_WAITING_FOR_COOKIE || mState == STATE_WAITING_IN_QUEUE) { + final int cookie = mClientMonitor.getCookie(); + if (cookie != 0) { + mState = STATE_WAITING_FOR_COOKIE; + } + return cookie; + } + + return 0; + } + + /** + * Start this operation without waiting for a cookie + * (i.e. {@link #isReadyToStart() returns zero} + * + * @param callback lifecycle callback + * @return if this operation started + */ + public boolean start(@NonNull BaseClientMonitor.Callback callback) { + checkInState("start", + STATE_WAITING_IN_QUEUE, + STATE_WAITING_FOR_COOKIE, + STATE_WAITING_IN_QUEUE_CANCELING); + + if (mClientMonitor.getCookie() != 0) { + throw new IllegalStateException("operation requires cookie"); + } + + return doStart(callback); + } + + /** + * Start this operation after receiving the given cookie. + * + * @param callback lifecycle callback + * @param cookie cookie indicting the operation should begin + * @return if this operation started + */ + public boolean startWithCookie(@NonNull BaseClientMonitor.Callback callback, int cookie) { + checkInState("start", + STATE_WAITING_IN_QUEUE, + STATE_WAITING_FOR_COOKIE, + STATE_WAITING_IN_QUEUE_CANCELING); + + if (mClientMonitor.getCookie() != cookie) { + Slog.e(TAG, "Mismatched cookie for operation: " + this + ", received: " + cookie); + return false; + } + + return doStart(callback); + } + + private boolean doStart(@NonNull BaseClientMonitor.Callback callback) { + final BaseClientMonitor.Callback cb = getWrappedCallback(callback); + + if (mState == STATE_WAITING_IN_QUEUE_CANCELING) { + Slog.d(TAG, "Operation marked for cancellation, cancelling now: " + this); + + cb.onClientFinished(mClientMonitor, true /* success */); + if (mClientMonitor instanceof ErrorConsumer) { + final ErrorConsumer errorConsumer = (ErrorConsumer) mClientMonitor; + errorConsumer.onError(BiometricConstants.BIOMETRIC_ERROR_CANCELED, + 0 /* vendorCode */); + } else { + Slog.w(TAG, "monitor cancelled but does not implement ErrorConsumer"); + } + + return false; + } + + if (isUnstartableHalOperation()) { + Slog.v(TAG, "unable to start: " + this); + ((HalClientMonitor<?>) mClientMonitor).unableToStart(); + cb.onClientFinished(mClientMonitor, false /* success */); + return false; + } + + mState = STATE_STARTED; + mClientMonitor.start(cb); + + Slog.v(TAG, "started: " + this); + return true; + } + + /** + * Abort a pending operation. + * + * This is similar to cancel but the operation must not have been started. It will + * immediately abort the operation and notify the client that it has finished unsuccessfully. + */ + public void abort() { + checkInState("cannot abort a non-pending operation", + STATE_WAITING_IN_QUEUE, + STATE_WAITING_FOR_COOKIE, + STATE_WAITING_IN_QUEUE_CANCELING); + + if (isHalOperation()) { + ((HalClientMonitor<?>) mClientMonitor).unableToStart(); + } + getWrappedCallback().onClientFinished(mClientMonitor, false /* success */); + + Slog.v(TAG, "Aborted: " + this); + } + + /** Flags this operation as canceled, if possible, but does not cancel it until started. */ + public boolean markCanceling() { + if (mState == STATE_WAITING_IN_QUEUE && isInterruptable()) { + mState = STATE_WAITING_IN_QUEUE_CANCELING; + return true; + } + return false; + } + + /** + * Cancel the operation now. + * + * @param handler handler to use for the cancellation watchdog + * @param callback lifecycle callback (only used if this operation hasn't started, otherwise + * the callback used from {@link #start(BaseClientMonitor.Callback)} is used) + */ + public void cancel(@NonNull Handler handler, @NonNull BaseClientMonitor.Callback callback) { + checkNotInState("cancel", STATE_FINISHED); + + final int currentState = mState; + if (!isInterruptable()) { + Slog.w(TAG, "Cannot cancel - operation not interruptable: " + this); + return; + } + if (currentState == STATE_STARTED_CANCELING) { + Slog.w(TAG, "Cannot cancel - already invoked for operation: " + this); + return; + } + + mState = STATE_STARTED_CANCELING; + if (currentState == STATE_WAITING_IN_QUEUE + || currentState == STATE_WAITING_IN_QUEUE_CANCELING + || currentState == STATE_WAITING_FOR_COOKIE) { + Slog.d(TAG, "[Cancelling] Current client (without start): " + mClientMonitor); + ((Interruptable) mClientMonitor).cancelWithoutStarting(getWrappedCallback(callback)); + } else { + Slog.d(TAG, "[Cancelling] Current client: " + mClientMonitor); + ((Interruptable) mClientMonitor).cancel(); + } + + // forcibly finish this client if the HAL does not acknowledge within the timeout + handler.postDelayed(mCancelWatchdog, CANCEL_WATCHDOG_DELAY_MS); + } + + @NonNull + private BaseClientMonitor.Callback getWrappedCallback() { + return getWrappedCallback(null); + } + + @NonNull + private BaseClientMonitor.Callback getWrappedCallback( + @Nullable BaseClientMonitor.Callback callback) { + final BaseClientMonitor.Callback destroyCallback = new BaseClientMonitor.Callback() { + @Override + public void onClientFinished(@NonNull BaseClientMonitor clientMonitor, + boolean success) { + Slog.d(TAG, "[Finished / destroy]: " + clientMonitor); + mClientMonitor.destroy(); + mState = STATE_FINISHED; + } + }; + return new BaseClientMonitor.CompositeCallback(destroyCallback, callback, mClientCallback); + } + + /** {@link BaseClientMonitor#getSensorId()}. */ + public int getSensorId() { + return mClientMonitor.getSensorId(); + } + + /** {@link BaseClientMonitor#getProtoEnum()}. */ + public int getProtoEnum() { + return mClientMonitor.getProtoEnum(); + } + + /** {@link BaseClientMonitor#getTargetUserId()}. */ + public int getTargetUserId() { + return mClientMonitor.getTargetUserId(); + } + + /** If the given clientMonitor is the same as the one in the constructor. */ + public boolean isFor(@NonNull BaseClientMonitor clientMonitor) { + return mClientMonitor == clientMonitor; + } + + /** If this operation is {@link Interruptable}. */ + public boolean isInterruptable() { + return mClientMonitor instanceof Interruptable; + } + + private boolean isHalOperation() { + return mClientMonitor instanceof HalClientMonitor<?>; + } + + private boolean isUnstartableHalOperation() { + if (isHalOperation()) { + final HalClientMonitor<?> client = (HalClientMonitor<?>) mClientMonitor; + if (client.getFreshDaemon() == null) { + return true; + } + } + return false; + } + + /** If this operation is an enrollment. */ + public boolean isEnrollOperation() { + return mClientMonitor instanceof EnrollClient; + } + + /** If this operation is authentication. */ + public boolean isAuthenticateOperation() { + return mClientMonitor instanceof AuthenticationClient; + } + + /** If this operation is authentication or detection. */ + public boolean isAuthenticationOrDetectionOperation() { + final boolean isAuthentication = mClientMonitor instanceof AuthenticationConsumer; + final boolean isDetection = mClientMonitor instanceof DetectionConsumer; + return isAuthentication || isDetection; + } + + /** If this operation performs acquisition {@link AcquisitionClient}. */ + public boolean isAcquisitionOperation() { + return mClientMonitor instanceof AcquisitionClient; + } + + /** + * If this operation matches the original requestId. + * + * By default, monitors are not associated with a request id to retain the original + * behavior (i.e. if no requestId is explicitly set then assume it matches) + * + * @param requestId a unique id {@link BaseClientMonitor#setRequestId(long)}. + */ + public boolean isMatchingRequestId(long requestId) { + return !mClientMonitor.hasRequestId() + || mClientMonitor.getRequestId() == requestId; + } + + /** If the token matches */ + public boolean isMatchingToken(@Nullable IBinder token) { + return mClientMonitor.getToken() == token; + } + + /** If this operation has started. */ + public boolean isStarted() { + return mState == STATE_STARTED; + } + + /** If this operation is cancelling but has not yet completed. */ + public boolean isCanceling() { + return mState == STATE_STARTED_CANCELING; + } + + /** If this operation has finished and completed its lifecycle. */ + public boolean isFinished() { + return mState == STATE_FINISHED; + } + + /** If {@link #markCanceling()} was called but the operation hasn't been canceled. */ + public boolean isMarkedCanceling() { + return mState == STATE_WAITING_IN_QUEUE_CANCELING; + } + + /** + * The monitor passed to the constructor. + * @deprecated avoid using and move to encapsulate within the operation + */ + @Deprecated + public BaseClientMonitor getClientMonitor() { + return mClientMonitor; + } + + private void checkNotInState(String message, @OperationState int... states) { + for (int state : states) { + if (mState == state) { + throw new IllegalStateException(message + ": illegal state= " + state); + } + } + } + + private void checkInState(String message, @OperationState int... states) { + for (int state : states) { + if (mState == state) { + return; + } + } + throw new IllegalStateException(message + ": illegal state= " + mState); + } + + @Override + public String toString() { + return mClientMonitor + ", State: " + mState; + } +} diff --git a/services/core/java/com/android/server/biometrics/sensors/Interruptable.java b/services/core/java/com/android/server/biometrics/sensors/Interruptable.java index fab98b6581a3..d5093c756415 100644 --- a/services/core/java/com/android/server/biometrics/sensors/Interruptable.java +++ b/services/core/java/com/android/server/biometrics/sensors/Interruptable.java @@ -32,6 +32,11 @@ public interface Interruptable { * {@link BaseClientMonitor#start(BaseClientMonitor.Callback)} was invoked. This usually happens * if the client is still waiting in the pending queue and got notified that a subsequent * operation is preempting it. + * + * This method must invoke + * {@link BaseClientMonitor.Callback#onClientFinished(BaseClientMonitor, boolean)} on the + * given callback (with success). + * * @param callback invoked when the operation is completed. */ void cancelWithoutStarting(@NonNull BaseClientMonitor.Callback callback); diff --git a/services/core/java/com/android/server/biometrics/sensors/UserAwareBiometricScheduler.java b/services/core/java/com/android/server/biometrics/sensors/UserAwareBiometricScheduler.java index b056bf897b5c..603cc22968a9 100644 --- a/services/core/java/com/android/server/biometrics/sensors/UserAwareBiometricScheduler.java +++ b/services/core/java/com/android/server/biometrics/sensors/UserAwareBiometricScheduler.java @@ -16,10 +16,14 @@ package com.android.server.biometrics.sensors; +import static com.android.server.biometrics.sensors.BiometricSchedulerOperation.STATE_STARTED; + import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; import android.hardware.biometrics.IBiometricService; +import android.os.Handler; +import android.os.Looper; import android.os.ServiceManager; import android.os.UserHandle; import android.util.Slog; @@ -68,9 +72,8 @@ public class UserAwareBiometricScheduler extends BiometricScheduler { return; } - Slog.d(getTag(), "[Client finished] " - + clientMonitor + ", success: " + success); - if (mCurrentOperation != null && mCurrentOperation.mClientMonitor == mOwner) { + Slog.d(getTag(), "[Client finished] " + clientMonitor + ", success: " + success); + if (mCurrentOperation != null && mCurrentOperation.isFor(mOwner)) { mCurrentOperation = null; startNextOperationIfIdle(); } else { @@ -83,26 +86,30 @@ public class UserAwareBiometricScheduler extends BiometricScheduler { } @VisibleForTesting - UserAwareBiometricScheduler(@NonNull String tag, @SensorType int sensorType, + public UserAwareBiometricScheduler(@NonNull String tag, + @NonNull Handler handler, + @SensorType int sensorType, @Nullable GestureAvailabilityDispatcher gestureAvailabilityDispatcher, @NonNull IBiometricService biometricService, @NonNull CurrentUserRetriever currentUserRetriever, @NonNull UserSwitchCallback userSwitchCallback, @NonNull CoexCoordinator coexCoordinator) { - super(tag, sensorType, gestureAvailabilityDispatcher, biometricService, + super(tag, handler, sensorType, gestureAvailabilityDispatcher, biometricService, LOG_NUM_RECENT_OPERATIONS, coexCoordinator); mCurrentUserRetriever = currentUserRetriever; mUserSwitchCallback = userSwitchCallback; } - public UserAwareBiometricScheduler(@NonNull String tag, @SensorType int sensorType, + public UserAwareBiometricScheduler(@NonNull String tag, + @SensorType int sensorType, @Nullable GestureAvailabilityDispatcher gestureAvailabilityDispatcher, @NonNull CurrentUserRetriever currentUserRetriever, @NonNull UserSwitchCallback userSwitchCallback) { - this(tag, sensorType, gestureAvailabilityDispatcher, IBiometricService.Stub.asInterface( - ServiceManager.getService(Context.BIOMETRIC_SERVICE)), currentUserRetriever, - userSwitchCallback, CoexCoordinator.getInstance()); + this(tag, new Handler(Looper.getMainLooper()), sensorType, gestureAvailabilityDispatcher, + IBiometricService.Stub.asInterface( + ServiceManager.getService(Context.BIOMETRIC_SERVICE)), + currentUserRetriever, userSwitchCallback, CoexCoordinator.getInstance()); } @Override @@ -122,7 +129,7 @@ public class UserAwareBiometricScheduler extends BiometricScheduler { } final int currentUserId = mCurrentUserRetriever.getCurrentUserId(); - final int nextUserId = mPendingOperations.getFirst().mClientMonitor.getTargetUserId(); + final int nextUserId = mPendingOperations.getFirst().getTargetUserId(); if (nextUserId == currentUserId) { super.startNextOperationIfIdle(); @@ -133,8 +140,8 @@ public class UserAwareBiometricScheduler extends BiometricScheduler { new ClientFinishedCallback(startClient); Slog.d(getTag(), "[Starting User] " + startClient); - mCurrentOperation = new Operation( - startClient, finishedCallback, Operation.STATE_STARTED); + mCurrentOperation = new BiometricSchedulerOperation( + startClient, finishedCallback, STATE_STARTED); startClient.start(finishedCallback); } else { if (mStopUserClient != null) { @@ -147,8 +154,8 @@ public class UserAwareBiometricScheduler extends BiometricScheduler { Slog.d(getTag(), "[Stopping User] current: " + currentUserId + ", next: " + nextUserId + ". " + mStopUserClient); - mCurrentOperation = new Operation( - mStopUserClient, finishedCallback, Operation.STATE_STARTED); + mCurrentOperation = new BiometricSchedulerOperation( + mStopUserClient, finishedCallback, STATE_STARTED); mStopUserClient.start(finishedCallback); } } diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java index 675ee545a14f..039b08e805c1 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java @@ -213,7 +213,7 @@ public class FaceService extends SystemService { } @Override // Binder call - public void enroll(int userId, final IBinder token, final byte[] hardwareAuthToken, + public long enroll(int userId, final IBinder token, final byte[] hardwareAuthToken, final IFaceServiceReceiver receiver, final String opPackageName, final int[] disabledFeatures, Surface previewSurface, boolean debugConsent) { Utils.checkPermission(getContext(), MANAGE_BIOMETRIC); @@ -221,23 +221,24 @@ public class FaceService extends SystemService { final Pair<Integer, ServiceProvider> provider = getSingleProvider(); if (provider == null) { Slog.w(TAG, "Null provider for enroll"); - return; + return -1; } - provider.second.scheduleEnroll(provider.first, token, hardwareAuthToken, userId, + return provider.second.scheduleEnroll(provider.first, token, hardwareAuthToken, userId, receiver, opPackageName, disabledFeatures, previewSurface, debugConsent); } @Override // Binder call - public void enrollRemotely(int userId, final IBinder token, final byte[] hardwareAuthToken, + public long enrollRemotely(int userId, final IBinder token, final byte[] hardwareAuthToken, final IFaceServiceReceiver receiver, final String opPackageName, final int[] disabledFeatures) { Utils.checkPermission(getContext(), MANAGE_BIOMETRIC); // TODO(b/145027036): Implement this. + return -1; } @Override // Binder call - public void cancelEnrollment(final IBinder token) { + public void cancelEnrollment(final IBinder token, long requestId) { Utils.checkPermission(getContext(), MANAGE_BIOMETRIC); final Pair<Integer, ServiceProvider> provider = getSingleProvider(); @@ -246,7 +247,7 @@ public class FaceService extends SystemService { return; } - provider.second.cancelEnrollment(provider.first, token); + provider.second.cancelEnrollment(provider.first, token, requestId); } @Override // Binder call @@ -624,7 +625,7 @@ public class FaceService extends SystemService { private void addHidlProviders(@NonNull List<FaceSensorPropertiesInternal> hidlSensors) { for (FaceSensorPropertiesInternal hidlSensor : hidlSensors) { mServiceProviders.add( - new Face10(getContext(), hidlSensor, mLockoutResetDispatcher)); + Face10.newInstance(getContext(), hidlSensor, mLockoutResetDispatcher)); } } diff --git a/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java b/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java index e099ba372b05..77e431c81192 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java @@ -94,12 +94,12 @@ public interface ServiceProvider { void scheduleRevokeChallenge(int sensorId, int userId, @NonNull IBinder token, @NonNull String opPackageName, long challenge); - void scheduleEnroll(int sensorId, @NonNull IBinder token, @NonNull byte[] hardwareAuthToken, + long scheduleEnroll(int sensorId, @NonNull IBinder token, @NonNull byte[] hardwareAuthToken, int userId, @NonNull IFaceServiceReceiver receiver, @NonNull String opPackageName, @NonNull int[] disabledFeatures, @Nullable Surface previewSurface, boolean debugConsent); - void cancelEnrollment(int sensorId, @NonNull IBinder token); + void cancelEnrollment(int sensorId, @NonNull IBinder token, long requestId); long scheduleFaceDetect(int sensorId, @NonNull IBinder token, int userId, @NonNull ClientMonitorCallbackConverter callback, @NonNull String opPackageName, diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java index a806277ed45e..aae4fbe9b0d7 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java @@ -82,13 +82,14 @@ public class FaceEnrollClient extends EnrollClient<ISession> { FaceEnrollClient(@NonNull Context context, @NonNull LazyDaemon<ISession> lazyDaemon, @NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener, int userId, - @NonNull byte[] hardwareAuthToken, @NonNull String opPackageName, + @NonNull byte[] hardwareAuthToken, @NonNull String opPackageName, long requestId, @NonNull BiometricUtils<Face> utils, @NonNull int[] disabledFeatures, int timeoutSec, @Nullable Surface previewSurface, int sensorId, int maxTemplatesPerUser, boolean debugConsent) { super(context, lazyDaemon, token, listener, userId, hardwareAuthToken, opPackageName, utils, timeoutSec, BiometricsProtoEnums.MODALITY_FACE, sensorId, false /* shouldVibrate */); + setRequestId(requestId); mEnrollIgnoreList = getContext().getResources() .getIntArray(R.array.config_face_acquire_enroll_ignorelist); mEnrollIgnoreListVendor = getContext().getResources() diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java index 4bae7756abe0..ae507abea537 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java @@ -327,17 +327,18 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider { } @Override - public void scheduleEnroll(int sensorId, @NonNull IBinder token, + public long scheduleEnroll(int sensorId, @NonNull IBinder token, @NonNull byte[] hardwareAuthToken, int userId, @NonNull IFaceServiceReceiver receiver, @NonNull String opPackageName, @NonNull int[] disabledFeatures, @Nullable Surface previewSurface, boolean debugConsent) { + final long id = mRequestCounter.incrementAndGet(); mHandler.post(() -> { final int maxTemplatesPerUser = mSensors.get( sensorId).getSensorProperties().maxEnrollmentsPerUser; final FaceEnrollClient client = new FaceEnrollClient(mContext, mSensors.get(sensorId).getLazySession(), token, new ClientMonitorCallbackConverter(receiver), userId, hardwareAuthToken, - opPackageName, FaceUtils.getInstance(sensorId), disabledFeatures, + opPackageName, id, FaceUtils.getInstance(sensorId), disabledFeatures, ENROLL_TIMEOUT_SEC, previewSurface, sensorId, maxTemplatesPerUser, debugConsent); scheduleForSensor(sensorId, client, new BaseClientMonitor.Callback() { @@ -351,11 +352,13 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider { } }); }); + return id; } @Override - public void cancelEnrollment(int sensorId, @NonNull IBinder token) { - mHandler.post(() -> mSensors.get(sensorId).getScheduler().cancelEnrollment(token)); + public void cancelEnrollment(int sensorId, @NonNull IBinder token, long requestId) { + mHandler.post(() -> + mSensors.get(sensorId).getScheduler().cancelEnrollment(token, requestId)); } @Override diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java index f4dcbbba21d7..e957794372aa 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java @@ -333,12 +333,13 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider { Face10(@NonNull Context context, @NonNull FaceSensorPropertiesInternal sensorProps, @NonNull LockoutResetDispatcher lockoutResetDispatcher, + @NonNull Handler handler, @NonNull BiometricScheduler scheduler) { mSensorProperties = sensorProps; mContext = context; mSensorId = sensorProps.sensorId; mScheduler = scheduler; - mHandler = new Handler(Looper.getMainLooper()); + mHandler = handler; mUsageStats = new UsageStats(context); mAuthenticatorIds = new HashMap<>(); mLazyDaemon = Face10.this::getDaemon; @@ -357,9 +358,11 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider { } } - public Face10(@NonNull Context context, @NonNull FaceSensorPropertiesInternal sensorProps, + public static Face10 newInstance(@NonNull Context context, + @NonNull FaceSensorPropertiesInternal sensorProps, @NonNull LockoutResetDispatcher lockoutResetDispatcher) { - this(context, sensorProps, lockoutResetDispatcher, + final Handler handler = new Handler(Looper.getMainLooper()); + return new Face10(context, sensorProps, lockoutResetDispatcher, handler, new BiometricScheduler(TAG, BiometricScheduler.SENSOR_TYPE_FACE, null /* gestureAvailabilityTracker */)); } @@ -573,10 +576,11 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider { } @Override - public void scheduleEnroll(int sensorId, @NonNull IBinder token, + public long scheduleEnroll(int sensorId, @NonNull IBinder token, @NonNull byte[] hardwareAuthToken, int userId, @NonNull IFaceServiceReceiver receiver, @NonNull String opPackageName, @NonNull int[] disabledFeatures, @Nullable Surface previewSurface, boolean debugConsent) { + final long id = mRequestCounter.incrementAndGet(); mHandler.post(() -> { scheduleUpdateActiveUserWithoutHandler(userId); @@ -584,7 +588,7 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider { final FaceEnrollClient client = new FaceEnrollClient(mContext, mLazyDaemon, token, new ClientMonitorCallbackConverter(receiver), userId, hardwareAuthToken, - opPackageName, FaceUtils.getLegacyInstance(mSensorId), disabledFeatures, + opPackageName, id, FaceUtils.getLegacyInstance(mSensorId), disabledFeatures, ENROLL_TIMEOUT_SEC, previewSurface, mSensorId); mScheduler.scheduleClientMonitor(client, new BaseClientMonitor.Callback() { @@ -598,13 +602,12 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider { } }); }); + return id; } @Override - public void cancelEnrollment(int sensorId, @NonNull IBinder token) { - mHandler.post(() -> { - mScheduler.cancelEnrollment(token); - }); + public void cancelEnrollment(int sensorId, @NonNull IBinder token, long requestId) { + mHandler.post(() -> mScheduler.cancelEnrollment(token, requestId)); } @Override @@ -893,6 +896,8 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider { boolean success) { if (success) { mCurrentUserId = targetUserId; + } else { + Slog.w(TAG, "Failed to change user, still: " + mCurrentUserId); } } }); diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceEnrollClient.java index 80828cced4e8..31e5c86103fb 100644 --- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceEnrollClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceEnrollClient.java @@ -53,12 +53,13 @@ public class FaceEnrollClient extends EnrollClient<IBiometricsFace> { FaceEnrollClient(@NonNull Context context, @NonNull LazyDaemon<IBiometricsFace> lazyDaemon, @NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener, int userId, - @NonNull byte[] hardwareAuthToken, @NonNull String owner, + @NonNull byte[] hardwareAuthToken, @NonNull String owner, long requestId, @NonNull BiometricUtils<Face> utils, @NonNull int[] disabledFeatures, int timeoutSec, @Nullable Surface previewSurface, int sensorId) { super(context, lazyDaemon, token, listener, userId, hardwareAuthToken, owner, utils, timeoutSec, BiometricsProtoEnums.MODALITY_FACE, sensorId, false /* shouldVibrate */); + setRequestId(requestId); mDisabledFeatures = Arrays.copyOf(disabledFeatures, disabledFeatures.length); mEnrollIgnoreList = getContext().getResources() .getIntArray(R.array.config_face_acquire_enroll_ignorelist); diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java index c5d33ed7400b..b44f4dc68274 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java @@ -249,7 +249,7 @@ public class FingerprintService extends SystemService { } @Override // Binder call - public void enroll(final IBinder token, @NonNull final byte[] hardwareAuthToken, + public long enroll(final IBinder token, @NonNull final byte[] hardwareAuthToken, final int userId, final IFingerprintServiceReceiver receiver, final String opPackageName, @FingerprintManager.EnrollReason int enrollReason) { Utils.checkPermission(getContext(), MANAGE_FINGERPRINT); @@ -257,15 +257,15 @@ public class FingerprintService extends SystemService { final Pair<Integer, ServiceProvider> provider = getSingleProvider(); if (provider == null) { Slog.w(TAG, "Null provider for enroll"); - return; + return -1; } - provider.second.scheduleEnroll(provider.first, token, hardwareAuthToken, userId, + return provider.second.scheduleEnroll(provider.first, token, hardwareAuthToken, userId, receiver, opPackageName, enrollReason); } @Override // Binder call - public void cancelEnrollment(final IBinder token) { + public void cancelEnrollment(final IBinder token, long requestId) { Utils.checkPermission(getContext(), MANAGE_FINGERPRINT); final Pair<Integer, ServiceProvider> provider = getSingleProvider(); @@ -274,7 +274,7 @@ public class FingerprintService extends SystemService { return; } - provider.second.cancelEnrollment(provider.first, token); + provider.second.cancelEnrollment(provider.first, token, requestId); } @SuppressWarnings("deprecation") @@ -818,7 +818,7 @@ public class FingerprintService extends SystemService { mLockoutResetDispatcher, mGestureAvailabilityDispatcher); } else { fingerprint21 = Fingerprint21.newInstance(getContext(), - mFingerprintStateCallback, hidlSensor, + mFingerprintStateCallback, hidlSensor, mHandler, mLockoutResetDispatcher, mGestureAvailabilityDispatcher); } mServiceProviders.add(fingerprint21); diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java index 1772f814dd10..535705c63cab 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/ServiceProvider.java @@ -88,11 +88,11 @@ public interface ServiceProvider { /** * Schedules fingerprint enrollment. */ - void scheduleEnroll(int sensorId, @NonNull IBinder token, @NonNull byte[] hardwareAuthToken, + long scheduleEnroll(int sensorId, @NonNull IBinder token, @NonNull byte[] hardwareAuthToken, int userId, @NonNull IFingerprintServiceReceiver receiver, @NonNull String opPackageName, @FingerprintManager.EnrollReason int enrollReason); - void cancelEnrollment(int sensorId, @NonNull IBinder token); + void cancelEnrollment(int sensorId, @NonNull IBinder token, long requestId); long scheduleFingerDetect(int sensorId, @NonNull IBinder token, int userId, @NonNull ClientMonitorCallbackConverter callback, @NonNull String opPackageName, diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java index ccb34aad3198..67507ccbbbfe 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java @@ -57,7 +57,7 @@ class FingerprintEnrollClient extends EnrollClient<ISession> implements Udfps { private boolean mIsPointerDown; FingerprintEnrollClient(@NonNull Context context, - @NonNull LazyDaemon<ISession> lazyDaemon, @NonNull IBinder token, + @NonNull LazyDaemon<ISession> lazyDaemon, @NonNull IBinder token, long requestId, @NonNull ClientMonitorCallbackConverter listener, int userId, @NonNull byte[] hardwareAuthToken, @NonNull String owner, @NonNull BiometricUtils<Fingerprint> utils, int sensorId, @@ -69,6 +69,7 @@ class FingerprintEnrollClient extends EnrollClient<ISession> implements Udfps { super(context, lazyDaemon, token, listener, userId, hardwareAuthToken, owner, utils, 0 /* timeoutSec */, BiometricsProtoEnums.MODALITY_FINGERPRINT, sensorId, !sensorProps.isAnyUdfpsType() /* shouldVibrate */); + setRequestId(requestId); mSensorProps = sensorProps; mSensorOverlays = new SensorOverlays(udfpsOverlayController, sidefpsController); mMaxTemplatesPerUser = maxTemplatesPerUser; diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java index 0defc3fb6a50..e8fde1d38aa2 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java @@ -343,15 +343,16 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi } @Override - public void scheduleEnroll(int sensorId, @NonNull IBinder token, + public long scheduleEnroll(int sensorId, @NonNull IBinder token, @NonNull byte[] hardwareAuthToken, int userId, @NonNull IFingerprintServiceReceiver receiver, @NonNull String opPackageName, @FingerprintManager.EnrollReason int enrollReason) { + final long id = mRequestCounter.incrementAndGet(); mHandler.post(() -> { final int maxTemplatesPerUser = mSensors.get(sensorId).getSensorProperties() .maxEnrollmentsPerUser; final FingerprintEnrollClient client = new FingerprintEnrollClient(mContext, - mSensors.get(sensorId).getLazySession(), token, + mSensors.get(sensorId).getLazySession(), token, id, new ClientMonitorCallbackConverter(receiver), userId, hardwareAuthToken, opPackageName, FingerprintUtils.getInstance(sensorId), sensorId, mSensors.get(sensorId).getSensorProperties(), @@ -374,11 +375,13 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi } }); }); + return id; } @Override - public void cancelEnrollment(int sensorId, @NonNull IBinder token) { - mHandler.post(() -> mSensors.get(sensorId).getScheduler().cancelEnrollment(token)); + public void cancelEnrollment(int sensorId, @NonNull IBinder token, long requestId) { + mHandler.post(() -> + mSensors.get(sensorId).getScheduler().cancelEnrollment(token, requestId)); } @Override diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java index 5f2f4cf6ef3c..6feb5fa418bb 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java @@ -42,7 +42,6 @@ import android.hardware.fingerprint.IUdfpsOverlayController; import android.os.Handler; import android.os.IBinder; import android.os.IHwBinder; -import android.os.Looper; import android.os.RemoteException; import android.os.UserHandle; import android.os.UserManager; @@ -320,7 +319,8 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider Fingerprint21(@NonNull Context context, @NonNull FingerprintStateCallback fingerprintStateCallback, @NonNull FingerprintSensorPropertiesInternal sensorProps, - @NonNull BiometricScheduler scheduler, @NonNull Handler handler, + @NonNull BiometricScheduler scheduler, + @NonNull Handler handler, @NonNull LockoutResetDispatcher lockoutResetDispatcher, @NonNull HalResultController controller) { mContext = context; @@ -356,16 +356,15 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider public static Fingerprint21 newInstance(@NonNull Context context, @NonNull FingerprintStateCallback fingerprintStateCallback, @NonNull FingerprintSensorPropertiesInternal sensorProps, + @NonNull Handler handler, @NonNull LockoutResetDispatcher lockoutResetDispatcher, @NonNull GestureAvailabilityDispatcher gestureAvailabilityDispatcher) { - final Handler handler = new Handler(Looper.getMainLooper()); final BiometricScheduler scheduler = new BiometricScheduler(TAG, BiometricScheduler.sensorTypeFromFingerprintProperties(sensorProps), gestureAvailabilityDispatcher); final HalResultController controller = new HalResultController(sensorProps.sensorId, - context, handler, - scheduler); + context, handler, scheduler); return new Fingerprint21(context, fingerprintStateCallback, sensorProps, scheduler, handler, lockoutResetDispatcher, controller); } @@ -491,19 +490,25 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider !getEnrolledFingerprints(mSensorProperties.sensorId, targetUserId).isEmpty(); final FingerprintUpdateActiveUserClient client = new FingerprintUpdateActiveUserClient(mContext, mLazyDaemon, targetUserId, - mContext.getOpPackageName(), mSensorProperties.sensorId, mCurrentUserId, - hasEnrolled, mAuthenticatorIds, force); + mContext.getOpPackageName(), mSensorProperties.sensorId, + this::getCurrentUser, hasEnrolled, mAuthenticatorIds, force); mScheduler.scheduleClientMonitor(client, new BaseClientMonitor.Callback() { @Override public void onClientFinished(@NonNull BaseClientMonitor clientMonitor, boolean success) { if (success) { mCurrentUserId = targetUserId; + } else { + Slog.w(TAG, "Failed to change user, still: " + mCurrentUserId); } } }); } + private int getCurrentUser() { + return mCurrentUserId; + } + @Override public boolean containsSensor(int sensorId) { return mSensorProperties.sensorId == sensorId; @@ -558,18 +563,20 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider } @Override - public void scheduleEnroll(int sensorId, @NonNull IBinder token, + public long scheduleEnroll(int sensorId, @NonNull IBinder token, @NonNull byte[] hardwareAuthToken, int userId, @NonNull IFingerprintServiceReceiver receiver, @NonNull String opPackageName, @FingerprintManager.EnrollReason int enrollReason) { + final long id = mRequestCounter.incrementAndGet(); mHandler.post(() -> { scheduleUpdateActiveUserWithoutHandler(userId); final FingerprintEnrollClient client = new FingerprintEnrollClient(mContext, - mLazyDaemon, token, new ClientMonitorCallbackConverter(receiver), userId, - hardwareAuthToken, opPackageName, FingerprintUtils.getLegacyInstance(mSensorId), - ENROLL_TIMEOUT_SEC, mSensorProperties.sensorId, mUdfpsOverlayController, - mSidefpsController, enrollReason); + mLazyDaemon, token, id, new ClientMonitorCallbackConverter(receiver), + userId, hardwareAuthToken, opPackageName, + FingerprintUtils.getLegacyInstance(mSensorId), ENROLL_TIMEOUT_SEC, + mSensorProperties.sensorId, mUdfpsOverlayController, mSidefpsController, + enrollReason); mScheduler.scheduleClientMonitor(client, new BaseClientMonitor.Callback() { @Override public void onClientStarted(@NonNull BaseClientMonitor clientMonitor) { @@ -588,13 +595,12 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider } }); }); + return id; } @Override - public void cancelEnrollment(int sensorId, @NonNull IBinder token) { - mHandler.post(() -> { - mScheduler.cancelEnrollment(token); - }); + public void cancelEnrollment(int sensorId, @NonNull IBinder token, long requestId) { + mHandler.post(() -> mScheduler.cancelEnrollment(token, requestId)); } @Override diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java index dd68b4d37e2a..273f8a545db5 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21UdfpsMock.java @@ -26,7 +26,6 @@ import android.hardware.fingerprint.FingerprintManager.AuthenticationCallback; import android.hardware.fingerprint.FingerprintManager.AuthenticationResult; import android.hardware.fingerprint.FingerprintSensorProperties; import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; -import android.hardware.fingerprint.FingerprintStateListener; import android.hardware.fingerprint.IUdfpsOverlayController; import android.os.Handler; import android.os.IBinder; @@ -135,43 +134,16 @@ public class Fingerprint21UdfpsMock extends Fingerprint21 implements TrustManage @NonNull private final RestartAuthRunnable mRestartAuthRunnable; private static class TestableBiometricScheduler extends BiometricScheduler { - @NonNull private final TestableInternalCallback mInternalCallback; @NonNull private Fingerprint21UdfpsMock mFingerprint21; - TestableBiometricScheduler(@NonNull String tag, + TestableBiometricScheduler(@NonNull String tag, @NonNull Handler handler, @Nullable GestureAvailabilityDispatcher gestureAvailabilityDispatcher) { - super(tag, BiometricScheduler.SENSOR_TYPE_FP_OTHER, - gestureAvailabilityDispatcher); - mInternalCallback = new TestableInternalCallback(); - } - - class TestableInternalCallback extends InternalCallback { - @Override - public void onClientStarted(BaseClientMonitor clientMonitor) { - super.onClientStarted(clientMonitor); - Slog.d(TAG, "Client started: " + clientMonitor); - mFingerprint21.setDebugMessage("Started: " + clientMonitor); - } - - @Override - public void onClientFinished(BaseClientMonitor clientMonitor, boolean success) { - super.onClientFinished(clientMonitor, success); - Slog.d(TAG, "Client finished: " + clientMonitor); - mFingerprint21.setDebugMessage("Finished: " + clientMonitor); - } + super(tag, BiometricScheduler.SENSOR_TYPE_FP_OTHER, gestureAvailabilityDispatcher); } void init(@NonNull Fingerprint21UdfpsMock fingerprint21) { mFingerprint21 = fingerprint21; } - - /** - * Expose the internal finish callback so it can be used for testing - */ - @Override - @NonNull protected InternalCallback getInternalCallback() { - return mInternalCallback; - } } /** @@ -280,7 +252,7 @@ public class Fingerprint21UdfpsMock extends Fingerprint21 implements TrustManage final Handler handler = new Handler(Looper.getMainLooper()); final TestableBiometricScheduler scheduler = - new TestableBiometricScheduler(TAG, gestureAvailabilityDispatcher); + new TestableBiometricScheduler(TAG, handler, gestureAvailabilityDispatcher); final MockHalResultController controller = new MockHalResultController(sensorProps.sensorId, context, handler, scheduler); return new Fingerprint21UdfpsMock(context, fingerprintStateCallback, sensorProps, scheduler, diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java index 1ebf44ca707f..cc50bdfb59ae 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java @@ -55,7 +55,7 @@ public class FingerprintEnrollClient extends EnrollClient<IBiometricsFingerprint FingerprintEnrollClient(@NonNull Context context, @NonNull LazyDaemon<IBiometricsFingerprint> lazyDaemon, @NonNull IBinder token, - @NonNull ClientMonitorCallbackConverter listener, int userId, + long requestId, @NonNull ClientMonitorCallbackConverter listener, int userId, @NonNull byte[] hardwareAuthToken, @NonNull String owner, @NonNull BiometricUtils<Fingerprint> utils, int timeoutSec, int sensorId, @Nullable IUdfpsOverlayController udfpsOverlayController, @@ -64,6 +64,7 @@ public class FingerprintEnrollClient extends EnrollClient<IBiometricsFingerprint super(context, lazyDaemon, token, listener, userId, hardwareAuthToken, owner, utils, timeoutSec, BiometricsProtoEnums.MODALITY_FINGERPRINT, sensorId, true /* shouldVibrate */); + setRequestId(requestId); mSensorOverlays = new SensorOverlays(udfpsOverlayController, sidefpsController); mEnrollReason = enrollReason; diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintUpdateActiveUserClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintUpdateActiveUserClient.java index fd38bdd1201e..a2c18923c00e 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintUpdateActiveUserClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintUpdateActiveUserClient.java @@ -31,6 +31,7 @@ import com.android.server.biometrics.sensors.HalClientMonitor; import java.io.File; import java.util.Map; +import java.util.function.Supplier; /** * Sets the HAL's current active user, and updates the framework's authenticatorId cache. @@ -40,7 +41,7 @@ public class FingerprintUpdateActiveUserClient extends HalClientMonitor<IBiometr private static final String TAG = "FingerprintUpdateActiveUserClient"; private static final String FP_DATA_DIR = "fpdata"; - private final int mCurrentUserId; + private final Supplier<Integer> mCurrentUserId; private final boolean mForceUpdateAuthenticatorId; private final boolean mHasEnrolledBiometrics; private final Map<Integer, Long> mAuthenticatorIds; @@ -48,8 +49,9 @@ public class FingerprintUpdateActiveUserClient extends HalClientMonitor<IBiometr FingerprintUpdateActiveUserClient(@NonNull Context context, @NonNull LazyDaemon<IBiometricsFingerprint> lazyDaemon, int userId, - @NonNull String owner, int sensorId, int currentUserId, boolean hasEnrolledBiometrics, - @NonNull Map<Integer, Long> authenticatorIds, boolean forceUpdateAuthenticatorId) { + @NonNull String owner, int sensorId, Supplier<Integer> currentUserId, + boolean hasEnrolledBiometrics, @NonNull Map<Integer, Long> authenticatorIds, + boolean forceUpdateAuthenticatorId) { super(context, lazyDaemon, null /* token */, null /* listener */, userId, owner, 0 /* cookie */, sensorId, BiometricsProtoEnums.MODALITY_UNKNOWN, BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN); @@ -63,7 +65,7 @@ public class FingerprintUpdateActiveUserClient extends HalClientMonitor<IBiometr public void start(@NonNull Callback callback) { super.start(callback); - if (mCurrentUserId == getTargetUserId() && !mForceUpdateAuthenticatorId) { + if (mCurrentUserId.get() == getTargetUserId() && !mForceUpdateAuthenticatorId) { Slog.d(TAG, "Already user: " + mCurrentUserId + ", returning"); callback.onClientFinished(this, true /* success */); return; @@ -109,8 +111,10 @@ public class FingerprintUpdateActiveUserClient extends HalClientMonitor<IBiometr @Override protected void startHalOperation() { try { - getFreshDaemon().setActiveGroup(getTargetUserId(), mDirectory.getAbsolutePath()); - mAuthenticatorIds.put(getTargetUserId(), mHasEnrolledBiometrics + final int targetId = getTargetUserId(); + Slog.d(TAG, "Setting active user: " + targetId); + getFreshDaemon().setActiveGroup(targetId, mDirectory.getAbsolutePath()); + mAuthenticatorIds.put(targetId, mHasEnrolledBiometrics ? getFreshDaemon().getAuthenticatorId() : 0L); mCallback.onClientFinished(this, true /* success */); } catch (RemoteException e) { diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java index eb991bd09f20..f526960d0ef3 100644 --- a/services/core/java/com/android/server/connectivity/Vpn.java +++ b/services/core/java/com/android/server/connectivity/Vpn.java @@ -2456,6 +2456,13 @@ public class Vpn { "usepeerdns", "idle", "1800", "mtu", "1270", "mru", "1270", (profile.mppe ? "+mppe" : "nomppe"), }; + if (profile.mppe) { + // Disallow PAP authentication when MPPE is requested, as MPPE cannot work + // with PAP anyway, and users may not expect PAP (plain text) to be used when + // MPPE was requested. + mtpd = Arrays.copyOf(mtpd, mtpd.length + 1); + mtpd[mtpd.length - 1] = "-pap"; + } break; case VpnProfile.TYPE_L2TP_IPSEC_PSK: case VpnProfile.TYPE_L2TP_IPSEC_RSA: diff --git a/services/core/java/com/android/server/display/BrightnessTracker.java b/services/core/java/com/android/server/display/BrightnessTracker.java index 7d8a22a9b563..6de08aed9687 100644 --- a/services/core/java/com/android/server/display/BrightnessTracker.java +++ b/services/core/java/com/android/server/display/BrightnessTracker.java @@ -131,6 +131,7 @@ public class BrightnessTracker { private static final int MSG_STOP_SENSOR_LISTENER = 2; private static final int MSG_START_SENSOR_LISTENER = 3; private static final int MSG_BRIGHTNESS_CONFIG_CHANGED = 4; + private static final int MSG_SENSOR_CHANGED = 5; private static final SimpleDateFormat FORMAT = new SimpleDateFormat("MM-dd HH:mm:ss.SSS"); @@ -158,6 +159,7 @@ public class BrightnessTracker { // These members should only be accessed on the mBgHandler thread. private BroadcastReceiver mBroadcastReceiver; private SensorListener mSensorListener; + private Sensor mLightSensor; private SettingsObserver mSettingsObserver; private DisplayListener mDisplayListener; private boolean mSensorRegistered; @@ -327,6 +329,14 @@ public class BrightnessTracker { m.sendToTarget(); } + /** + * Updates the light sensor to use. + */ + public void setLightSensor(Sensor lightSensor) { + mBgHandler.obtainMessage(MSG_SENSOR_CHANGED, 0 /*unused*/, 0/*unused*/, lightSensor) + .sendToTarget(); + } + private void handleBrightnessChanged(float brightness, boolean userInitiated, float powerBrightnessFactor, boolean isUserSetBrightness, boolean isDefaultBrightnessConfig, long timestamp, String uniqueDisplayId) { @@ -428,13 +438,28 @@ public class BrightnessTracker { } } + private void handleSensorChanged(Sensor lightSensor) { + if (mLightSensor != lightSensor) { + mLightSensor = lightSensor; + stopSensorListener(); + synchronized (mDataCollectionLock) { + mLastSensorReadings.clear(); + } + // Attempt to restart the sensor listener. It will check to see if it should be running + // so there is no need to also check here. + startSensorListener(); + } + } + private void startSensorListener() { if (!mSensorRegistered + && mLightSensor != null + && mAmbientBrightnessStatsTracker != null && mInjector.isInteractive(mContext) && mInjector.isBrightnessModeAutomatic(mContentResolver)) { mAmbientBrightnessStatsTracker.start(); mSensorRegistered = true; - mInjector.registerSensorListener(mContext, mSensorListener, + mInjector.registerSensorListener(mContext, mSensorListener, mLightSensor, mInjector.getBackgroundHandler()); } } @@ -760,6 +785,7 @@ public class BrightnessTracker { pw.println("BrightnessTracker state:"); synchronized (mDataCollectionLock) { pw.println(" mStarted=" + mStarted); + pw.println(" mLightSensor=" + mLightSensor); pw.println(" mLastBatteryLevel=" + mLastBatteryLevel); pw.println(" mLastBrightness=" + mLastBrightness); pw.println(" mLastSensorReadings.size=" + mLastSensorReadings.size()); @@ -1041,6 +1067,9 @@ public class BrightnessTracker { disableColorSampling(); } break; + case MSG_SENSOR_CHANGED: + handleSensorChanged((Sensor) msg.obj); + break; } } @@ -1069,9 +1098,8 @@ public class BrightnessTracker { @VisibleForTesting static class Injector { public void registerSensorListener(Context context, - SensorEventListener sensorListener, Handler handler) { + SensorEventListener sensorListener, Sensor lightSensor, Handler handler) { SensorManager sensorManager = context.getSystemService(SensorManager.class); - Sensor lightSensor = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT); sensorManager.registerListener(sensorListener, lightSensor, SensorManager.SENSOR_DELAY_NORMAL, handler); } diff --git a/services/core/java/com/android/server/display/BrightnessUtils.java b/services/core/java/com/android/server/display/BrightnessUtils.java new file mode 100644 index 000000000000..84fa0cccbd10 --- /dev/null +++ b/services/core/java/com/android/server/display/BrightnessUtils.java @@ -0,0 +1,83 @@ +/* + * 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.server.display; + +import android.util.MathUtils; + +/** + * Utility class providing functions to convert between linear and perceptual gamma space. + * + * Internally, this implements the Hybrid Log Gamma electro-optical transfer function, which is a + * slight improvement to the typical gamma transfer function for displays whose max brightness + * exceeds the 120 nit reference point, but doesn't set a specific reference brightness like the PQ + * function does. + * + * Note that this transfer function is only valid if the display's backlight value is a linear + * control. If it's calibrated to be something non-linear, then a different transfer function + * should be used. + * + * Note: This code is based on the same class in the com.android.settingslib.display package. + */ +public class BrightnessUtils { + + // Hybrid Log Gamma constant values + private static final float R = 0.5f; + private static final float A = 0.17883277f; + private static final float B = 0.28466892f; + private static final float C = 0.55991073f; + + /** + * A function for converting from the gamma space into the linear space. + * + * @param val The value in the gamma space [0 .. 1.0] + * @return The corresponding value in the linear space [0 .. 1.0]. + */ + public static final float convertGammaToLinear(float val) { + final float ret; + if (val <= R) { + ret = MathUtils.sq(val / R); + } else { + ret = MathUtils.exp((val - C) / A) + B; + } + + // HLG is normalized to the range [0, 12], ensure that value is within that range, + // it shouldn't be out of bounds. + final float normalizedRet = MathUtils.constrain(ret, 0, 12); + + // Re-normalize to the range [0, 1] + // in order to derive the correct setting value. + return normalizedRet / 12; + } + + /** + * A function for converting from the linear space into the gamma space. + * + * @param val The value in linear space [0 .. 1.0] + * @return The corresponding value in gamma space [0 .. 1.0] + */ + public static final float convertLinearToGamma(float val) { + // For some reason, HLG normalizes to the range [0, 12] rather than [0, 1] + final float normalizedVal = val * 12; + final float ret; + if (normalizedVal <= 1f) { + ret = MathUtils.sqrt(normalizedVal) * R; + } else { + ret = A * MathUtils.log(normalizedVal - B) + C; + } + return ret; + } +} diff --git a/services/core/java/com/android/server/display/DisplayDeviceConfig.java b/services/core/java/com/android/server/display/DisplayDeviceConfig.java index 2ae5cbbbf24b..255494f98667 100644 --- a/services/core/java/com/android/server/display/DisplayDeviceConfig.java +++ b/services/core/java/com/android/server/display/DisplayDeviceConfig.java @@ -31,6 +31,7 @@ import android.view.DisplayAddress; import com.android.internal.R; import com.android.internal.display.BrightnessSynchronizer; +import com.android.server.display.config.BrightnessThresholds; import com.android.server.display.config.DisplayConfiguration; import com.android.server.display.config.DisplayQuirks; import com.android.server.display.config.HbmTiming; @@ -40,6 +41,7 @@ import com.android.server.display.config.Point; import com.android.server.display.config.RefreshRateRange; import com.android.server.display.config.SensorDetails; import com.android.server.display.config.ThermalStatus; +import com.android.server.display.config.Thresholds; import com.android.server.display.config.XmlParser; import org.xmlpull.v1.XmlPullParserException; @@ -115,6 +117,10 @@ public class DisplayDeviceConfig { private float mBrightnessRampFastIncrease = Float.NaN; private float mBrightnessRampSlowDecrease = Float.NaN; private float mBrightnessRampSlowIncrease = Float.NaN; + private float mScreenBrighteningMinThreshold = 0.0f; // Retain behaviour as though there is + private float mScreenDarkeningMinThreshold = 0.0f; // no minimum threshold for change in + private float mAmbientLuxBrighteningMinThreshold = 0.0f; // screen brightness or ambient + private float mAmbientLuxDarkeningMinThreshold = 0.0f; // brightness. private Spline mBrightnessToBacklightSpline; private Spline mBacklightToBrightnessSpline; private Spline mBacklightToNitsSpline; @@ -282,6 +288,22 @@ public class DisplayDeviceConfig { return mBrightnessRampSlowIncrease; } + public float getScreenBrighteningMinThreshold() { + return mScreenBrighteningMinThreshold; + } + + public float getScreenDarkeningMinThreshold() { + return mScreenDarkeningMinThreshold; + } + + public float getAmbientLuxBrighteningMinThreshold() { + return mAmbientLuxBrighteningMinThreshold; + } + + public float getAmbientLuxDarkeningMinThreshold() { + return mAmbientLuxDarkeningMinThreshold; + } + SensorData getAmbientLightSensor() { return mAmbientLightSensor; } @@ -337,6 +359,10 @@ public class DisplayDeviceConfig { + ", mBrightnessRampFastIncrease=" + mBrightnessRampFastIncrease + ", mBrightnessRampSlowDecrease=" + mBrightnessRampSlowDecrease + ", mBrightnessRampSlowIncrease=" + mBrightnessRampSlowIncrease + + ", mScreenDarkeningMinThreshold=" + mScreenDarkeningMinThreshold + + ", mScreenBrighteningMinThreshold=" + mScreenBrighteningMinThreshold + + ", mAmbientLuxDarkeningMinThreshold=" + mAmbientLuxDarkeningMinThreshold + + ", mAmbientLuxBrighteningMinThreshold=" + mAmbientLuxBrighteningMinThreshold + ", mAmbientLightSensor=" + mAmbientLightSensor + ", mProximitySensor=" + mProximitySensor + ", mRefreshRateLimitations= " + Arrays.toString(mRefreshRateLimitations.toArray()) @@ -392,6 +418,7 @@ public class DisplayDeviceConfig { loadBrightnessRamps(config); loadAmbientLightSensorFromDdc(config); loadProxSensorFromDdc(config); + loadBrightnessChangeThresholds(config); } else { Slog.w(TAG, "DisplayDeviceConfig file is null"); } @@ -746,6 +773,45 @@ public class DisplayDeviceConfig { } } + private void loadBrightnessChangeThresholds(DisplayConfiguration config) { + Thresholds displayBrightnessThresholds = config.getDisplayBrightnessChangeThresholds(); + Thresholds ambientBrightnessThresholds = config.getAmbientBrightnessChangeThresholds(); + + if (displayBrightnessThresholds != null) { + BrightnessThresholds brighteningScreen = + displayBrightnessThresholds.getBrighteningThresholds(); + BrightnessThresholds darkeningScreen = + displayBrightnessThresholds.getDarkeningThresholds(); + + final BigDecimal screenBrighteningThreshold = brighteningScreen.getMinimum(); + final BigDecimal screenDarkeningThreshold = darkeningScreen.getMinimum(); + + if (screenBrighteningThreshold != null) { + mScreenBrighteningMinThreshold = screenBrighteningThreshold.floatValue(); + } + if (screenDarkeningThreshold != null) { + mScreenDarkeningMinThreshold = screenDarkeningThreshold.floatValue(); + } + } + + if (ambientBrightnessThresholds != null) { + BrightnessThresholds brighteningAmbientLux = + ambientBrightnessThresholds.getBrighteningThresholds(); + BrightnessThresholds darkeningAmbientLux = + ambientBrightnessThresholds.getDarkeningThresholds(); + + final BigDecimal ambientBrighteningThreshold = brighteningAmbientLux.getMinimum(); + final BigDecimal ambientDarkeningThreshold = darkeningAmbientLux.getMinimum(); + + if (ambientBrighteningThreshold != null) { + mAmbientLuxBrighteningMinThreshold = ambientBrighteningThreshold.floatValue(); + } + if (ambientDarkeningThreshold != null) { + mAmbientLuxDarkeningMinThreshold = ambientDarkeningThreshold.floatValue(); + } + } + } + private @PowerManager.ThermalStatus int convertThermalStatus(ThermalStatus value) { if (value == null) { return PowerManager.THERMAL_STATUS_NONE; diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java index 22dd2c05c157..77c1fc031598 100644 --- a/services/core/java/com/android/server/display/DisplayPowerController.java +++ b/services/core/java/com/android/server/display/DisplayPowerController.java @@ -795,7 +795,6 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call private void loadFromDisplayDeviceConfig(IBinder token, DisplayDeviceInfo info) { // All properties that depend on the associated DisplayDevice and the DDC must be // updated here. - loadAmbientLightSensor(); loadBrightnessRampRates(); loadProximitySensor(); loadNitsRange(mContext.getResources()); @@ -880,9 +879,14 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call com.android.internal.R.array.config_ambientDarkeningThresholds); int[] ambientThresholdLevels = resources.getIntArray( com.android.internal.R.array.config_ambientThresholdLevels); + float ambientDarkeningMinThreshold = + mDisplayDeviceConfig.getAmbientLuxDarkeningMinThreshold(); + float ambientBrighteningMinThreshold = + mDisplayDeviceConfig.getAmbientLuxBrighteningMinThreshold(); HysteresisLevels ambientBrightnessThresholds = new HysteresisLevels( ambientBrighteningThresholds, ambientDarkeningThresholds, - ambientThresholdLevels); + ambientThresholdLevels, ambientDarkeningMinThreshold, + ambientBrighteningMinThreshold); int[] screenBrighteningThresholds = resources.getIntArray( com.android.internal.R.array.config_screenBrighteningThresholds); @@ -890,8 +894,13 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call com.android.internal.R.array.config_screenDarkeningThresholds); int[] screenThresholdLevels = resources.getIntArray( com.android.internal.R.array.config_screenThresholdLevels); + float screenDarkeningMinThreshold = + mDisplayDeviceConfig.getScreenDarkeningMinThreshold(); + float screenBrighteningMinThreshold = + mDisplayDeviceConfig.getScreenBrighteningMinThreshold(); HysteresisLevels screenBrightnessThresholds = new HysteresisLevels( - screenBrighteningThresholds, screenDarkeningThresholds, screenThresholdLevels); + screenBrighteningThresholds, screenDarkeningThresholds, screenThresholdLevels, + screenDarkeningMinThreshold, screenBrighteningMinThreshold); long brighteningLightDebounce = resources.getInteger( com.android.internal.R.integer.config_autoBrightnessBrighteningLightDebounce); @@ -915,6 +924,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call } loadAmbientLightSensor(); + if (mBrightnessTracker != null) { + mBrightnessTracker.setLightSensor(mLightSensor); + } if (mAutomaticBrightnessController != null) { mAutomaticBrightnessController.stop(); diff --git a/services/core/java/com/android/server/display/HysteresisLevels.java b/services/core/java/com/android/server/display/HysteresisLevels.java index 2b565698ff8c..7a932ce6d7cf 100644 --- a/services/core/java/com/android/server/display/HysteresisLevels.java +++ b/services/core/java/com/android/server/display/HysteresisLevels.java @@ -30,17 +30,13 @@ import java.util.Arrays; public class HysteresisLevels { private static final String TAG = "HysteresisLevels"; - // Default hysteresis constraints for brightening or darkening. - // The recent value must have changed by at least this fraction relative to the - // current value before a change will be considered. - private static final float DEFAULT_BRIGHTENING_HYSTERESIS = 0.10f; - private static final float DEFAULT_DARKENING_HYSTERESIS = 0.20f; - private static final boolean DEBUG = false; private final float[] mBrighteningThresholds; private final float[] mDarkeningThresholds; private final float[] mThresholdLevels; + private final float mMinDarkening; + private final float mMinBrightening; /** * Creates a {@code HysteresisLevels} object with the given equal-length @@ -48,9 +44,12 @@ public class HysteresisLevels { * @param brighteningThresholds an array of brightening hysteresis constraint constants. * @param darkeningThresholds an array of darkening hysteresis constraint constants. * @param thresholdLevels a monotonically increasing array of threshold levels. + * @param minBrighteningThreshold the minimum value for which the brightening value needs to + * return. + * @param minDarkeningThreshold the minimum value for which the darkening value needs to return. */ HysteresisLevels(int[] brighteningThresholds, int[] darkeningThresholds, - int[] thresholdLevels) { + int[] thresholdLevels, float minDarkeningThreshold, float minBrighteningThreshold) { if (brighteningThresholds.length != darkeningThresholds.length || darkeningThresholds.length != thresholdLevels.length + 1) { throw new IllegalArgumentException("Mismatch between hysteresis array lengths."); @@ -58,6 +57,8 @@ public class HysteresisLevels { mBrighteningThresholds = setArrayFormat(brighteningThresholds, 1000.0f); mDarkeningThresholds = setArrayFormat(darkeningThresholds, 1000.0f); mThresholdLevels = setArrayFormat(thresholdLevels, 1.0f); + mMinDarkening = minDarkeningThreshold; + mMinBrightening = minBrighteningThreshold; } /** @@ -65,11 +66,13 @@ public class HysteresisLevels { */ public float getBrighteningThreshold(float value) { final float brightConstant = getReferenceLevel(value, mBrighteningThresholds); - final float brightThreshold = value * (1.0f + brightConstant); + float brightThreshold = value * (1.0f + brightConstant); if (DEBUG) { Slog.d(TAG, "bright hysteresis constant=" + brightConstant + ", threshold=" + brightThreshold + ", value=" + value); } + + brightThreshold = Math.max(brightThreshold, value + mMinBrightening); return brightThreshold; } @@ -78,12 +81,13 @@ public class HysteresisLevels { */ public float getDarkeningThreshold(float value) { final float darkConstant = getReferenceLevel(value, mDarkeningThresholds); - final float darkThreshold = value * (1.0f - darkConstant); + float darkThreshold = value * (1.0f - darkConstant); if (DEBUG) { Slog.d(TAG, "dark hysteresis constant=: " + darkConstant + ", threshold=" + darkThreshold + ", value=" + value); } - return darkThreshold; + darkThreshold = Math.min(darkThreshold, value - mMinDarkening); + return Math.max(darkThreshold, 0.0f); } /** diff --git a/services/core/java/com/android/server/display/RampAnimator.java b/services/core/java/com/android/server/display/RampAnimator.java index ed3b15fb2661..d8672fc07619 100644 --- a/services/core/java/com/android/server/display/RampAnimator.java +++ b/services/core/java/com/android/server/display/RampAnimator.java @@ -23,6 +23,8 @@ import android.view.Choreographer; /** * A custom animator that progressively updates a property value at * a given variable rate until it reaches a particular target value. + * The ramping at the given rate is done in the perceptual space using + * the HLG transfer functions. */ class RampAnimator<T> { private final T mObject; @@ -57,7 +59,9 @@ class RampAnimator<T> { * @param rate The convergence rate in units per second, or 0 to set the value immediately. * @return True if the target differs from the previous target. */ - public boolean animateTo(float target, float rate) { + public boolean animateTo(float targetLinear, float rate) { + // Convert the target from the linear into the HLG space. + final float target = BrightnessUtils.convertLinearToGamma(targetLinear); // Immediately jump to the target the first time. if (mFirstTime || rate <= 0) { @@ -66,7 +70,7 @@ class RampAnimator<T> { mRate = 0; mTargetValue = target; mCurrentValue = target; - mProperty.setValue(mObject, target); + setPropertyValue(target); if (mAnimating) { mAnimating = false; cancelAnimationCallback(); @@ -121,6 +125,15 @@ class RampAnimator<T> { mListener = listener; } + /** + * Sets the brightness property by converting the given value from HLG space + * into linear space. + */ + private void setPropertyValue(float val) { + final float linearVal = BrightnessUtils.convertGammaToLinear(val); + mProperty.setValue(mObject, linearVal); + } + private void postAnimationCallback() { mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION, mAnimationCallback, null); } @@ -156,7 +169,7 @@ class RampAnimator<T> { final float oldCurrentValue = mCurrentValue; mCurrentValue = mAnimatedValue; if (oldCurrentValue != mCurrentValue) { - mProperty.setValue(mObject, mCurrentValue); + setPropertyValue(mCurrentValue); } if (mTargetValue != mCurrentValue) { postAnimationCallback(); @@ -201,14 +214,14 @@ class RampAnimator<T> { * If this is the first time the property is being set or if the rate is 0, * the value jumps directly to the target. * - * @param firstTarget The first target value. - * @param secondTarget The second target value. + * @param linearFirstTarget The first target value in linear space. + * @param linearSecondTarget The second target value in linear space. * @param rate The convergence rate in units per second, or 0 to set the value immediately. * @return True if either target differs from the previous target. */ - public boolean animateTo(float firstTarget, float secondTarget, float rate) { - final boolean firstRetval = mFirst.animateTo(firstTarget, rate); - final boolean secondRetval = mSecond.animateTo(secondTarget, rate); + public boolean animateTo(float linearFirstTarget, float linearSecondTarget, float rate) { + final boolean firstRetval = mFirst.animateTo(linearFirstTarget, rate); + final boolean secondRetval = mSecond.animateTo(linearSecondTarget, rate); return firstRetval && secondRetval; } diff --git a/services/core/java/com/android/server/location/gnss/GnssNetworkConnectivityHandler.java b/services/core/java/com/android/server/location/gnss/GnssNetworkConnectivityHandler.java index 4d9253eff69e..718f98a0f04b 100644 --- a/services/core/java/com/android/server/location/gnss/GnssNetworkConnectivityHandler.java +++ b/services/core/java/com/android/server/location/gnss/GnssNetworkConnectivityHandler.java @@ -215,7 +215,9 @@ class GnssNetworkConnectivityHandler { } @Override public void onPreciseCallStateChanged(PreciseCallState state) { - if (state.PRECISE_CALL_STATE_ACTIVE == state.getForegroundCallState()) { + if (PreciseCallState.PRECISE_CALL_STATE_ACTIVE == state.getForegroundCallState() + || PreciseCallState.PRECISE_CALL_STATE_DIALING + == state.getForegroundCallState()) { mActiveSubId = mSubId; if (DEBUG) Log.d(TAG, "mActiveSubId: " + mActiveSubId); } diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index bdd683022d08..f836a6c4af7a 100755 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -7706,7 +7706,9 @@ public class NotificationManagerService extends SystemService { int index = mToastQueue.indexOf(record); if (index >= 0) { - mToastQueue.remove(index); + ToastRecord toast = mToastQueue.remove(index); + mWindowManagerInternal.removeWindowToken( + toast.windowToken, true /* removeWindows */, toast.displayId); } record = (mToastQueue.size() > 0) ? mToastQueue.get(0) : null; } @@ -10065,10 +10067,10 @@ public class NotificationManagerService extends SystemService { boolean isPrimary, boolean enabled, boolean userSet) { super.setPackageOrComponentEnabled(pkgOrComponent, userId, isPrimary, enabled, userSet); - getContext().sendBroadcastAsUser( + mContext.sendBroadcastAsUser( new Intent(ACTION_NOTIFICATION_LISTENER_ENABLED_CHANGED) .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY), - UserHandle.ALL, null); + UserHandle.of(userId), null); } @Override diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java index b6b54fc19011..c3e0290fb530 100644 --- a/services/core/java/com/android/server/notification/NotificationRecord.java +++ b/services/core/java/com/android/server/notification/NotificationRecord.java @@ -200,6 +200,10 @@ public final class NotificationRecord { private boolean mIsAppImportanceLocked; private ArraySet<Uri> mGrantableUris; + // Storage for phone numbers that were found to be associated with + // contacts in this notification. + private ArraySet<String> mPhoneNumbers; + // Whether this notification record should have an update logged the next time notifications // are sorted. private boolean mPendingLogUpdate = false; @@ -1525,6 +1529,26 @@ public final class NotificationRecord { return mPendingLogUpdate; } + /** + * Merge the given set of phone numbers into the list of phone numbers that + * are cached on this notification record. + */ + public void mergePhoneNumbers(ArraySet<String> phoneNumbers) { + // if the given phone numbers are null or empty then don't do anything + if (phoneNumbers == null || phoneNumbers.size() == 0) { + return; + } + // initialize if not already + if (mPhoneNumbers == null) { + mPhoneNumbers = new ArraySet<>(); + } + mPhoneNumbers.addAll(phoneNumbers); + } + + public ArraySet<String> getPhoneNumbers() { + return mPhoneNumbers; + } + @VisibleForTesting static final class Light { public final int color; diff --git a/services/core/java/com/android/server/notification/ValidateNotificationPeople.java b/services/core/java/com/android/server/notification/ValidateNotificationPeople.java index d7bc3bb8af28..bdc571103ffd 100644 --- a/services/core/java/com/android/server/notification/ValidateNotificationPeople.java +++ b/services/core/java/com/android/server/notification/ValidateNotificationPeople.java @@ -68,10 +68,17 @@ public class ValidateNotificationPeople implements NotificationSignalExtractor { private static final boolean ENABLE_PEOPLE_VALIDATOR = true; private static final String SETTING_ENABLE_PEOPLE_VALIDATOR = "validate_notification_people_enabled"; - private static final String[] LOOKUP_PROJECTION = { Contacts._ID, Contacts.STARRED }; + private static final String[] LOOKUP_PROJECTION = { Contacts._ID, Contacts.LOOKUP_KEY, + Contacts.STARRED, Contacts.HAS_PHONE_NUMBER }; private static final int MAX_PEOPLE = 10; private static final int PEOPLE_CACHE_SIZE = 200; + /** Columns used to look up phone numbers for contacts. */ + @VisibleForTesting + static final String[] PHONE_LOOKUP_PROJECTION = + { ContactsContract.CommonDataKinds.Phone.NORMALIZED_NUMBER, + ContactsContract.CommonDataKinds.Phone.NUMBER }; + /** Indicates that the notification does not reference any valid contacts. */ static final float NONE = 0f; @@ -409,6 +416,35 @@ public class ValidateNotificationPeople implements NotificationSignalExtractor { return lookupResult; } + @VisibleForTesting + // Performs a contacts search using searchContacts, and then follows up by looking up + // any phone numbers associated with the resulting contact information and merge those + // into the lookup result as well. Will have no additional effect if the contact does + // not have any phone numbers. + LookupResult searchContactsAndLookupNumbers(Context context, Uri lookupUri) { + LookupResult lookupResult = searchContacts(context, lookupUri); + String phoneLookupKey = lookupResult.getPhoneLookupKey(); + if (phoneLookupKey != null) { + String selection = Contacts.LOOKUP_KEY + " = ?"; + String[] selectionArgs = new String[] { phoneLookupKey }; + try (Cursor cursor = context.getContentResolver().query( + ContactsContract.CommonDataKinds.Phone.CONTENT_URI, PHONE_LOOKUP_PROJECTION, + selection, selectionArgs, /* sortOrder= */ null)) { + if (cursor == null) { + Slog.w(TAG, "Cursor is null when querying contact phone number."); + return lookupResult; + } + + while (cursor.moveToNext()) { + lookupResult.mergePhoneNumber(cursor); + } + } catch (Throwable t) { + Slog.w(TAG, "Problem getting content resolver or querying phone numbers.", t); + } + } + return lookupResult; + } + private void addWorkContacts(LookupResult lookupResult, Context context, Uri corpLookupUri) { final int workUserId = findWorkUserId(context); if (workUserId == -1) { @@ -454,6 +490,9 @@ public class ValidateNotificationPeople implements NotificationSignalExtractor { private final long mExpireMillis; private float mAffinity = NONE; + private boolean mHasPhone = false; + private String mPhoneLookupKey = null; + private ArraySet<String> mPhoneNumbers = new ArraySet<>(); public LookupResult() { mExpireMillis = System.currentTimeMillis() + CONTACT_REFRESH_MILLIS; @@ -473,6 +512,15 @@ public class ValidateNotificationPeople implements NotificationSignalExtractor { Slog.i(TAG, "invalid cursor: no _ID"); } + // Lookup key for potentially looking up contact phone number later + final int lookupKeyIdx = cursor.getColumnIndex(Contacts.LOOKUP_KEY); + if (lookupKeyIdx >= 0) { + mPhoneLookupKey = cursor.getString(lookupKeyIdx); + if (DEBUG) Slog.d(TAG, "contact LOOKUP_KEY is: " + mPhoneLookupKey); + } else { + if (DEBUG) Slog.d(TAG, "invalid cursor: no LOOKUP_KEY"); + } + // Starred final int starIdx = cursor.getColumnIndex(Contacts.STARRED); if (starIdx >= 0) { @@ -484,6 +532,46 @@ public class ValidateNotificationPeople implements NotificationSignalExtractor { } else { if (DEBUG) Slog.d(TAG, "invalid cursor: no STARRED"); } + + // whether a phone number is present + final int hasPhoneIdx = cursor.getColumnIndex(Contacts.HAS_PHONE_NUMBER); + if (hasPhoneIdx >= 0) { + mHasPhone = cursor.getInt(hasPhoneIdx) != 0; + if (DEBUG) Slog.d(TAG, "contact HAS_PHONE_NUMBER is: " + mHasPhone); + } else { + if (DEBUG) Slog.d(TAG, "invalid cursor: no HAS_PHONE_NUMBER"); + } + } + + // Returns the phone lookup key that is cached in this result, or null + // if the contact has no known phone info. + public String getPhoneLookupKey() { + if (!mHasPhone) { + return null; + } + return mPhoneLookupKey; + } + + // Merge phone numbers found in this lookup and store them in mPhoneNumbers. + public void mergePhoneNumber(Cursor cursor) { + final int normalizedNumIdx = cursor.getColumnIndex( + ContactsContract.CommonDataKinds.Phone.NORMALIZED_NUMBER); + if (normalizedNumIdx >= 0) { + mPhoneNumbers.add(cursor.getString(normalizedNumIdx)); + } else { + if (DEBUG) Slog.d(TAG, "cursor data not found: no NORMALIZED_NUMBER"); + } + + final int numIdx = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER); + if (numIdx >= 0) { + mPhoneNumbers.add(cursor.getString(numIdx)); + } else { + if (DEBUG) Slog.d(TAG, "cursor data not found: no NUMBER"); + } + } + + public ArraySet<String> getPhoneNumbers() { + return mPhoneNumbers; } private boolean isExpired() { @@ -509,6 +597,7 @@ public class ValidateNotificationPeople implements NotificationSignalExtractor { // Amount of time to wait for a result from the contacts db before rechecking affinity. private static final long LOOKUP_TIME = 1000; private float mContactAffinity = NONE; + private ArraySet<String> mPhoneNumbers = null; private NotificationRecord mRecord; private PeopleRankingReconsideration(Context context, String key, @@ -543,7 +632,9 @@ public class ValidateNotificationPeople implements NotificationSignalExtractor { lookupResult = resolveEmailContact(mContext, uri.getSchemeSpecificPart()); } else if (handle.startsWith(Contacts.CONTENT_LOOKUP_URI.toString())) { if (DEBUG) Slog.d(TAG, "checking lookup URI: " + handle); - lookupResult = searchContacts(mContext, uri); + // only look up phone number if this is a contact lookup uri and thus isn't + // already directly a phone number. + lookupResult = searchContactsAndLookupNumbers(mContext, uri); } else { lookupResult = new LookupResult(); // invalid person for the cache if (!"name".equals(uri.getScheme())) { @@ -561,6 +652,13 @@ public class ValidateNotificationPeople implements NotificationSignalExtractor { Slog.d(TAG, "lookup contactAffinity is " + lookupResult.getAffinity()); } mContactAffinity = Math.max(mContactAffinity, lookupResult.getAffinity()); + // merge any phone numbers found in this lookup result + if (lookupResult.getPhoneNumbers() != null) { + if (mPhoneNumbers == null) { + mPhoneNumbers = new ArraySet<>(); + } + mPhoneNumbers.addAll(lookupResult.getPhoneNumbers()); + } } else { if (DEBUG) Slog.d(TAG, "lookupResult is null"); } @@ -581,6 +679,7 @@ public class ValidateNotificationPeople implements NotificationSignalExtractor { float affinityBound = operand.getContactAffinity(); operand.setContactAffinity(Math.max(mContactAffinity, affinityBound)); if (VERBOSE) Slog.i(TAG, "final affinity: " + operand.getContactAffinity()); + operand.mergePhoneNumbers(mPhoneNumbers); } public float getContactAffinity() { diff --git a/services/core/java/com/android/server/notification/ZenModeFiltering.java b/services/core/java/com/android/server/notification/ZenModeFiltering.java index 4d1985590d7d..458bef3a2567 100644 --- a/services/core/java/com/android/server/notification/ZenModeFiltering.java +++ b/services/core/java/com/android/server/notification/ZenModeFiltering.java @@ -24,12 +24,16 @@ import android.app.NotificationManager; import android.content.ComponentName; import android.content.Context; import android.media.AudioAttributes; +import android.net.Uri; import android.os.Bundle; import android.os.UserHandle; import android.provider.Settings.Global; import android.service.notification.ZenModeConfig; import android.telecom.TelecomManager; +import android.telephony.PhoneNumberUtils; +import android.telephony.TelephonyManager; import android.util.ArrayMap; +import android.util.ArraySet; import android.util.Slog; import com.android.internal.messages.nano.SystemMessageProto; @@ -64,13 +68,22 @@ public class ZenModeFiltering { pw.print(prefix); pw.print("RepeatCallers.mThresholdMinutes="); pw.println(REPEAT_CALLERS.mThresholdMinutes); synchronized (REPEAT_CALLERS) { - if (!REPEAT_CALLERS.mCalls.isEmpty()) { - pw.print(prefix); pw.println("RepeatCallers.mCalls="); - for (int i = 0; i < REPEAT_CALLERS.mCalls.size(); i++) { + if (!REPEAT_CALLERS.mTelCalls.isEmpty()) { + pw.print(prefix); pw.println("RepeatCallers.mTelCalls="); + for (int i = 0; i < REPEAT_CALLERS.mTelCalls.size(); i++) { pw.print(prefix); pw.print(" "); - pw.print(REPEAT_CALLERS.mCalls.keyAt(i)); + pw.print(REPEAT_CALLERS.mTelCalls.keyAt(i)); pw.print(" at "); - pw.println(ts(REPEAT_CALLERS.mCalls.valueAt(i))); + pw.println(ts(REPEAT_CALLERS.mTelCalls.valueAt(i))); + } + } + if (!REPEAT_CALLERS.mOtherCalls.isEmpty()) { + pw.print(prefix); pw.println("RepeatCallers.mOtherCalls="); + for (int i = 0; i < REPEAT_CALLERS.mOtherCalls.size(); i++) { + pw.print(prefix); pw.print(" "); + pw.print(REPEAT_CALLERS.mOtherCalls.keyAt(i)); + pw.print(" at "); + pw.println(ts(REPEAT_CALLERS.mOtherCalls.valueAt(i))); } } } @@ -93,7 +106,7 @@ public class ZenModeFiltering { if (zen == Global.ZEN_MODE_ALARMS) return false; // not an alarm if (zen == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS) { if (consolidatedPolicy.allowRepeatCallers() - && REPEAT_CALLERS.isRepeat(context, extras)) { + && REPEAT_CALLERS.isRepeat(context, extras, null)) { return true; } if (!consolidatedPolicy.allowCalls()) return false; // no other calls get through @@ -112,7 +125,7 @@ public class ZenModeFiltering { } protected void recordCall(NotificationRecord record) { - REPEAT_CALLERS.recordCall(mContext, extras(record)); + REPEAT_CALLERS.recordCall(mContext, extras(record), record.getPhoneNumbers()); } /** @@ -202,7 +215,8 @@ public class ZenModeFiltering { } if (isCall(record)) { if (policy.allowRepeatCallers() - && REPEAT_CALLERS.isRepeat(mContext, extras(record))) { + && REPEAT_CALLERS.isRepeat( + mContext, extras(record), record.getPhoneNumbers())) { ZenLog.traceNotIntercepted(record, "repeatCaller"); return false; } @@ -311,41 +325,77 @@ public class ZenModeFiltering { } } + protected void cleanUpCallersAfter(long timeThreshold) { + REPEAT_CALLERS.cleanUpCallsAfter(timeThreshold); + } + private static class RepeatCallers { - // Person : time - private final ArrayMap<String, Long> mCalls = new ArrayMap<>(); + // We keep a separate map per uri scheme to do more generous number-matching + // handling on telephone numbers specifically. For other inputs, we + // simply match directly on the string. + private final ArrayMap<String, Long> mTelCalls = new ArrayMap<>(); + private final ArrayMap<String, Long> mOtherCalls = new ArrayMap<>(); private int mThresholdMinutes; - private synchronized void recordCall(Context context, Bundle extras) { + // Record all people URIs in the extras bundle as well as the provided phoneNumbers set + // as callers. The phoneNumbers set is used to pass in any additional phone numbers + // associated with the people URIs as separately retrieved from contacts. + private synchronized void recordCall(Context context, Bundle extras, + ArraySet<String> phoneNumbers) { setThresholdMinutes(context); if (mThresholdMinutes <= 0 || extras == null) return; - final String peopleString = peopleString(extras); - if (peopleString == null) return; + final String[] extraPeople = ValidateNotificationPeople.getExtraPeople(extras); + if (extraPeople == null || extraPeople.length == 0) return; final long now = System.currentTimeMillis(); - cleanUp(mCalls, now); - mCalls.put(peopleString, now); + cleanUp(mTelCalls, now); + cleanUp(mOtherCalls, now); + recordCallers(extraPeople, phoneNumbers, now); } - private synchronized boolean isRepeat(Context context, Bundle extras) { + // Determine whether any people in the provided extras bundle or phone number set is + // a repeat caller. The extras bundle contains the people associated with a specific + // notification, and will suffice for most callers; the phoneNumbers array may be used + // to additionally check any specific phone numbers previously retrieved from contacts + // associated with the people in the extras bundle. + private synchronized boolean isRepeat(Context context, Bundle extras, + ArraySet<String> phoneNumbers) { setThresholdMinutes(context); if (mThresholdMinutes <= 0 || extras == null) return false; - final String peopleString = peopleString(extras); - if (peopleString == null) return false; + final String[] extraPeople = ValidateNotificationPeople.getExtraPeople(extras); + if (extraPeople == null || extraPeople.length == 0) return false; final long now = System.currentTimeMillis(); - cleanUp(mCalls, now); - return mCalls.containsKey(peopleString); + cleanUp(mTelCalls, now); + cleanUp(mOtherCalls, now); + return checkCallers(context, extraPeople, phoneNumbers); } private synchronized void cleanUp(ArrayMap<String, Long> calls, long now) { final int N = calls.size(); for (int i = N - 1; i >= 0; i--) { - final long time = mCalls.valueAt(i); + final long time = calls.valueAt(i); if (time > now || (now - time) > mThresholdMinutes * 1000 * 60) { calls.removeAt(i); } } } + // Clean up all calls that occurred after the given time. + // Used only for tests, to clean up after testing. + private synchronized void cleanUpCallsAfter(long timeThreshold) { + for (int i = mTelCalls.size() - 1; i >= 0; i--) { + final long time = mTelCalls.valueAt(i); + if (time > timeThreshold) { + mTelCalls.removeAt(i); + } + } + for (int j = mOtherCalls.size() - 1; j >= 0; j--) { + final long time = mOtherCalls.valueAt(j); + if (time > timeThreshold) { + mOtherCalls.removeAt(j); + } + } + } + private void setThresholdMinutes(Context context) { if (mThresholdMinutes <= 0) { mThresholdMinutes = context.getResources().getInteger(com.android.internal.R.integer @@ -353,21 +403,87 @@ public class ZenModeFiltering { } } - private static String peopleString(Bundle extras) { - final String[] extraPeople = ValidateNotificationPeople.getExtraPeople(extras); - if (extraPeople == null || extraPeople.length == 0) return null; - final StringBuilder sb = new StringBuilder(); - for (int i = 0; i < extraPeople.length; i++) { - String extraPerson = extraPeople[i]; - if (extraPerson == null) continue; - extraPerson = extraPerson.trim(); - if (extraPerson.isEmpty()) continue; - if (sb.length() > 0) { - sb.append('|'); + private synchronized void recordCallers(String[] people, ArraySet<String> phoneNumbers, + long now) { + for (int i = 0; i < people.length; i++) { + String person = people[i]; + if (person == null) continue; + final Uri uri = Uri.parse(person); + if ("tel".equals(uri.getScheme())) { + // while ideally we should not need to decode this, sometimes we have seen tel + // numbers given in an encoded format + String tel = Uri.decode(uri.getSchemeSpecificPart()); + if (tel != null) mTelCalls.put(tel, now); + } else { + // for non-tel calls, store the entire string, uri-component and all + mOtherCalls.put(person, now); + } + } + + // record any additional numbers from the notification record if + // provided; these are in the format of just a phone number string + if (phoneNumbers != null) { + for (String num : phoneNumbers) { + if (num != null) mTelCalls.put(num, now); } - sb.append(extraPerson); } - return sb.length() == 0 ? null : sb.toString(); + } + + // helper function to check mTelCalls array for a number, and also check its decoded + // version + private synchronized boolean checkForNumber(String number, String defaultCountryCode) { + if (mTelCalls.containsKey(number)) { + // check directly via map first + return true; + } else { + // see if a number that matches via areSameNumber exists + String numberToCheck = Uri.decode(number); + if (numberToCheck != null) { + for (String prev : mTelCalls.keySet()) { + if (PhoneNumberUtils.areSamePhoneNumber( + numberToCheck, prev, defaultCountryCode)) { + return true; + } + } + } + } + return false; + } + + // Check whether anyone in the provided array of people URIs or phone number set matches a + // previously recorded phone call. + private synchronized boolean checkCallers(Context context, String[] people, + ArraySet<String> phoneNumbers) { + // get the default country code for checking telephone numbers + final String defaultCountryCode = + context.getSystemService(TelephonyManager.class).getNetworkCountryIso(); + for (int i = 0; i < people.length; i++) { + String person = people[i]; + if (person == null) continue; + final Uri uri = Uri.parse(person); + if ("tel".equals(uri.getScheme())) { + String number = uri.getSchemeSpecificPart(); + if (checkForNumber(number, defaultCountryCode)) { + return true; + } + } else { + if (mOtherCalls.containsKey(person)) { + return true; + } + } + } + + // also check any passed-in phone numbers + if (phoneNumbers != null) { + for (String num : phoneNumbers) { + if (checkForNumber(num, defaultCountryCode)) { + return true; + } + } + } + + // no matches + return false; } } diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java index 16a0b7e39a07..c11116c827cb 100644 --- a/services/core/java/com/android/server/notification/ZenModeHelper.java +++ b/services/core/java/com/android/server/notification/ZenModeHelper.java @@ -104,6 +104,7 @@ public class ZenModeHelper { // The amount of time rules instances can exist without their owning app being installed. private static final int RULE_INSTANCE_GRACE_PERIOD = 1000 * 60 * 60 * 72; + static final int RULE_LIMIT_PER_PACKAGE = 100; // pkg|userId => uid protected final ArrayMap<String, Integer> mRulesUidCache = new ArrayMap<>(); @@ -325,10 +326,10 @@ public class ZenModeHelper { int newRuleInstanceCount = getCurrentInstanceCount(automaticZenRule.getOwner()) + getCurrentInstanceCount(automaticZenRule.getConfigurationActivity()) + 1; - if (ruleInstanceLimit > 0 && ruleInstanceLimit < newRuleInstanceCount) { + if (newRuleInstanceCount > RULE_LIMIT_PER_PACKAGE + || (ruleInstanceLimit > 0 && ruleInstanceLimit < newRuleInstanceCount)) { throw new IllegalArgumentException("Rule instance limit exceeded"); } - } ZenModeConfig newConfig; diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java index 7b6c8e3fad62..37547fa5a377 100644 --- a/services/core/java/com/android/server/pm/PackageInstallerService.java +++ b/services/core/java/com/android/server/pm/PackageInstallerService.java @@ -394,7 +394,10 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements // Their staging dirs will be removed too PackageInstallerSession root = !session.hasParentSessionId() ? session : mSessions.get(session.getParentSessionId()); - if (!root.isDestroyed()) { + if (root == null) { + Slog.e(TAG, "freeStageDirs: found an orphaned session: " + + session.sessionId + " parent=" + session.getParentSessionId()); + } else if (!root.isDestroyed()) { root.abandon(); } } else { diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 7d1dbc53fedb..39d501be6c89 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -21609,6 +21609,16 @@ public class PackageManagerService extends IPackageManager.Stub return PackageManager.DELETE_FAILED_INTERNAL_ERROR; } + if (isSystemApp(uninstalledPs)) { + UserInfo userInfo = mUserManager.getUserInfo(userId); + if (userInfo == null || !userInfo.isAdmin()) { + Slog.w(TAG, "Not removing package " + packageName + + " as only admin user may downgrade system apps"); + EventLog.writeEvent(0x534e4554, "170646036", -1, packageName); + return PackageManager.DELETE_FAILED_USER_RESTRICTED; + } + } + disabledSystemPs = mSettings.getDisabledSystemPkgLPr(packageName); // Static shared libs can be declared by any package, so let us not // allow removing a package if it provides a lib others depend on. diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index 26aebbc1ea93..851ef08c6f87 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -116,6 +116,7 @@ import com.android.server.pm.permission.LegacyPermissionState.PermissionState; import com.android.server.pm.verify.domain.DomainVerificationLegacySettings; import com.android.server.pm.verify.domain.DomainVerificationManagerInternal; import com.android.server.pm.verify.domain.DomainVerificationPersistence; +import com.android.server.utils.Slogf; import com.android.server.utils.Snappable; import com.android.server.utils.SnapshotCache; import com.android.server.utils.TimingsTraceAndSlog; @@ -944,7 +945,8 @@ public final class Settings implements Watchable, Snappable { Slog.i(PackageManagerService.TAG, "Stopping package " + pkgName, e); } List<UserInfo> users = getAllUsers(userManager); - final int installUserId = installUser != null ? installUser.getIdentifier() : 0; + int installUserId = installUser != null ? installUser.getIdentifier() + : UserHandle.USER_SYSTEM; if (users != null && allowInstall) { for (UserInfo user : users) { // By default we consider this app to be installed @@ -955,8 +957,14 @@ public final class Settings implements Watchable, Snappable { // user we are installing for. final boolean installed = installUser == null || (installUserId == UserHandle.USER_ALL - && !isAdbInstallDisallowed(userManager, user.id)) + && !isAdbInstallDisallowed(userManager, user.id) + && !user.preCreated) || installUserId == user.id; + if (DEBUG_MU) { + Slogf.d(TAG, "createNewSetting(pkg=%s, installUserId=%s, user=%s, " + + "installed=%b)", + pkgName, installUserId, user.toFullString(), installed); + } pkgSetting.setUserState(user.id, 0, COMPONENT_ENABLED_STATE_DEFAULT, installed, true /*stopped*/, @@ -1980,11 +1988,14 @@ public final class Settings implements Watchable, Snappable { serializer.startTag(null, TAG_PACKAGE_RESTRICTIONS); - if (DEBUG_MU) Log.i(TAG, "Writing " + userPackagesStateFile); + if (DEBUG_MU) { + Slogf.i(TAG, "Writing %s (%d packages)", userPackagesStateFile, + mPackages.values().size()); + } for (final PackageSetting pkg : mPackages.values()) { final PackageUserState ustate = pkg.readUserState(userId); if (DEBUG_MU) { - Log.i(TAG, " pkg=" + pkg.name + ", installed=" + ustate.installed + Log.v(TAG, " pkg=" + pkg.name + ", installed=" + ustate.installed + ", state=" + ustate.enabled); } diff --git a/services/core/java/com/android/server/pm/TEST_MAPPING b/services/core/java/com/android/server/pm/TEST_MAPPING index 9182d811d56d..b2088fdb17d1 100644 --- a/services/core/java/com/android/server/pm/TEST_MAPPING +++ b/services/core/java/com/android/server/pm/TEST_MAPPING @@ -41,20 +41,6 @@ ] }, { - "name": "CtsContentTestCases", - "options": [ - { - "exclude-annotation": "androidx.test.filters.FlakyTest" - }, - { - "exclude-annotation": "org.junit.Ignore" - }, - { - "include-filter": "android.content.pm.cts" - } - ] - }, - { "name": "GtsContentTestCases", "options": [ { @@ -107,6 +93,22 @@ ] } ], + "presubmit-large": [ + { + "name": "CtsContentTestCases", + "options": [ + { + "exclude-annotation": "androidx.test.filters.FlakyTest" + }, + { + "exclude-annotation": "org.junit.Ignore" + }, + { + "include-filter": "android.content.pm.cts" + } + ] + } + ], "postsubmit": [ { "name": "CtsPermissionTestCases", diff --git a/services/core/java/com/android/server/policy/AppOpsPolicy.java b/services/core/java/com/android/server/policy/AppOpsPolicy.java index 8b4690629ec5..e5db2e4dab35 100644 --- a/services/core/java/com/android/server/policy/AppOpsPolicy.java +++ b/services/core/java/com/android/server/policy/AppOpsPolicy.java @@ -185,8 +185,13 @@ public final class AppOpsPolicy implements AppOpsManagerInternal.CheckOpsDelegat initializeActivityRecognizersTags(); - // If this device does not have telephony, restrict the phone call ops - if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) { + // If this device does not have telephony or microphone features, the TelecomService will + // not be started (which sets phone call ops to allow only its package). Therefore, phone + // call ops need to be restricted here. + PackageManager pm = mContext.getPackageManager(); + if (!pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY) + && !pm.hasSystemFeature(PackageManager.FEATURE_MICROPHONE) + && !pm.hasSystemFeature(PackageManager.FEATURE_CONNECTION_SERVICE)) { AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class); appOps.setUserRestrictionForUser(AppOpsManager.OP_PHONE_CALL_MICROPHONE, true, mToken, null, UserHandle.USER_ALL); diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java index 2029f869802e..ac650ec0f564 100644 --- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java +++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java @@ -195,12 +195,6 @@ public class KeyguardServiceWrapper implements IKeyguardService { @Override // Binder interface public void doKeyguardTimeout(Bundle options) { - int userId = mKeyguardStateMonitor.getCurrentUser(); - if (mKeyguardStateMonitor.isSecure(userId)) { - // Preemptively inform the cache that the keyguard will soon be showing, as calls to - // doKeyguardTimeout are a signal to lock the device as soon as possible. - mKeyguardStateMonitor.onShowingStateChanged(true, userId); - } try { mService.doKeyguardTimeout(options); } catch (RemoteException e) { diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java b/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java index c0aa8aeff711..e6511372d62c 100644 --- a/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java +++ b/services/core/java/com/android/server/policy/keyguard/KeyguardStateMonitor.java @@ -78,14 +78,8 @@ public class KeyguardStateMonitor extends IKeyguardStateCallback.Stub { return mTrusted; } - public int getCurrentUser() { - return mCurrentUserId; - } - @Override // Binder interface - public void onShowingStateChanged(boolean showing, int userId) { - if (userId != mCurrentUserId) return; - + public void onShowingStateChanged(boolean showing) { mIsShowing = showing; mCallback.onShowingChanged(); diff --git a/services/core/java/com/android/server/utils/TimingsTraceAndSlog.java b/services/core/java/com/android/server/utils/TimingsTraceAndSlog.java index 6bdb5cea7f9c..291deee6a8f4 100644 --- a/services/core/java/com/android/server/utils/TimingsTraceAndSlog.java +++ b/services/core/java/com/android/server/utils/TimingsTraceAndSlog.java @@ -80,7 +80,7 @@ public final class TimingsTraceAndSlog extends TimingsTraceLog { @Override public void traceBegin(@NonNull String name) { - Slog.i(mTag, name); + Slog.d(mTag, name); super.traceBegin(name); } diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java index eddb5e977fa2..15a41f6b3d2c 100644 --- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java +++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java @@ -2267,6 +2267,19 @@ public class WallpaperManagerService extends IWallpaperManager.Stub throw new IllegalArgumentException("padding must be positive: " + padding); } + int maxSize = getMaximumSizeDimension(displayId); + + final int paddingWidth = padding.left + padding.right; + final int paddingHeight = padding.top + padding.bottom; + if (paddingWidth > maxSize) { + throw new IllegalArgumentException("padding width " + paddingWidth + + " exceeds max width " + maxSize); + } + if (paddingHeight > maxSize) { + throw new IllegalArgumentException("padding height " + paddingHeight + + " exceeds max height " + maxSize); + } + final DisplayData wpdData = getDisplayDataOrCreate(displayId); if (!padding.equals(wpdData.mPadding)) { wpdData.mPadding.set(padding); diff --git a/services/core/java/com/android/server/wm/ActivityStartController.java b/services/core/java/com/android/server/wm/ActivityStartController.java index bb5d962760e7..6026ddb143c7 100644 --- a/services/core/java/com/android/server/wm/ActivityStartController.java +++ b/services/core/java/com/android/server/wm/ActivityStartController.java @@ -517,8 +517,8 @@ public class ActivityStartController { } void registerRemoteAnimationForNextActivityStart(String packageName, - RemoteAnimationAdapter adapter) { - mPendingRemoteAnimationRegistry.addPendingAnimation(packageName, adapter); + RemoteAnimationAdapter adapter, @Nullable IBinder launchCookie) { + mPendingRemoteAnimationRegistry.addPendingAnimation(packageName, adapter, launchCookie); } PendingRemoteAnimationRegistry getPendingRemoteAnimationRegistry() { diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index dde52c5e33fb..9f1f13aacc68 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -3616,7 +3616,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { @Override public void registerRemoteAnimationForNextActivityStart(String packageName, - RemoteAnimationAdapter adapter) { + RemoteAnimationAdapter adapter, IBinder launchCookie) { mAmInternal.enforceCallingPermission(CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS, "registerRemoteAnimationForNextActivityStart"); adapter.setCallingPidUid(Binder.getCallingPid(), Binder.getCallingUid()); @@ -3624,7 +3624,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { final long origId = Binder.clearCallingIdentity(); try { getActivityStartController().registerRemoteAnimationForNextActivityStart( - packageName, adapter); + packageName, adapter, launchCookie); } finally { Binder.restoreCallingIdentity(origId); } diff --git a/services/core/java/com/android/server/wm/DisplayArea.java b/services/core/java/com/android/server/wm/DisplayArea.java index 99f6fd4771b7..2130e3373e5f 100644 --- a/services/core/java/com/android/server/wm/DisplayArea.java +++ b/services/core/java/com/android/server/wm/DisplayArea.java @@ -644,7 +644,9 @@ public class DisplayArea<T extends WindowContainer> extends WindowContainer<T> { void prepareSurfaces() { mDimmer.resetDimStates(); super.prepareSurfaces(); + // Bounds need to be relative, as the dim layer is a child. getBounds(mTmpDimBoundsRect); + mTmpDimBoundsRect.offsetTo(0 /* newLeft */, 0 /* newTop */); // If SystemUI is dragging for recents, we want to reset the dim state so any dim layer // on the display level fades out. diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 42c6dd43ebce..b184d5c62008 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -4193,17 +4193,17 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp */ @VisibleForTesting SurfaceControl computeImeParent() { + if (mImeLayeringTarget != null && mImeInputTarget != null + && mImeLayeringTarget.mActivityRecord != mImeInputTarget.mActivityRecord) { + // Do not change parent if the window hasn't requested IME. + return null; + } // Attach it to app if the target is part of an app and such app is covering the entire // screen. If it's not covering the entire screen the IME might extend beyond the apps // bounds. if (shouldImeAttachedToApp()) { - if (mImeLayeringTarget.mActivityRecord != mImeInputTarget.mActivityRecord) { - // Do not change parent if the window hasn't requested IME. - return null; - } return mImeLayeringTarget.mActivityRecord.getSurfaceControl(); } - // Otherwise, we just attach it to where the display area policy put it. return mImeWindowsContainer.getParent() != null ? mImeWindowsContainer.getParent().getSurfaceControl() : null; diff --git a/services/core/java/com/android/server/wm/EmbeddedWindowController.java b/services/core/java/com/android/server/wm/EmbeddedWindowController.java index fc317a1212d5..a05769c0a48b 100644 --- a/services/core/java/com/android/server/wm/EmbeddedWindowController.java +++ b/services/core/java/com/android/server/wm/EmbeddedWindowController.java @@ -41,6 +41,8 @@ class EmbeddedWindowController { private static final String TAG = TAG_WITH_CLASS_NAME ? "EmbeddedWindowController" : TAG_WM; /* maps input token to an embedded window */ private ArrayMap<IBinder /*input token */, EmbeddedWindow> mWindows = new ArrayMap<>(); + private ArrayMap<IBinder /*focus grant token */, EmbeddedWindow> mWindowsByFocusToken = + new ArrayMap<>(); private final Object mGlobalLock; private final ActivityTaskManagerService mAtmService; @@ -59,10 +61,13 @@ class EmbeddedWindowController { void add(IBinder inputToken, EmbeddedWindow window) { try { mWindows.put(inputToken, window); + final IBinder focusToken = window.getFocusGrantToken(); + mWindowsByFocusToken.put(focusToken, window); updateProcessController(window); window.mClient.asBinder().linkToDeath(()-> { synchronized (mGlobalLock) { mWindows.remove(inputToken); + mWindowsByFocusToken.remove(focusToken); } }, 0); } catch (RemoteException e) { @@ -95,8 +100,10 @@ class EmbeddedWindowController { void remove(IWindow client) { for (int i = mWindows.size() - 1; i >= 0; i--) { - if (mWindows.valueAt(i).mClient.asBinder() == client.asBinder()) { + EmbeddedWindow ew = mWindows.valueAt(i); + if (ew.mClient.asBinder() == client.asBinder()) { mWindows.removeAt(i).onRemoved(); + mWindowsByFocusToken.remove(ew.getFocusGrantToken()); return; } } @@ -104,8 +111,10 @@ class EmbeddedWindowController { void onWindowRemoved(WindowState host) { for (int i = mWindows.size() - 1; i >= 0; i--) { - if (mWindows.valueAt(i).mHostWindowState == host) { + EmbeddedWindow ew = mWindows.valueAt(i); + if (ew.mHostWindowState == host) { mWindows.removeAt(i).onRemoved(); + mWindowsByFocusToken.remove(ew.getFocusGrantToken()); } } } @@ -114,6 +123,10 @@ class EmbeddedWindowController { return mWindows.get(inputToken); } + EmbeddedWindow getByFocusToken(IBinder focusGrantToken) { + return mWindowsByFocusToken.get(focusGrantToken); + } + void onActivityRemoved(ActivityRecord activityRecord) { for (int i = mWindows.size() - 1; i >= 0; i--) { final EmbeddedWindow window = mWindows.valueAt(i); @@ -139,6 +152,8 @@ class EmbeddedWindowController { InputChannel mInputChannel; final int mWindowType; + private IBinder mFocusGrantToken; + /** * @param session calling session to check ownership of the window * @param clientToken client token used to clean up the map if the embedding process dies @@ -153,7 +168,7 @@ class EmbeddedWindowController { */ EmbeddedWindow(Session session, WindowManagerService service, IWindow clientToken, WindowState hostWindowState, int ownerUid, int ownerPid, int windowType, - int displayId) { + int displayId, IBinder focusGrantToken) { mSession = session; mWmService = service; mClient = clientToken; @@ -164,6 +179,7 @@ class EmbeddedWindowController { mOwnerPid = ownerPid; mWindowType = windowType; mDisplayId = displayId; + mFocusGrantToken = focusGrantToken; } @Override @@ -216,5 +232,16 @@ class EmbeddedWindowController { public int getPid() { return mOwnerPid; } + + IBinder getFocusGrantToken() { + return mFocusGrantToken; + } + + IBinder getInputChannelToken() { + if (mInputChannel != null) { + return mInputChannel.getToken(); + } + return null; + } } } diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java index 10ae152c3365..5124841bcbbb 100644 --- a/services/core/java/com/android/server/wm/InsetsPolicy.java +++ b/services/core/java/com/android/server/wm/InsetsPolicy.java @@ -265,14 +265,12 @@ class InsetsPolicy { return state; } } else if (w.mActivityRecord != null && w.mActivityRecord.mImeInsetsFrozenUntilStartInput) { - // During switching tasks with gestural navigation, if the IME is attached to - // one app window on that time, even the next app window is behind the IME window, - // conceptually the window should not receive the IME insets if the next window is - // not eligible IME requester and ready to show IME on top of it. - final boolean shouldImeAttachedToApp = mDisplayContent.shouldImeAttachedToApp(); + // During switching tasks with gestural navigation, before the next IME input target + // starts the input, we should adjust and freeze the last IME visibility of the window + // in case delivering obsoleted IME insets state during transitioning. final InsetsSource originalImeSource = originalState.peekSource(ITYPE_IME); - if (shouldImeAttachedToApp && originalImeSource != null) { + if (originalImeSource != null) { final boolean imeVisibility = w.mActivityRecord.mLastImeShown || w.getRequestedVisibility(ITYPE_IME); final InsetsState state = copyState ? new InsetsState(originalState) diff --git a/services/core/java/com/android/server/wm/MirrorActiveUids.java b/services/core/java/com/android/server/wm/MirrorActiveUids.java index 4e7f1d4cca18..b9aa9599babe 100644 --- a/services/core/java/com/android/server/wm/MirrorActiveUids.java +++ b/services/core/java/com/android/server/wm/MirrorActiveUids.java @@ -19,7 +19,7 @@ package com.android.server.wm; import static android.app.ActivityManager.PROCESS_STATE_NONEXISTENT; import android.app.ActivityManager.ProcessState; -import android.util.SparseArray; +import android.util.SparseIntArray; import java.io.PrintWriter; @@ -29,15 +29,14 @@ import java.io.PrintWriter; * adjustment) or getting state from window manager (background start check). */ class MirrorActiveUids { - private final SparseArray<UidRecord> mUidStates = new SparseArray<>(); + /** Uid -> process state. */ + private final SparseIntArray mUidStates = new SparseIntArray(); + + /** Uid -> number of non-app visible windows belong to the uid. */ + private final SparseIntArray mNumNonAppVisibleWindowMap = new SparseIntArray(); synchronized void onUidActive(int uid, int procState) { - UidRecord r = mUidStates.get(uid); - if (r == null) { - r = new UidRecord(); - mUidStates.put(uid, r); - } - r.mProcState = procState; + mUidStates.put(uid, procState); } synchronized void onUidInactive(int uid) { @@ -45,22 +44,28 @@ class MirrorActiveUids { } synchronized void onUidProcStateChanged(int uid, int procState) { - final UidRecord r = mUidStates.get(uid); - if (r != null) { - r.mProcState = procState; + final int index = mUidStates.indexOfKey(uid); + if (index >= 0) { + mUidStates.setValueAt(index, procState); } } synchronized @ProcessState int getUidState(int uid) { - final UidRecord r = mUidStates.get(uid); - return r != null ? r.mProcState : PROCESS_STATE_NONEXISTENT; + return mUidStates.get(uid, PROCESS_STATE_NONEXISTENT); } /** Called when the surface of non-application (exclude toast) window is shown or hidden. */ synchronized void onNonAppSurfaceVisibilityChanged(int uid, boolean visible) { - final UidRecord r = mUidStates.get(uid); - if (r != null) { - r.mNumNonAppVisibleWindow += visible ? 1 : -1; + final int index = mNumNonAppVisibleWindowMap.indexOfKey(uid); + if (index >= 0) { + final int num = mNumNonAppVisibleWindowMap.valueAt(index) + (visible ? 1 : -1); + if (num > 0) { + mNumNonAppVisibleWindowMap.setValueAt(index, num); + } else { + mNumNonAppVisibleWindowMap.removeAt(index); + } + } else if (visible) { + mNumNonAppVisibleWindowMap.append(uid, 1); } } @@ -70,23 +75,15 @@ class MirrorActiveUids { * {@link VisibleActivityProcessTracker}. */ synchronized boolean hasNonAppVisibleWindow(int uid) { - final UidRecord r = mUidStates.get(uid); - return r != null && r.mNumNonAppVisibleWindow > 0; + return mNumNonAppVisibleWindowMap.get(uid) > 0; } synchronized void dump(PrintWriter pw, String prefix) { - pw.print(prefix + "NumNonAppVisibleWindowByUid:["); - for (int i = mUidStates.size() - 1; i >= 0; i--) { - final UidRecord r = mUidStates.valueAt(i); - if (r.mNumNonAppVisibleWindow > 0) { - pw.print(" " + mUidStates.keyAt(i) + ":" + r.mNumNonAppVisibleWindow); - } + pw.print(prefix + "NumNonAppVisibleWindowUidMap:["); + for (int i = mNumNonAppVisibleWindowMap.size() - 1; i >= 0; i--) { + pw.print(" " + mNumNonAppVisibleWindowMap.keyAt(i) + ":" + + mNumNonAppVisibleWindowMap.valueAt(i)); } pw.println("]"); } - - private static final class UidRecord { - @ProcessState int mProcState; - int mNumNonAppVisibleWindow; - } } diff --git a/services/core/java/com/android/server/wm/PendingRemoteAnimationRegistry.java b/services/core/java/com/android/server/wm/PendingRemoteAnimationRegistry.java index 3b8631ab3a8e..073bbbb8edf8 100644 --- a/services/core/java/com/android/server/wm/PendingRemoteAnimationRegistry.java +++ b/services/core/java/com/android/server/wm/PendingRemoteAnimationRegistry.java @@ -19,6 +19,7 @@ package com.android.server.wm; import android.annotation.Nullable; import android.app.ActivityOptions; import android.os.Handler; +import android.os.IBinder; import android.util.ArrayMap; import android.view.RemoteAnimationAdapter; @@ -43,8 +44,9 @@ class PendingRemoteAnimationRegistry { /** * Adds a remote animation to be run for all activity starts originating from a certain package. */ - void addPendingAnimation(String packageName, RemoteAnimationAdapter adapter) { - mEntries.put(packageName, new Entry(packageName, adapter)); + void addPendingAnimation(String packageName, RemoteAnimationAdapter adapter, + @Nullable IBinder launchCookie) { + mEntries.put(packageName, new Entry(packageName, adapter, launchCookie)); } /** @@ -62,6 +64,10 @@ class PendingRemoteAnimationRegistry { } else { options.setRemoteAnimationAdapter(entry.adapter); } + IBinder launchCookie = entry.launchCookie; + if (launchCookie != null) { + options.setLaunchCookie(launchCookie); + } mEntries.remove(callingPackage); return options; } @@ -69,10 +75,13 @@ class PendingRemoteAnimationRegistry { private class Entry { final String packageName; final RemoteAnimationAdapter adapter; + @Nullable + final IBinder launchCookie; - Entry(String packageName, RemoteAnimationAdapter adapter) { + Entry(String packageName, RemoteAnimationAdapter adapter, @Nullable IBinder launchCookie) { this.packageName = packageName; this.adapter = adapter; + this.launchCookie = launchCookie; mHandler.postDelayed(() -> { synchronized (mLock) { final Entry entry = mEntries.get(packageName); diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index 628e124877e9..9cd37b305dc6 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -3624,11 +3624,17 @@ class RootWindowContainer extends WindowContainer<DisplayContent> return new ArrayList<>(); } } else { + final RecentTasks recentTasks = mWindowManager.mAtmService.getRecentTasks(); + final int recentsComponentUid = recentTasks != null + ? recentTasks.getRecentsComponentUid() + : -1; final ArrayList<ActivityRecord> activities = new ArrayList<>(); - forAllRootTasks(rootTask -> { - if (!dumpVisibleRootTasksOnly || rootTask.shouldBeVisible(null)) { - activities.addAll(rootTask.getDumpActivitiesLocked(name)); + forAllLeafTasks(task -> { + final boolean isRecents = (task.effectiveUid == recentsComponentUid); + if (!dumpVisibleRootTasksOnly || task.shouldBeVisible(null) || isRecents) { + activities.addAll(task.getDumpActivitiesLocked(name)); } + return false; }); return activities; } diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java index d8adc512b65a..deed514464da 100644 --- a/services/core/java/com/android/server/wm/Session.java +++ b/services/core/java/com/android/server/wm/Session.java @@ -807,7 +807,7 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient { @Override public void grantInputChannel(int displayId, SurfaceControl surface, IWindow window, IBinder hostInputToken, int flags, int privateFlags, int type, - InputChannel outInputChannel) { + IBinder focusGrantToken, InputChannel outInputChannel) { if (hostInputToken == null && !mCanAddInternalSystemWindow) { // Callers without INTERNAL_SYSTEM_WINDOW permission cannot grant input channel to // embedded windows without providing a host window input token @@ -823,7 +823,7 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient { try { mService.grantInputChannel(this, mUid, mPid, displayId, surface, window, hostInputToken, flags, mCanAddInternalSystemWindow ? privateFlags : 0, - mCanAddInternalSystemWindow ? type : 0, outInputChannel); + mCanAddInternalSystemWindow ? type : 0, focusGrantToken, outInputChannel); } finally { Binder.restoreCallingIdentity(identity); } diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java index db6d3ce69cc8..15a294ee7484 100644 --- a/services/core/java/com/android/server/wm/TaskDisplayArea.java +++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java @@ -971,9 +971,19 @@ final class TaskDisplayArea extends DisplayArea<WindowContainer> { } void setBackgroundColor(@ColorInt int colorInt) { + setBackgroundColor(colorInt, false /* restore */); + } + + void setBackgroundColor(@ColorInt int colorInt, boolean restore) { mBackgroundColor = colorInt; Color color = Color.valueOf(colorInt); - mColorLayerCounter++; + + // We don't want to increment the mColorLayerCounter if we are restoring the background + // color after a surface migration because in that case the mColorLayerCounter already + // accounts for setting that background color. + if (!restore) { + mColorLayerCounter++; + } // Only apply the background color if the TDA is actually attached and has a valid surface // to set the background color on. We still want to keep track of the background color state @@ -1002,7 +1012,7 @@ final class TaskDisplayArea extends DisplayArea<WindowContainer> { super.migrateToNewSurfaceControl(t); if (mColorLayerCounter > 0) { - setBackgroundColor(mBackgroundColor); + setBackgroundColor(mBackgroundColor, true /* restore */); } // As TaskDisplayArea is getting a new surface, reparent and reorder the child surfaces. diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java index 24b66ca3ac9c..ae7e96fab1fe 100644 --- a/services/core/java/com/android/server/wm/TaskFragment.java +++ b/services/core/java/com/android/server/wm/TaskFragment.java @@ -822,11 +822,17 @@ class TaskFragment extends WindowContainer<WindowContainer> { if (!adjacentTaskFragments.isEmpty() && !gotTranslucentAdjacent) { // The z-order of this TaskFragment is in middle of two adjacent TaskFragments // and it cannot be visible if the TaskFragment on top is not translucent and - // is fully occluding this one. + // is occluding this one. + mTmpRect.set(getBounds()); for (int j = adjacentTaskFragments.size() - 1; j >= 0; --j) { final TaskFragment taskFragment = adjacentTaskFragments.get(j); - if (!taskFragment.isTranslucent(starting) - && taskFragment.getBounds().contains(this.getBounds())) { + final TaskFragment adjacentTaskFragment = + taskFragment.mAdjacentTaskFragment; + if (adjacentTaskFragment == this) { + continue; + } + if (mTmpRect.intersect(taskFragment.getBounds()) + || mTmpRect.intersect(adjacentTaskFragment.getBounds())) { return TASK_FRAGMENT_VISIBILITY_INVISIBLE; } } diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java index 4b2aa0f76272..b61e711d75f5 100644 --- a/services/core/java/com/android/server/wm/WallpaperController.java +++ b/services/core/java/com/android/server/wm/WallpaperController.java @@ -202,8 +202,11 @@ class WallpaperController { "Win " + w + ": token animating, looking behind."); } mFindResults.setIsWallpaperTargetForLetterbox(w.hasWallpaperForLetterboxBackground()); - // Found a target! End search. - return true; + // While the keyguard is going away, both notification shade and a normal activity such + // as a launcher can satisfy criteria for a wallpaper target. In this case, we should + // chose the normal activity, otherwise wallpaper becomes invisible when a new animation + // starts before the keyguard going away animation finishes. + return w.mActivityRecord != null; } return false; }; diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java index 5af9147cd56f..c63780c3dd57 100644 --- a/services/core/java/com/android/server/wm/WindowContainer.java +++ b/services/core/java/com/android/server/wm/WindowContainer.java @@ -70,6 +70,7 @@ import android.annotation.Nullable; import android.content.Context; import android.content.pm.ActivityInfo; import android.content.res.Configuration; +import android.graphics.Color; import android.graphics.Point; import android.graphics.Rect; import android.os.Debug; @@ -3563,7 +3564,7 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< private void setTaskBackgroundColor(@ColorInt int backgroundColor) { TaskDisplayArea taskDisplayArea = getTaskDisplayArea(); - if (taskDisplayArea != null) { + if (taskDisplayArea != null && backgroundColor != Color.TRANSPARENT) { taskDisplayArea.setBackgroundColor(backgroundColor); // Atomic counter to make sure the clearColor callback is only called one. diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 8839fbac26a1..1820159d6458 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -2676,6 +2676,10 @@ public class WindowManagerService extends IWindowManager.Stub void finishDrawingWindow(Session session, IWindow client, @Nullable SurfaceControl.Transaction postDrawTransaction) { + if (postDrawTransaction != null) { + postDrawTransaction.sanitize(); + } + final long origId = Binder.clearCallingIdentity(); try { synchronized (mGlobalLock) { @@ -8374,7 +8378,8 @@ public class WindowManagerService extends IWindowManager.Stub */ void grantInputChannel(Session session, int callingUid, int callingPid, int displayId, SurfaceControl surface, IWindow window, IBinder hostInputToken, - int flags, int privateFlags, int type, InputChannel outInputChannel) { + int flags, int privateFlags, int type, IBinder focusGrantToken, + InputChannel outInputChannel) { final InputApplicationHandle applicationHandle; final String name; final InputChannel clientChannel; @@ -8382,7 +8387,7 @@ public class WindowManagerService extends IWindowManager.Stub EmbeddedWindowController.EmbeddedWindow win = new EmbeddedWindowController.EmbeddedWindow(session, this, window, mInputToWindowMap.get(hostInputToken), callingUid, callingPid, type, - displayId); + displayId, focusGrantToken); clientChannel = win.openInputChannel(); mEmbeddedWindowController.add(clientChannel.getToken(), win); applicationHandle = win.getApplicationHandle(); @@ -8602,10 +8607,10 @@ public class WindowManagerService extends IWindowManager.Stub } } - void grantEmbeddedWindowFocus(Session session, IBinder inputToken, boolean grantFocus) { + void grantEmbeddedWindowFocus(Session session, IBinder focusToken, boolean grantFocus) { synchronized (mGlobalLock) { final EmbeddedWindowController.EmbeddedWindow embeddedWindow = - mEmbeddedWindowController.get(inputToken); + mEmbeddedWindowController.getByFocusToken(focusToken); if (embeddedWindow == null) { Slog.e(TAG, "Embedded window not found"); return; @@ -8614,6 +8619,11 @@ public class WindowManagerService extends IWindowManager.Stub Slog.e(TAG, "Window not in session:" + session); return; } + IBinder inputToken = embeddedWindow.getInputChannelToken(); + if (inputToken == null) { + Slog.e(TAG, "Focus token found but input channel token not found"); + return; + } SurfaceControl.Transaction t = mTransactionFactory.get(); final int displayId = embeddedWindow.mDisplayId; if (grantFocus) { @@ -8643,7 +8653,7 @@ public class WindowManagerService extends IWindowManager.Stub } } - void grantEmbeddedWindowFocus(Session session, IWindow callingWindow, IBinder targetInputToken, + void grantEmbeddedWindowFocus(Session session, IWindow callingWindow, IBinder targetFocusToken, boolean grantFocus) { synchronized (mGlobalLock) { final WindowState hostWindow = @@ -8657,7 +8667,7 @@ public class WindowManagerService extends IWindowManager.Stub return; } final EmbeddedWindowController.EmbeddedWindow embeddedWindow = - mEmbeddedWindowController.get(targetInputToken); + mEmbeddedWindowController.getByFocusToken(targetFocusToken); if (embeddedWindow == null) { Slog.e(TAG, "Embedded window not found"); return; @@ -8668,7 +8678,7 @@ public class WindowManagerService extends IWindowManager.Stub } SurfaceControl.Transaction t = mTransactionFactory.get(); if (grantFocus) { - t.requestFocusTransfer(targetInputToken, embeddedWindow.toString(), + t.requestFocusTransfer(embeddedWindow.getInputChannelToken(), embeddedWindow.toString(), hostWindow.mInputChannel.getToken(), hostWindow.getName(), hostWindow.getDisplayId()).apply(); @@ -8677,7 +8687,7 @@ public class WindowManagerService extends IWindowManager.Stub "reason=grantEmbeddedWindowFocus(true)"); } else { t.requestFocusTransfer(hostWindow.mInputChannel.getToken(), hostWindow.getName(), - targetInputToken, + embeddedWindow.getInputChannelToken(), embeddedWindow.toString(), hostWindow.getDisplayId()).apply(); EventLog.writeEvent(LOGTAG_INPUT_FOCUS, diff --git a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java index a94fd074ff2e..2d8410bd12d2 100644 --- a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java +++ b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java @@ -513,9 +513,14 @@ public class WindowManagerShellCommand extends ShellCommand { try (ZipOutputStream out = new ZipOutputStream(getRawOutputStream())) { ArrayList<Pair<String, ByteTransferPipe>> requestList = new ArrayList<>(); synchronized (mInternal.mGlobalLock) { + final RecentTasks recentTasks = mInternal.mAtmService.getRecentTasks(); + final int recentsComponentUid = recentTasks != null + ? recentTasks.getRecentsComponentUid() + : -1; // Request dump from all windows parallelly before writing to disk. mInternal.mRoot.forAllWindows(w -> { - if (w.isVisible()) { + final boolean isRecents = (w.mSession.mUid == recentsComponentUid); + if (w.isVisible() || isRecents) { ByteTransferPipe pipe = null; try { pipe = new ByteTransferPipe(); diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp index a87b513491f6..532590ec1ac7 100644 --- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp +++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp @@ -1115,17 +1115,18 @@ jobject GnssAntennaInfoCallback::translateSingleGnssAntennaInfo( env->NewObject(class_gnssAntennaInfoBuilder, method_gnssAntennaInfoBuilderCtor); // Set fields - env->CallObjectMethod(gnssAntennaInfoBuilderObject, - method_gnssAntennaInfoBuilderSetCarrierFrequencyMHz, - gnssAntennaInfo.carrierFrequencyMHz); - env->CallObjectMethod(gnssAntennaInfoBuilderObject, - method_gnssAntennaInfoBuilderSetPhaseCenterOffset, phaseCenterOffset); - env->CallObjectMethod(gnssAntennaInfoBuilderObject, - method_gnssAntennaInfoBuilderSetPhaseCenterVariationCorrections, - phaseCenterVariationCorrections); - env->CallObjectMethod(gnssAntennaInfoBuilderObject, - method_gnssAntennaInfoBuilderSetSignalGainCorrections, - signalGainCorrections); + callObjectMethodIgnoringResult(env, gnssAntennaInfoBuilderObject, + method_gnssAntennaInfoBuilderSetCarrierFrequencyMHz, + gnssAntennaInfo.carrierFrequencyMHz); + callObjectMethodIgnoringResult(env, gnssAntennaInfoBuilderObject, + method_gnssAntennaInfoBuilderSetPhaseCenterOffset, + phaseCenterOffset); + callObjectMethodIgnoringResult(env, gnssAntennaInfoBuilderObject, + method_gnssAntennaInfoBuilderSetPhaseCenterVariationCorrections, + phaseCenterVariationCorrections); + callObjectMethodIgnoringResult(env, gnssAntennaInfoBuilderObject, + method_gnssAntennaInfoBuilderSetSignalGainCorrections, + signalGainCorrections); // build jobject gnssAntennaInfoObject = @@ -2707,7 +2708,7 @@ static SingleSatCorrection_V1_0 getSingleSatCorrection_1_0_withoutConstellation( jfloat eplMeters = env->CallFloatMethod(singleSatCorrectionObj, method_correctionSatEpl); jfloat eplUncMeters = env->CallFloatMethod(singleSatCorrectionObj, method_correctionSatEplUnc); uint16_t corrFlags = static_cast<uint16_t>(correctionFlags); - jobject reflectingPlaneObj; + jobject reflectingPlaneObj = nullptr; bool has_ref_plane = (corrFlags & GnssSingleSatCorrectionFlags::HAS_REFLECTING_PLANE) != 0; if (has_ref_plane) { reflectingPlaneObj = @@ -2731,6 +2732,7 @@ static SingleSatCorrection_V1_0 getSingleSatCorrection_1_0_withoutConstellation( .azimuthDegrees = azimuthDegreeRefPlane, }; } + env->DeleteLocalRef(reflectingPlaneObj); SingleSatCorrection_V1_0 singleSatCorrection = { .singleSatCorrectionFlags = corrFlags, @@ -2762,6 +2764,7 @@ static void getSingleSatCorrectionList_1_1(JNIEnv* env, jobject singleSatCorrect }; list[i] = singleSatCorrection_1_1; + env->DeleteLocalRef(singleSatCorrectionObj); } } @@ -2779,6 +2782,7 @@ static void getSingleSatCorrectionList_1_0(JNIEnv* env, jobject singleSatCorrect singleSatCorrection.constellation = static_cast<GnssConstellationType_V1_0>(constType), list[i] = singleSatCorrection; + env->DeleteLocalRef(singleSatCorrectionObj); } } @@ -2849,6 +2853,7 @@ static jboolean android_location_gnss_hal_GnssNative_inject_measurement_correcti hidl_vec<SingleSatCorrection_V1_0> list(len); getSingleSatCorrectionList_1_0(env, singleSatCorrectionList, list); + env->DeleteLocalRef(singleSatCorrectionList); measurementCorrections_1_0.satCorrections = list; auto result = gnssCorrectionsIface_V1_0->setCorrections(measurementCorrections_1_0); diff --git a/services/core/jni/gnss/GnssMeasurementCallback.cpp b/services/core/jni/gnss/GnssMeasurementCallback.cpp index 8c6c673fb5b2..de99dcecf2dc 100644 --- a/services/core/jni/gnss/GnssMeasurementCallback.cpp +++ b/services/core/jni/gnss/GnssMeasurementCallback.cpp @@ -335,24 +335,24 @@ void GnssMeasurementCallbackAidl::translateSingleGnssMeasurement(JNIEnv* env, satellitePvt.satClockInfo.satHardwareCodeBiasMeters, satellitePvt.satClockInfo.satTimeCorrectionMeters, satellitePvt.satClockInfo.satClkDriftMps); - env->CallObjectMethod(satellitePvtBuilderObject, - method_satellitePvtBuilderSetPositionEcef, positionEcef); - env->CallObjectMethod(satellitePvtBuilderObject, - method_satellitePvtBuilderSetVelocityEcef, velocityEcef); - env->CallObjectMethod(satellitePvtBuilderObject, method_satellitePvtBuilderSetClockInfo, - clockInfo); + callObjectMethodIgnoringResult(env, satellitePvtBuilderObject, + method_satellitePvtBuilderSetPositionEcef, positionEcef); + callObjectMethodIgnoringResult(env, satellitePvtBuilderObject, + method_satellitePvtBuilderSetVelocityEcef, velocityEcef); + callObjectMethodIgnoringResult(env, satellitePvtBuilderObject, + method_satellitePvtBuilderSetClockInfo, clockInfo); } if (satFlags & SatellitePvt::HAS_IONO) { - env->CallObjectMethod(satellitePvtBuilderObject, - method_satellitePvtBuilderSetIonoDelayMeters, - satellitePvt.ionoDelayMeters); + callObjectMethodIgnoringResult(env, satellitePvtBuilderObject, + method_satellitePvtBuilderSetIonoDelayMeters, + satellitePvt.ionoDelayMeters); } if (satFlags & SatellitePvt::HAS_TROPO) { - env->CallObjectMethod(satellitePvtBuilderObject, - method_satellitePvtBuilderSetTropoDelayMeters, - satellitePvt.tropoDelayMeters); + callObjectMethodIgnoringResult(env, satellitePvtBuilderObject, + method_satellitePvtBuilderSetTropoDelayMeters, + satellitePvt.tropoDelayMeters); } jobject satellitePvtObject = @@ -380,17 +380,19 @@ void GnssMeasurementCallbackAidl::translateSingleGnssMeasurement(JNIEnv* env, jobject correlationVectorBuilderObject = env->NewObject(class_correlationVectorBuilder, method_correlationVectorBuilderCtor); - env->CallObjectMethod(correlationVectorBuilderObject, - method_correlationVectorBuilderSetMagnitude, magnitudeArray); - env->CallObjectMethod(correlationVectorBuilderObject, - method_correlationVectorBuilderSetFrequencyOffsetMetersPerSecond, - correlationVector.frequencyOffsetMps); - env->CallObjectMethod(correlationVectorBuilderObject, - method_correlationVectorBuilderSetSamplingStartMeters, - correlationVector.samplingStartM); - env->CallObjectMethod(correlationVectorBuilderObject, - method_correlationVectorBuilderSetSamplingWidthMeters, - correlationVector.samplingWidthM); + callObjectMethodIgnoringResult(env, correlationVectorBuilderObject, + method_correlationVectorBuilderSetMagnitude, + magnitudeArray); + callObjectMethodIgnoringResult( + env, correlationVectorBuilderObject, + method_correlationVectorBuilderSetFrequencyOffsetMetersPerSecond, + correlationVector.frequencyOffsetMps); + callObjectMethodIgnoringResult(env, correlationVectorBuilderObject, + method_correlationVectorBuilderSetSamplingStartMeters, + correlationVector.samplingStartM); + callObjectMethodIgnoringResult(env, correlationVectorBuilderObject, + method_correlationVectorBuilderSetSamplingWidthMeters, + correlationVector.samplingWidthM); jobject correlationVectorObject = env->CallObjectMethod(correlationVectorBuilderObject, method_correlationVectorBuilderBuild); diff --git a/services/core/jni/gnss/Utils.cpp b/services/core/jni/gnss/Utils.cpp index 20e14a919fce..08a08882ab87 100644 --- a/services/core/jni/gnss/Utils.cpp +++ b/services/core/jni/gnss/Utils.cpp @@ -82,6 +82,13 @@ void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName) { } } +void callObjectMethodIgnoringResult(JNIEnv* env, jobject obj, jmethodID mid, ...) { + va_list args; + va_start(args, mid); + env->DeleteLocalRef(env->CallObjectMethodV(obj, mid, args)); + va_end(args); +} + JavaObject::JavaObject(JNIEnv* env, jclass clazz, jmethodID defaultCtor) : env_(env), clazz_(clazz) { object_ = env_->NewObject(clazz_, defaultCtor); diff --git a/services/core/jni/gnss/Utils.h b/services/core/jni/gnss/Utils.h index 0938a1b30dc8..52e2b2097df7 100644 --- a/services/core/jni/gnss/Utils.h +++ b/services/core/jni/gnss/Utils.h @@ -48,6 +48,8 @@ jboolean checkAidlStatus(const android::binder::Status& status, const char* erro void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName); +void callObjectMethodIgnoringResult(JNIEnv* env, jobject obj, jmethodID mid, ...); + template <class T> void logHidlError(hardware::Return<T>& result, const char* errorMessage) { ALOGE("%s HIDL transport error: %s", errorMessage, result.description().c_str()); diff --git a/services/core/xsd/display-device-config/display-device-config.xsd b/services/core/xsd/display-device-config/display-device-config.xsd index 429edf175be4..a98483c6d03b 100644 --- a/services/core/xsd/display-device-config/display-device-config.xsd +++ b/services/core/xsd/display-device-config/display-device-config.xsd @@ -34,7 +34,8 @@ <xs:annotation name="nonnull"/> <xs:annotation name="final"/> </xs:element> - <xs:element type="highBrightnessMode" name="highBrightnessMode" minOccurs="0" maxOccurs="1"/> + <xs:element type="highBrightnessMode" name="highBrightnessMode" minOccurs="0" + maxOccurs="1"/> <xs:element type="displayQuirks" name="quirks" minOccurs="0" maxOccurs="1" /> <xs:element type="nonNegativeDecimal" name="screenBrightnessRampFastDecrease"> <xs:annotation name="final"/> @@ -54,6 +55,19 @@ <xs:element type="sensorDetails" name="proxSensor"> <xs:annotation name="final"/> </xs:element> + + <!-- Set of thresholds that dictate the change needed for screen brightness + adaptations --> + <xs:element type="thresholds" name="displayBrightnessChangeThresholds"> + <xs:annotation name="nonnull"/> + <xs:annotation name="final"/> + </xs:element> + <!-- Set of thresholds that dictate the change needed for ambient brightness + adaptations --> + <xs:element type="thresholds" name="ambientBrightnessChangeThresholds"> + <xs:annotation name="nonnull"/> + <xs:annotation name="final"/> + </xs:element> </xs:sequence> </xs:complexType> </xs:element> @@ -68,7 +82,8 @@ <xs:complexType name="highBrightnessMode"> <xs:all> - <xs:element name="transitionPoint" type="nonNegativeDecimal" minOccurs="1" maxOccurs="1"> + <xs:element name="transitionPoint" type="nonNegativeDecimal" minOccurs="1" + maxOccurs="1"> <xs:annotation name="nonnull"/> <xs:annotation name="final"/> </xs:element> @@ -97,7 +112,8 @@ <xs:complexType name="hbmTiming"> <xs:all> - <xs:element name="timeWindowSecs" type="xs:nonNegativeInteger" minOccurs="1" maxOccurs="1"> + <xs:element name="timeWindowSecs" type="xs:nonNegativeInteger" minOccurs="1" + maxOccurs="1"> <xs:annotation name="nonnull"/> <xs:annotation name="final"/> </xs:element> @@ -181,5 +197,31 @@ </xs:sequence> </xs:complexType> + <!-- Thresholds for brightness changes. --> + <xs:complexType name="thresholds"> + <xs:sequence> + <!-- Brightening thresholds. --> + <xs:element name="brighteningThresholds" type="brightnessThresholds" minOccurs="0" + maxOccurs="1" > + <xs:annotation name="nonnull"/> + <xs:annotation name="final"/> + </xs:element> + <!-- Darkening thresholds. --> + <xs:element name="darkeningThresholds" type="brightnessThresholds" minOccurs="0" + maxOccurs="1" > + <xs:annotation name="nonnull"/> + <xs:annotation name="final"/> + </xs:element> + </xs:sequence> + </xs:complexType> + + <!-- Brightening and darkening minimum change thresholds. --> + <xs:complexType name="brightnessThresholds"> + <!-- Minimum brightness change needed. --> + <xs:element name="minimum" type="nonNegativeDecimal" minOccurs="0" maxOccurs="1" > + <xs:annotation name="nonnull"/> + <xs:annotation name="final"/> + </xs:element> + </xs:complexType> </xs:schema> diff --git a/services/core/xsd/display-device-config/schema/current.txt b/services/core/xsd/display-device-config/schema/current.txt index ad186026d30c..df468d41fdef 100644 --- a/services/core/xsd/display-device-config/schema/current.txt +++ b/services/core/xsd/display-device-config/schema/current.txt @@ -1,8 +1,16 @@ // Signature format: 2.0 package com.android.server.display.config { + public class BrightnessThresholds { + ctor public BrightnessThresholds(); + method @NonNull public final java.math.BigDecimal getMinimum(); + method public final void setMinimum(@NonNull java.math.BigDecimal); + } + public class DisplayConfiguration { ctor public DisplayConfiguration(); + method @NonNull public final com.android.server.display.config.Thresholds getAmbientBrightnessChangeThresholds(); + method @NonNull public final com.android.server.display.config.Thresholds getDisplayBrightnessChangeThresholds(); method public com.android.server.display.config.HighBrightnessMode getHighBrightnessMode(); method public final com.android.server.display.config.SensorDetails getLightSensor(); method public final com.android.server.display.config.SensorDetails getProxSensor(); @@ -13,6 +21,8 @@ package com.android.server.display.config { method public final java.math.BigDecimal getScreenBrightnessRampFastIncrease(); method public final java.math.BigDecimal getScreenBrightnessRampSlowDecrease(); method public final java.math.BigDecimal getScreenBrightnessRampSlowIncrease(); + method public final void setAmbientBrightnessChangeThresholds(@NonNull com.android.server.display.config.Thresholds); + method public final void setDisplayBrightnessChangeThresholds(@NonNull com.android.server.display.config.Thresholds); method public void setHighBrightnessMode(com.android.server.display.config.HighBrightnessMode); method public final void setLightSensor(com.android.server.display.config.SensorDetails); method public final void setProxSensor(com.android.server.display.config.SensorDetails); @@ -100,6 +110,14 @@ package com.android.server.display.config { enum_constant public static final com.android.server.display.config.ThermalStatus shutdown; } + public class Thresholds { + ctor public Thresholds(); + method @NonNull public final com.android.server.display.config.BrightnessThresholds getBrighteningThresholds(); + method @NonNull public final com.android.server.display.config.BrightnessThresholds getDarkeningThresholds(); + method public final void setBrighteningThresholds(@NonNull com.android.server.display.config.BrightnessThresholds); + method public final void setDarkeningThresholds(@NonNull com.android.server.display.config.BrightnessThresholds); + } + public class XmlParser { ctor public XmlParser(); method public static com.android.server.display.config.DisplayConfiguration read(java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException; diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java index 55ab8c3b1af6..10ff2447948b 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java @@ -15,6 +15,7 @@ */ package com.android.server.devicepolicy; +import android.accounts.Account; import android.annotation.NonNull; import android.annotation.UserIdInt; import android.app.admin.DevicePolicySafetyChecker; @@ -58,6 +59,7 @@ abstract class BaseIDevicePolicyManager extends IDevicePolicyManager.Stub { * @see {@link SystemService#onUserUnlocking} */ abstract void handleUnlockUser(int userId); + /** * To be called by {@link DevicePolicyManagerService#Lifecycle} after a user is being unlocked. * @@ -133,6 +135,11 @@ abstract class BaseIDevicePolicyManager extends IDevicePolicyManager.Stub { return null; } + public void finalizeWorkProfileProvisioning( + UserHandle managedProfileUser, Account migratedAccount) { + + } + public void provisionFullyManagedDevice( FullyManagedDeviceProvisioningParams provisioningParams, String callerPackage) { } diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java index 26c442dc1f47..e18e0020407f 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java @@ -23,6 +23,7 @@ import android.app.admin.DevicePolicyManager; import android.content.ComponentName; import android.os.FileUtils; import android.os.PersistableBundle; +import android.os.UserHandle; import android.util.ArrayMap; import android.util.ArraySet; import android.util.DebugUtils; @@ -83,7 +84,7 @@ class DevicePolicyData { private static final String ATTR_NEW_USER_DISCLAIMER = "new-user-disclaimer"; // Values of ATTR_NEW_USER_DISCLAIMER - static final String NEW_USER_DISCLAIMER_SHOWN = "shown"; + static final String NEW_USER_DISCLAIMER_ACKNOWLEDGED = "acked"; static final String NEW_USER_DISCLAIMER_NOT_NEEDED = "not_needed"; static final String NEW_USER_DISCLAIMER_NEEDED = "needed"; @@ -613,6 +614,28 @@ class DevicePolicyData { } } + boolean isNewUserDisclaimerAcknowledged() { + if (mNewUserDisclaimer == null) { + if (mUserId == UserHandle.USER_SYSTEM) { + return true; + } + Slogf.w(TAG, "isNewUserDisclaimerAcknowledged(%d): mNewUserDisclaimer is null", + mUserId); + return false; + } + switch (mNewUserDisclaimer) { + case NEW_USER_DISCLAIMER_ACKNOWLEDGED: + case NEW_USER_DISCLAIMER_NOT_NEEDED: + return true; + case NEW_USER_DISCLAIMER_NEEDED: + return false; + default: + Slogf.w(TAG, "isNewUserDisclaimerAcknowledged(%d): invalid value %d", mUserId, + mNewUserDisclaimer); + return false; + } + } + void dump(IndentingPrintWriter pw) { pw.println(); pw.println("Enabled Device Admins (User " + mUserId + ", provisioningState: " diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 5e95a785a3e5..80c41f3300d5 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -26,6 +26,7 @@ import static android.app.AppOpsManager.MODE_DEFAULT; import static android.app.admin.DeviceAdminReceiver.ACTION_COMPLIANCE_ACKNOWLEDGEMENT_REQUIRED; import static android.app.admin.DeviceAdminReceiver.EXTRA_TRANSFER_OWNERSHIP_ADMIN_EXTRAS_BUNDLE; import static android.app.admin.DevicePolicyManager.ACTION_CHECK_POLICY_COMPLIANCE; +import static android.app.admin.DevicePolicyManager.ACTION_MANAGED_PROFILE_PROVISIONED; import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE; import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE; import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_USER; @@ -56,6 +57,7 @@ import static android.app.admin.DevicePolicyManager.DELEGATION_PACKAGE_ACCESS; import static android.app.admin.DevicePolicyManager.DELEGATION_PERMISSION_GRANT; import static android.app.admin.DevicePolicyManager.DELEGATION_SECURITY_LOGGING; import static android.app.admin.DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE_PER_USER; +import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE; import static android.app.admin.DevicePolicyManager.ID_TYPE_BASE_INFO; import static android.app.admin.DevicePolicyManager.ID_TYPE_IMEI; import static android.app.admin.DevicePolicyManager.ID_TYPE_INDIVIDUAL_ATTESTATION; @@ -5876,6 +5878,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { * (1.1) The caller is the Device Owner * (1.2) The caller is another app in the same user as the device owner, AND * The caller is the delegated certificate installer. + * (1.3) The caller is a Profile Owner and the calling user is affiliated. * (2) The user has a profile owner, AND: * (2.1) The profile owner has been granted access to Device IDs and one of the following * holds: @@ -5901,12 +5904,14 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { * If the caller is from the work profile, then it must be the PO or the delegate, and * it must have the right permission to access device identifiers. */ - if (hasProfileOwner(caller.getUserId())) { + int callerUserId = caller.getUserId(); + if (hasProfileOwner(callerUserId)) { // Make sure that the caller is the profile owner or delegate. Preconditions.checkCallAuthorization(canInstallCertificates(caller)); - // Verify that the managed profile is on an organization-owned device and as such - // the profile owner can access Device IDs. - if (isProfileOwnerOfOrganizationOwnedDevice(caller.getUserId())) { + // Verify that the managed profile is on an organization-owned device (or is affiliated + // with the device owner user) and as such the profile owner can access Device IDs. + if (isProfileOwnerOfOrganizationOwnedDevice(callerUserId) + || isUserAffiliatedWithDevice(callerUserId)) { return; } throw new SecurityException( @@ -8435,20 +8440,23 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { admin.getPackageName(), userId, "set-device-owner"); Slogf.i(LOG_TAG, "Device owner set: " + admin + " on user " + userId); + } - if (setProfileOwnerOnCurrentUserIfNecessary - && mInjector.userManagerIsHeadlessSystemUserMode()) { - int currentForegroundUser = getCurrentForegroundUserId(); - Slogf.i(LOG_TAG, "setDeviceOwner(): setting " + admin - + " as profile owner on user " + currentForegroundUser); - // Sets profile owner on current foreground user since - // the human user will complete the DO setup workflow from there. - manageUserUnchecked(/* deviceOwner= */ admin, /* profileOwner= */ admin, - /* managedUser= */ currentForegroundUser, /* adminExtras= */ null, - /* showDisclaimer= */ false); + if (setProfileOwnerOnCurrentUserIfNecessary + && mInjector.userManagerIsHeadlessSystemUserMode()) { + int currentForegroundUser; + synchronized (getLockObject()) { + currentForegroundUser = getCurrentForegroundUserId(); } - return true; + Slogf.i(LOG_TAG, "setDeviceOwner(): setting " + admin + + " as profile owner on user " + currentForegroundUser); + // Sets profile owner on current foreground user since + // the human user will complete the DO setup workflow from there. + manageUserUnchecked(/* deviceOwner= */ admin, /* profileOwner= */ admin, + /* managedUser= */ currentForegroundUser, /* adminExtras= */ null, + /* showDisclaimer= */ false); } + return true; } @Override @@ -9278,10 +9286,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return false; } - // Allow access to the device owner or delegate cert installer. + // Allow access to the device owner or delegate cert installer or profile owner of an + // affiliated user ComponentName deviceOwner = getDeviceOwnerComponent(true); if (deviceOwner != null && (deviceOwner.getPackageName().equals(packageName) - || isCallerDelegate(packageName, uid, DELEGATION_CERT_INSTALL))) { + || isCallerDelegate(packageName, uid, DELEGATION_CERT_INSTALL))) { return true; } final int userId = UserHandle.getUserId(uid); @@ -9291,7 +9300,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { final boolean isCallerProfileOwnerOrDelegate = profileOwner != null && (profileOwner.getPackageName().equals(packageName) || isCallerDelegate(packageName, uid, DELEGATION_CERT_INSTALL)); - if (isCallerProfileOwnerOrDelegate && isProfileOwnerOfOrganizationOwnedDevice(userId)) { + if (isCallerProfileOwnerOrDelegate && (isProfileOwnerOfOrganizationOwnedDevice(userId) + || isUserAffiliatedWithDevice(userId))) { return true; } @@ -10535,6 +10545,35 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } @Override + public void finalizeWorkProfileProvisioning(UserHandle managedProfileUser, + Account migratedAccount) { + Preconditions.checkCallAuthorization( + hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS)); + + if (!isManagedProfile(managedProfileUser.getIdentifier())) { + throw new IllegalStateException("Given user is not a managed profile"); + } + ComponentName profileOwnerComponent = + mOwners.getProfileOwnerComponent(managedProfileUser.getIdentifier()); + if (profileOwnerComponent == null) { + throw new IllegalStateException("There is no profile owner on the given profile"); + } + Intent primaryProfileSuccessIntent = new Intent(ACTION_MANAGED_PROFILE_PROVISIONED); + primaryProfileSuccessIntent.setPackage(profileOwnerComponent.getPackageName()); + primaryProfileSuccessIntent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES + | Intent.FLAG_RECEIVER_FOREGROUND); + primaryProfileSuccessIntent.putExtra(Intent.EXTRA_USER, managedProfileUser); + + if (migratedAccount != null) { + primaryProfileSuccessIntent.putExtra(EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE, + migratedAccount); + } + + mContext.sendBroadcastAsUser(primaryProfileSuccessIntent, + UserHandle.of(getProfileParentId(managedProfileUser.getIdentifier()))); + } + + @Override public UserHandle createAndManageUser(ComponentName admin, String name, ComponentName profileOwner, PersistableBundle adminExtras, int flags) { Objects.requireNonNull(admin, "admin is null"); @@ -10737,12 +10776,13 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } @Override - public void resetNewUserDisclaimer() { + public void acknowledgeNewUserDisclaimer() { CallerIdentity callerIdentity = getCallerIdentity(); - canManageUsers(callerIdentity); + Preconditions.checkCallAuthorization(canManageUsers(callerIdentity) + || hasCallingOrSelfPermission(permission.INTERACT_ACROSS_USERS)); setShowNewUserDisclaimer(callerIdentity.getUserId(), - DevicePolicyData.NEW_USER_DISCLAIMER_SHOWN); + DevicePolicyData.NEW_USER_DISCLAIMER_ACKNOWLEDGED); } private void setShowNewUserDisclaimer(@UserIdInt int userId, String value) { @@ -10775,6 +10815,18 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } @Override + public boolean isNewUserDisclaimerAcknowledged() { + CallerIdentity callerIdentity = getCallerIdentity(); + Preconditions.checkCallAuthorization(canManageUsers(callerIdentity) + || hasCallingOrSelfPermission(permission.INTERACT_ACROSS_USERS)); + int userId = callerIdentity.getUserId(); + synchronized (getLockObject()) { + DevicePolicyData policyData = getUserData(userId); + return policyData.isNewUserDisclaimerAcknowledged(); + } + } + + @Override public boolean removeUser(ComponentName who, UserHandle userHandle) { Objects.requireNonNull(who, "ComponentName is null"); Objects.requireNonNull(userHandle, "UserHandle is null"); @@ -13162,12 +13214,17 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { /** * @param restriction The restriction enforced by admin. It could be any user restriction or - * policy like {@link DevicePolicyManager#POLICY_DISABLE_CAMERA} and - * {@link DevicePolicyManager#POLICY_DISABLE_SCREEN_CAPTURE}. + * policy like {@link DevicePolicyManager#POLICY_DISABLE_CAMERA}, + * {@link DevicePolicyManager#POLICY_DISABLE_SCREEN_CAPTURE} and {@link + * DevicePolicyManager#POLICY_SUSPEND_PACKAGES}. */ private Bundle getEnforcingAdminAndUserDetailsInternal(int userId, String restriction) { Bundle result = null; - if (restriction == null) { + + // For POLICY_SUSPEND_PACKAGES return PO or DO to keep the behavior same as + // before the bug fix for b/192245204. + if (restriction == null || DevicePolicyManager.POLICY_SUSPEND_PACKAGES.equals( + restriction)) { ComponentName profileOwner = mOwners.getProfileOwnerComponent(userId); if (profileOwner != null) { result = new Bundle(); @@ -14562,7 +14619,13 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { final CallerIdentity caller = getCallerIdentity(); Preconditions.checkCallAuthorization(hasCrossUsersPermission(caller, userId)); - return isUserAffiliatedWithDeviceLocked(userId); + return isUserAffiliatedWithDevice(userId); + } + + private boolean isUserAffiliatedWithDevice(@UserIdInt int userId) { + synchronized (getLockObject()) { + return isUserAffiliatedWithDeviceLocked(userId); + } } private boolean isUserAffiliatedWithDeviceLocked(@UserIdInt int userId) { diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/FactoryResetter.java b/services/devicepolicy/java/com/android/server/devicepolicy/FactoryResetter.java index 964be38943bf..c72e1eabb086 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/FactoryResetter.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/FactoryResetter.java @@ -16,6 +16,8 @@ package com.android.server.devicepolicy; +import static com.android.server.FactoryResetter.setFactoryResetting; + import android.annotation.Nullable; import android.app.admin.DevicePolicySafetyChecker; import android.content.Context; @@ -36,7 +38,10 @@ import java.util.Objects; /** * Entry point for "factory reset" requests. + * + * @deprecated TODO(b/225012970): should be moved to {@code com.android.server.FactoryResetter} */ +@Deprecated public final class FactoryResetter { private static final String TAG = FactoryResetter.class.getSimpleName(); @@ -60,6 +65,8 @@ public final class FactoryResetter { Preconditions.checkCallAuthorization(mContext.checkCallingOrSelfPermission( android.Manifest.permission.MASTER_CLEAR) == PackageManager.PERMISSION_GRANTED); + setFactoryResetting(mContext); + if (mSafetyChecker == null) { factoryResetInternalUnchecked(); return true; diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportManager.java b/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportManager.java index d7cbd9b17ff3..346e859f9275 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportManager.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/RemoteBugreportManager.java @@ -31,6 +31,7 @@ import android.annotation.IntDef; import android.app.Notification; import android.app.PendingIntent; import android.app.admin.DeviceAdminReceiver; +import android.app.admin.DevicePolicyManager; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; @@ -54,7 +55,9 @@ import com.android.server.utils.Slogf; import java.io.FileNotFoundException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.security.SecureRandom; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicLong; /** * Class managing bugreport collection upon device owner's request. @@ -78,6 +81,9 @@ public class RemoteBugreportManager { private final DevicePolicyManagerService mService; private final DevicePolicyManagerService.Injector mInjector; + private final SecureRandom mRng = new SecureRandom(); + + private final AtomicLong mRemoteBugreportNonce = new AtomicLong(); private final AtomicBoolean mRemoteBugreportServiceIsActive = new AtomicBoolean(); private final AtomicBoolean mRemoteBugreportSharingAccepted = new AtomicBoolean(); private final Context mContext; @@ -197,8 +203,13 @@ public class RemoteBugreportManager { final long callingIdentity = mInjector.binderClearCallingIdentity(); try { - mInjector.getIActivityManager().requestRemoteBugReport(); + long nonce; + do { + nonce = mRng.nextLong(); + } while (nonce == 0); + mInjector.getIActivityManager().requestRemoteBugReport(nonce); + mRemoteBugreportNonce.set(nonce); mRemoteBugreportServiceIsActive.set(true); mRemoteBugreportSharingAccepted.set(false); registerRemoteBugreportReceivers(); @@ -231,6 +242,11 @@ public class RemoteBugreportManager { } private void onBugreportFinished(Intent intent) { + long nonce = intent.getLongExtra(DevicePolicyManager.EXTRA_REMOTE_BUGREPORT_NONCE, 0); + if (nonce == 0 || mRemoteBugreportNonce.get() != nonce) { + Slogf.w(LOG_TAG, "Invalid nonce provided, ignoring " + nonce); + return; + } mHandler.removeCallbacks(mRemoteBugreportTimeoutRunnable); mRemoteBugreportServiceIsActive.set(false); final Uri bugreportUri = intent.getData(); diff --git a/services/incremental/TEST_MAPPING b/services/incremental/TEST_MAPPING index 6aa8a939739a..f2ad068854c4 100644 --- a/services/incremental/TEST_MAPPING +++ b/services/incremental/TEST_MAPPING @@ -1,20 +1,6 @@ { "presubmit": [ { - "name": "CtsContentTestCases", - "options": [ - { - "include-filter": "android.content.pm.cts.PackageManagerShellCommandTest" - }, - { - "include-filter": "android.content.pm.cts.PackageManagerShellCommandIncrementalTest" - }, - { - "include-filter": "android.content.pm.cts.ChecksumsTest" - } - ] - }, - { "name": "CtsPackageManagerStatsHostTestCases", "options": [ { @@ -29,6 +15,20 @@ "presubmit-large": [ { "name": "CtsInstalledLoadingProgressHostTests" + }, + { + "name": "CtsContentTestCases", + "options": [ + { + "include-filter": "android.content.pm.cts.PackageManagerShellCommandTest" + }, + { + "include-filter": "android.content.pm.cts.PackageManagerShellCommandIncrementalTest" + }, + { + "include-filter": "android.content.pm.cts.ChecksumsTest" + } + ] } ] } diff --git a/services/midi/java/com/android/server/midi/MidiService.java b/services/midi/java/com/android/server/midi/MidiService.java index d0205ae24f85..ca31efcdf3d2 100644 --- a/services/midi/java/com/android/server/midi/MidiService.java +++ b/services/midi/java/com/android/server/midi/MidiService.java @@ -340,6 +340,11 @@ public class MidiService extends IMidiManager.Stub { IBinder binder = server.asBinder(); mDevicesByServer.remove(binder); + // Clearing mDeviceStatus is needed because setDeviceStatus() + // relies on finding the device in mDevicesByServer. + // So the status can no longer be updated after we remove it. + // Then we can end up with input ports that are stuck open. + mDeviceStatus = null; try { server.closeDevice(); diff --git a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java index 16afef57d31e..32d9247216c4 100644 --- a/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/alarm/AlarmManagerServiceTest.java @@ -462,9 +462,9 @@ public class AlarmManagerServiceTest { final ArgumentCaptor<AlarmManagerService.UninstallReceiver> packageReceiverCaptor = ArgumentCaptor.forClass(AlarmManagerService.UninstallReceiver.class); - verify(mMockContext).registerReceiver(packageReceiverCaptor.capture(), + verify(mMockContext).registerReceiverForAllUsers(packageReceiverCaptor.capture(), argThat((filter) -> filter.hasAction(Intent.ACTION_PACKAGE_ADDED) - && filter.hasAction(Intent.ACTION_PACKAGE_REMOVED))); + && filter.hasAction(Intent.ACTION_PACKAGE_REMOVED)), isNull(), isNull()); mPackageChangesReceiver = packageReceiverCaptor.getValue(); assertEquals(mService.mExactAlarmCandidates, Collections.emptySet()); diff --git a/services/tests/mockingservicestests/src/com/android/server/devicepolicy/FactoryResetterTest.java b/services/tests/mockingservicestests/src/com/android/server/devicepolicy/FactoryResetterTest.java index 457c8db9fdf3..4ffa0fbec758 100644 --- a/services/tests/mockingservicestests/src/com/android/server/devicepolicy/FactoryResetterTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/devicepolicy/FactoryResetterTest.java @@ -14,11 +14,13 @@ * limitations under the License. */ +// TODO(b/225012970): should be moved to com.android.server package com.android.server.devicepolicy; import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; +import static com.android.server.FactoryResetter.isFactoryResetting; import static com.google.common.truth.Truth.assertThat; @@ -165,6 +167,7 @@ public final class FactoryResetterTest { .factoryReset(); assertThat(success).isTrue(); + assertThat(isFactoryResetting()).isTrue(); verifyWipeAdoptableStorageCalled(); verifyWipeFactoryResetProtectionNotCalled(); verifyRebootWipeUserDataMinimumArgsCalled(); @@ -179,6 +182,7 @@ public final class FactoryResetterTest { .build().factoryReset(); assertThat(success).isTrue(); + assertThat(isFactoryResetting()).isTrue(); verifyWipeAdoptableStorageNotCalled(); verifyWipeFactoryResetProtectionCalled(); verifyRebootWipeUserDataMinimumArgsCalled(); @@ -198,6 +202,7 @@ public final class FactoryResetterTest { .build().factoryReset(); assertThat(success).isTrue(); + assertThat(isFactoryResetting()).isTrue(); verifyWipeAdoptableStorageCalled(); verifyWipeFactoryResetProtectionCalled(); verifyRebootWipeUserDataAllArgsCalled(); @@ -211,6 +216,7 @@ public final class FactoryResetterTest { .setSafetyChecker(mSafetyChecker).build().factoryReset(); assertThat(success).isFalse(); + assertThat(isFactoryResetting()).isTrue(); verifyWipeAdoptableStorageNotCalled(); verifyWipeFactoryResetProtectionNotCalled(); verifyRebootWipeUserDataNotCalled(); @@ -238,6 +244,7 @@ public final class FactoryResetterTest { .build().factoryReset(); assertThat(success).isFalse(); + assertThat(isFactoryResetting()).isTrue(); verifyWipeAdoptableStorageCalled(); verifyWipeFactoryResetProtectionCalled(); verifyRebootWipeUserDataAllArgsCalled(); diff --git a/services/tests/mockingservicestests/src/com/android/server/utils/TimingsTraceAndSlogTest.java b/services/tests/mockingservicestests/src/com/android/server/utils/TimingsTraceAndSlogTest.java new file mode 100644 index 000000000000..52cd29cabb94 --- /dev/null +++ b/services/tests/mockingservicestests/src/com/android/server/utils/TimingsTraceAndSlogTest.java @@ -0,0 +1,165 @@ +/* + * 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.server.utils; + +import static android.os.Trace.TRACE_TAG_APP; + +import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.contains; +import static org.mockito.Matchers.eq; +import static org.mockito.Matchers.matches; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; + +import android.os.Trace; +import android.util.Slog; + +import androidx.test.filters.SmallTest; +import androidx.test.runner.AndroidJUnit4; + +import com.android.dx.mockito.inline.extended.MockedVoidMethod; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.MockitoSession; + +import java.util.ArrayList; +import java.util.List; + +/** + * Tests for {@link TimingsTraceAndSlog}. + * + * <p>Usage: {@code atest FrameworksMockingServicesTests:TimingsTraceAndSlogTest} + */ +@SmallTest +@RunWith(AndroidJUnit4.class) +public class TimingsTraceAndSlogTest { + + private static final String TAG = "TEST"; + + private MockitoSession mSession; + + @Before + public final void startMockSession() { + mSession = mockitoSession() + .spyStatic(Slog.class) + .spyStatic(Trace.class) + .startMocking(); + } + + @After + public final void finishMockSession() { + mSession.finishMocking(); + } + + @Test + public void testDifferentThreads() throws Exception { + TimingsTraceAndSlog log = new TimingsTraceAndSlog(TAG, TRACE_TAG_APP); + // Should be able to log on the same thread + log.traceBegin("test"); + log.traceEnd(); + final List<String> errors = new ArrayList<>(); + // Calling from a different thread should fail + Thread t = new Thread(() -> { + try { + log.traceBegin("test"); + errors.add("traceBegin should fail on a different thread"); + } catch (IllegalStateException expected) { + } + try { + log.traceEnd(); + errors.add("traceEnd should fail on a different thread"); + } catch (IllegalStateException expected) { + } + // Verify that creating a new log will work + TimingsTraceAndSlog log2 = new TimingsTraceAndSlog(TAG, TRACE_TAG_APP); + log2.traceBegin("test"); + log2.traceEnd(); + + }); + t.start(); + t.join(); + assertThat(errors).isEmpty(); + } + + @Test + public void testGetUnfinishedTracesForDebug() { + TimingsTraceAndSlog log = new TimingsTraceAndSlog(TAG, TRACE_TAG_APP); + assertThat(log.getUnfinishedTracesForDebug()).isEmpty(); + + log.traceBegin("One"); + assertThat(log.getUnfinishedTracesForDebug()).containsExactly("One").inOrder(); + + log.traceBegin("Two"); + assertThat(log.getUnfinishedTracesForDebug()).containsExactly("One", "Two").inOrder(); + + log.traceEnd(); + assertThat(log.getUnfinishedTracesForDebug()).containsExactly("One").inOrder(); + + log.traceEnd(); + assertThat(log.getUnfinishedTracesForDebug()).isEmpty(); + } + + @Test + public void testLogDuration() throws Exception { + TimingsTraceAndSlog log = new TimingsTraceAndSlog(TAG, TRACE_TAG_APP); + log.logDuration("logro", 42); + verify((MockedVoidMethod) () -> Slog.v(eq(TAG), contains("logro took to complete: 42ms"))); + } + + @Test + public void testOneLevel() throws Exception { + TimingsTraceAndSlog log = new TimingsTraceAndSlog(TAG, TRACE_TAG_APP); + log.traceBegin("test"); + log.traceEnd(); + + verify((MockedVoidMethod) () -> Trace.traceBegin(TRACE_TAG_APP, "test")); + verify((MockedVoidMethod) () -> Trace.traceEnd(TRACE_TAG_APP)); + verify((MockedVoidMethod) () -> Slog.v(eq(TAG), matches("test took to complete: \\dms"))); + } + + @Test + public void testMultipleLevels() throws Exception { + TimingsTraceAndSlog log = new TimingsTraceAndSlog(TAG, TRACE_TAG_APP); + log.traceBegin("L1"); + log.traceBegin("L2"); + log.traceEnd(); + log.traceEnd(); + + verify((MockedVoidMethod) () -> Trace.traceBegin(TRACE_TAG_APP, "L1")); + verify((MockedVoidMethod) () -> Trace.traceBegin(TRACE_TAG_APP, "L2")); + verify((MockedVoidMethod) () -> Trace.traceEnd(TRACE_TAG_APP), times(2)); // L1 and L2 + + verify((MockedVoidMethod) () -> Slog.v(eq(TAG), matches("L2 took to complete: \\d+ms"))); + verify((MockedVoidMethod) () -> Slog.v(eq(TAG), matches("L1 took to complete: \\d+ms"))); + } + + @Test + public void testEndNoBegin() throws Exception { + TimingsTraceAndSlog log = new TimingsTraceAndSlog(TAG, TRACE_TAG_APP); + log.traceEnd(); + verify((MockedVoidMethod) () -> Trace.traceEnd(TRACE_TAG_APP)); + verify((MockedVoidMethod) () -> Slog.d(eq(TAG), anyString()), never()); + verify((MockedVoidMethod) () -> Slog.w(TAG, "traceEnd called more times than traceBegin")); + } +} diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp index ec7c17af6a0c..fb36a61bc5b1 100644 --- a/services/tests/servicestests/Android.bp +++ b/services/tests/servicestests/Android.bp @@ -25,7 +25,7 @@ android_test { "test-apps/JobTestApp/src/**/*.java", "test-apps/SuspendTestApp/src/**/*.java", - ":service-bluetooth-tests-sources", // TODO(b/214988855) : Remove once framework-bluetooth jar is ready + ":service-bluetooth-tests-sources", // TODO(b/214988855) : Remove once framework-bluetooth jar is ready ], static_libs: [ "frameworks-base-testutils", diff --git a/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java b/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java index 2eb9e34b3fd0..3d3c1abb3e91 100644 --- a/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/GestureLauncherServiceTest.java @@ -187,6 +187,30 @@ public class GestureLauncherServiceTest { } @Test + public void testGetEmergencyGesturePowerButtonCooldownPeriodMs_enabled() { + withEmergencyGesturePowerButtonCooldownPeriodMsValue(4000); + assertEquals(4000, + mGestureLauncherService.getEmergencyGesturePowerButtonCooldownPeriodMs(mContext, + FAKE_USER_ID)); + } + + @Test + public void testGetEmergencyGesturePowerButtonCooldownPeriodMs_disabled() { + withEmergencyGesturePowerButtonCooldownPeriodMsValue(0); + assertEquals(0, + mGestureLauncherService.getEmergencyGesturePowerButtonCooldownPeriodMs(mContext, + FAKE_USER_ID)); + } + + @Test + public void testGetEmergencyGesturePowerButtonCooldownPeriodMs_cappedAtMaximum() { + withEmergencyGesturePowerButtonCooldownPeriodMsValue(10000); + assertEquals(GestureLauncherService.EMERGENCY_GESTURE_POWER_BUTTON_COOLDOWN_PERIOD_MS_MAX, + mGestureLauncherService.getEmergencyGesturePowerButtonCooldownPeriodMs(mContext, + FAKE_USER_ID)); + } + + @Test public void testHandleCameraLaunchGesture_userSetupComplete() { withUserSetupCompleteValue(true); @@ -645,6 +669,211 @@ public class GestureLauncherServiceTest { } @Test + public void testInterceptPowerKeyDown_triggerEmergency_singleTaps_cooldownTriggered() { + // Enable power button cooldown + withEmergencyGesturePowerButtonCooldownPeriodMsValue(3000); + mGestureLauncherService.updateEmergencyGesturePowerButtonCooldownPeriodMs(); + + // Trigger emergency by tapping button 5 times + long eventTime = triggerEmergencyGesture(); + + // Add enough interval to reset consecutive tap count + long interval = GestureLauncherService.POWER_SHORT_TAP_SEQUENCE_MAX_INTERVAL_MS + 1; + eventTime += interval; + + // Subsequent single tap is intercepted, but should not trigger any gesture + KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, + IGNORED_REPEAT); + boolean interactive = true; + MutableBoolean outLaunched = new MutableBoolean(true); + boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, + outLaunched); + assertTrue(intercepted); + assertFalse(outLaunched.value); + + // Add enough interval to reset consecutive tap count + interval = GestureLauncherService.POWER_SHORT_TAP_SEQUENCE_MAX_INTERVAL_MS + 1; + eventTime += interval; + + // Another single tap should be the same (intercepted but should not trigger gesture) + keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, + IGNORED_REPEAT); + interactive = true; + outLaunched = new MutableBoolean(true); + intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, + outLaunched); + assertTrue(intercepted); + assertFalse(outLaunched.value); + } + + @Test + public void + testInterceptPowerKeyDown_triggerEmergency_cameraGestureEnabled_doubleTap_cooldownTriggered() { + // Enable camera double tap gesture + withCameraDoubleTapPowerEnableConfigValue(true); + withCameraDoubleTapPowerDisableSettingValue(0); + mGestureLauncherService.updateCameraDoubleTapPowerEnabled(); + + // Enable power button cooldown + withEmergencyGesturePowerButtonCooldownPeriodMsValue(3000); + mGestureLauncherService.updateEmergencyGesturePowerButtonCooldownPeriodMs(); + + // Trigger emergency by tapping button 5 times + long eventTime = triggerEmergencyGesture(); + + // Add enough interval to reset consecutive tap count + long interval = GestureLauncherService.POWER_SHORT_TAP_SEQUENCE_MAX_INTERVAL_MS + 1; + eventTime += interval; + + // Subsequent double tap is intercepted, but should not trigger any gesture + for (int i = 0; i < 2; i++) { + KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, + IGNORED_CODE, IGNORED_REPEAT); + boolean interactive = true; + MutableBoolean outLaunched = new MutableBoolean(true); + boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, + interactive, outLaunched); + assertTrue(intercepted); + assertFalse(outLaunched.value); + interval = GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; + eventTime += interval; + } + } + + @Test + public void testInterceptPowerKeyDown_triggerEmergency_fiveTaps_cooldownTriggered() { + // Enable power button cooldown + withEmergencyGesturePowerButtonCooldownPeriodMsValue(3000); + mGestureLauncherService.updateEmergencyGesturePowerButtonCooldownPeriodMs(); + + // Trigger emergency by tapping button 5 times + long eventTime = triggerEmergencyGesture(); + + // Add enough interval to reset consecutive tap count + long interval = GestureLauncherService.POWER_SHORT_TAP_SEQUENCE_MAX_INTERVAL_MS + 1; + eventTime += interval; + + // Subsequent 5 taps are intercepted, but should not trigger any gesture + for (int i = 0; i < 5; i++) { + KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, + IGNORED_CODE, IGNORED_REPEAT); + boolean interactive = true; + MutableBoolean outLaunched = new MutableBoolean(true); + boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, + interactive, outLaunched); + assertTrue(intercepted); + assertFalse(outLaunched.value); + interval = GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; + eventTime += interval; + } + } + + @Test + public void testInterceptPowerKeyDown_triggerEmergency_longPress_cooldownTriggered() { + // Enable power button cooldown + withEmergencyGesturePowerButtonCooldownPeriodMsValue(3000); + mGestureLauncherService.updateEmergencyGesturePowerButtonCooldownPeriodMs(); + + // Trigger emergency by tapping button 5 times + long eventTime = triggerEmergencyGesture(); + + // Add enough interval to reset consecutive tap count + long interval = GestureLauncherService.POWER_SHORT_TAP_SEQUENCE_MAX_INTERVAL_MS + 1; + eventTime += interval; + + // Subsequent long press is intercepted, but should not trigger any gesture + KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, + IGNORED_REPEAT, IGNORED_META_STATE, IGNORED_DEVICE_ID, IGNORED_SCANCODE, + KeyEvent.FLAG_LONG_PRESS); + + boolean interactive = true; + MutableBoolean outLaunched = new MutableBoolean(true); + boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, + outLaunched); + assertTrue(intercepted); + assertFalse(outLaunched.value); + } + + @Test + public void testInterceptPowerKeyDown_triggerEmergency_cooldownDisabled_cooldownNotTriggered() { + // Disable power button cooldown by setting cooldown period to 0 + withEmergencyGesturePowerButtonCooldownPeriodMsValue(0); + mGestureLauncherService.updateEmergencyGesturePowerButtonCooldownPeriodMs(); + + // Trigger emergency by tapping button 5 times + long eventTime = triggerEmergencyGesture(); + + // Add enough interval to reset consecutive tap count + long interval = GestureLauncherService.POWER_SHORT_TAP_SEQUENCE_MAX_INTERVAL_MS + 1; + eventTime += interval; + + // Subsequent single tap is NOT intercepted + KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, + IGNORED_REPEAT); + boolean interactive = true; + MutableBoolean outLaunched = new MutableBoolean(true); + boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, + outLaunched); + assertFalse(intercepted); + assertFalse(outLaunched.value); + + // Add enough interval to reset consecutive tap count + interval = GestureLauncherService.POWER_SHORT_TAP_SEQUENCE_MAX_INTERVAL_MS + 1; + eventTime += interval; + + // Long press also NOT intercepted + keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, + IGNORED_REPEAT, IGNORED_META_STATE, IGNORED_DEVICE_ID, IGNORED_SCANCODE, + KeyEvent.FLAG_LONG_PRESS); + interactive = true; + outLaunched = new MutableBoolean(true); + intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, + outLaunched); + assertFalse(intercepted); + assertFalse(outLaunched.value); + } + + @Test + public void + testInterceptPowerKeyDown_triggerEmergency_outsideCooldownPeriod_cooldownNotTriggered() { + // Enable power button cooldown + withEmergencyGesturePowerButtonCooldownPeriodMsValue(5000); + mGestureLauncherService.updateEmergencyGesturePowerButtonCooldownPeriodMs(); + + // Trigger emergency by tapping button 5 times + long eventTime = triggerEmergencyGesture(); + + // Add enough interval to be outside of cooldown period + long interval = 5001; + eventTime += interval; + + // Subsequent single tap is NOT intercepted + KeyEvent keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, + IGNORED_REPEAT); + boolean interactive = true; + MutableBoolean outLaunched = new MutableBoolean(true); + boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, + outLaunched); + assertFalse(intercepted); + assertFalse(outLaunched.value); + + // Add enough interval to reset consecutive tap count + interval = GestureLauncherService.POWER_SHORT_TAP_SEQUENCE_MAX_INTERVAL_MS + 1; + eventTime += interval; + + // Long press also NOT intercepted + keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, + IGNORED_REPEAT, IGNORED_META_STATE, IGNORED_DEVICE_ID, IGNORED_SCANCODE, + KeyEvent.FLAG_LONG_PRESS); + interactive = true; + outLaunched = new MutableBoolean(true); + intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, + outLaunched); + assertFalse(intercepted); + assertFalse(outLaunched.value); + } + + @Test public void testInterceptPowerKeyDown_longpress() { withCameraDoubleTapPowerEnableConfigValue(true); withCameraDoubleTapPowerDisableSettingValue(0); @@ -1153,6 +1382,45 @@ public class GestureLauncherServiceTest { assertEquals(1, tapCounts.get(1).intValue()); } + /** + * Helper method to trigger emergency gesture by pressing button for 5 times. + * @return last event time. + */ + private long triggerEmergencyGesture() { + // Enable emergency power gesture + withEmergencyGestureEnabledConfigValue(true); + withEmergencyGestureEnabledSettingValue(true); + mGestureLauncherService.updateEmergencyGestureEnabled(); + withUserSetupCompleteValue(true); + + // 4 button presses + long eventTime = INITIAL_EVENT_TIME_MILLIS; + boolean interactive = true; + KeyEvent keyEvent; + MutableBoolean outLaunched = new MutableBoolean(false); + for (int i = 0; i < 4; i++) { + keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, + IGNORED_REPEAT); + mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, outLaunched); + final long interval = GestureLauncherService.CAMERA_POWER_DOUBLE_TAP_MAX_TIME_MS - 1; + eventTime += interval; + } + + // 5th button press should trigger the emergency flow + keyEvent = new KeyEvent(IGNORED_DOWN_TIME, eventTime, IGNORED_ACTION, IGNORED_CODE, + IGNORED_REPEAT); + outLaunched.value = false; + boolean intercepted = mGestureLauncherService.interceptPowerKeyDown(keyEvent, interactive, + outLaunched); + assertTrue(outLaunched.value); + assertTrue(intercepted); + verify(mUiEventLogger, times(1)) + .log(GestureLauncherService.GestureLauncherEvent.GESTURE_EMERGENCY_TAP_POWER); + verify(mStatusBarManagerInternal).onEmergencyActionLaunchGestureDetected(); + + return eventTime; + } + private void withCameraDoubleTapPowerEnableConfigValue(boolean enableConfigValue) { when(mResources.getBoolean( com.android.internal.R.bool.config_cameraDoubleTapPowerGestureEnabled)) @@ -1181,6 +1449,13 @@ public class GestureLauncherServiceTest { UserHandle.USER_CURRENT); } + private void withEmergencyGesturePowerButtonCooldownPeriodMsValue(int period) { + Settings.Global.putInt( + mContentResolver, + Settings.Global.EMERGENCY_GESTURE_POWER_BUTTON_COOLDOWN_PERIOD_MS, + period); + } + private void withUserSetupCompleteValue(boolean userSetupComplete) { int userSetupCompleteValue = userSetupComplete ? 1 : 0; Settings.Secure.putIntForUser( diff --git a/services/tests/servicestests/src/com/android/server/backup/restore/FullRestoreEngineTest.java b/services/tests/servicestests/src/com/android/server/backup/restore/FullRestoreEngineTest.java new file mode 100644 index 000000000000..049c745fc128 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/backup/restore/FullRestoreEngineTest.java @@ -0,0 +1,150 @@ +/* + * 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.server.backup.restore; + +import static com.google.common.truth.Truth.assertWithMessage; + +import android.app.backup.BackupAgent; +import android.platform.test.annotations.Presubmit; +import android.system.OsConstants; + +import androidx.test.runner.AndroidJUnit4; + +import com.android.server.backup.FileMetadata; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +@Presubmit +@RunWith(AndroidJUnit4.class) +public class FullRestoreEngineTest { + private static final String DEFAULT_PACKAGE_NAME = "package"; + private static final String DEFAULT_DOMAIN_NAME = "domain"; + private static final String NEW_PACKAGE_NAME = "new_package"; + private static final String NEW_DOMAIN_NAME = "new_domain"; + + private FullRestoreEngine mRestoreEngine; + + @Before + public void setUp() { + mRestoreEngine = new FullRestoreEngine(); + } + + @Test + public void shouldSkipReadOnlyDir_skipsAllReadonlyDirsAndTheirChildren() { + // Create the file tree. + TestFile[] testFiles = new TestFile[] { + TestFile.dir("root"), + TestFile.file("root/auth_token"), + TestFile.dir("root/media"), + TestFile.file("root/media/picture1.png"), + TestFile.file("root/push_token.txt"), + TestFile.dir("root/read-only-dir-1").markReadOnly().expectSkipped(), + TestFile.dir("root/read-only-dir-1/writable-subdir").expectSkipped(), + TestFile.file("root/read-only-dir-1/writable-subdir/writable-file").expectSkipped(), + TestFile.dir("root/read-only-dir-1/writable-subdir/read-only-subdir-2") + .markReadOnly().expectSkipped(), + TestFile.file("root/read-only-dir-1/writable-file").expectSkipped(), + TestFile.file("root/random-stuff.txt"), + TestFile.dir("root/database"), + TestFile.file("root/database/users.db"), + TestFile.dir("root/read-only-dir-2").markReadOnly().expectSkipped(), + TestFile.file("root/read-only-dir-2/writable-file-1").expectSkipped(), + TestFile.file("root/read-only-dir-2/writable-file-2").expectSkipped(), + }; + + assertCorrectItemsAreSkipped(testFiles); + } + + @Test + public void shouldSkipReadOnlyDir_onlySkipsChildrenUnderTheSamePackage() { + TestFile[] testFiles = new TestFile[]{ + TestFile.dir("read-only-dir").markReadOnly().expectSkipped(), + TestFile.file("read-only-dir/file").expectSkipped(), + TestFile.file("read-only-dir/file-from-different-package") + .setPackage(NEW_PACKAGE_NAME), + }; + + assertCorrectItemsAreSkipped(testFiles); + } + + @Test + public void shouldSkipReadOnlyDir_onlySkipsChildrenUnderTheSameDomain() { + TestFile[] testFiles = new TestFile[]{ + TestFile.dir("read-only-dir").markReadOnly().expectSkipped(), + TestFile.file("read-only-dir/file").expectSkipped(), + TestFile.file("read-only-dir/file-from-different-domain") + .setDomain(NEW_DOMAIN_NAME), + }; + + assertCorrectItemsAreSkipped(testFiles); + } + + private void assertCorrectItemsAreSkipped(TestFile[] testFiles) { + // Verify all directories marked with .expectSkipped are skipped. + for (TestFile testFile : testFiles) { + boolean actualExcluded = mRestoreEngine.shouldSkipReadOnlyDir(testFile.mMetadata); + boolean expectedExcluded = testFile.mShouldSkip; + assertWithMessage(testFile.mMetadata.path).that(actualExcluded).isEqualTo( + expectedExcluded); + } + } + + private static class TestFile { + private final FileMetadata mMetadata; + private boolean mShouldSkip; + + static TestFile dir(String path) { + return new TestFile(path, BackupAgent.TYPE_DIRECTORY); + } + + static TestFile file(String path) { + return new TestFile(path, BackupAgent.TYPE_FILE); + } + + TestFile markReadOnly() { + mMetadata.mode = 0; + return this; + } + + TestFile expectSkipped() { + mShouldSkip = true; + return this; + } + + TestFile setPackage(String packageName) { + mMetadata.packageName = packageName; + return this; + } + + TestFile setDomain(String domain) { + mMetadata.domain = domain; + return this; + } + + private TestFile(String path, int type) { + FileMetadata metadata = new FileMetadata(); + metadata.path = path; + metadata.type = type; + metadata.packageName = DEFAULT_PACKAGE_NAME; + metadata.domain = DEFAULT_DOMAIN_NAME; + metadata.mode = OsConstants.S_IWUSR; // Mark as writable. + mMetadata = metadata; + } + } +} diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerOperationTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerOperationTest.java new file mode 100644 index 000000000000..d4bac2c0402d --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerOperationTest.java @@ -0,0 +1,326 @@ +/* + * Copyright (C) 2021 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.server.biometrics.sensors; + +import static android.testing.TestableLooper.RunWithLooper; + +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.anyBoolean; +import static org.mockito.Mockito.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.testng.Assert.assertThrows; + +import android.os.Handler; +import android.platform.test.annotations.Presubmit; +import android.testing.AndroidTestingRunner; +import android.testing.TestableLooper; + +import androidx.test.filters.SmallTest; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +@Presubmit +@RunWith(AndroidTestingRunner.class) +@RunWithLooper(setAsMainLooper = true) +@SmallTest +public class BiometricSchedulerOperationTest { + + public interface FakeHal {} + public abstract static class InterruptableMonitor<T> + extends HalClientMonitor<T> implements Interruptable { + public InterruptableMonitor() { + super(null, null, null, null, 0, null, 0, 0, 0, 0, 0); + } + } + + @Mock + private InterruptableMonitor<FakeHal> mClientMonitor; + @Mock + private BaseClientMonitor.Callback mClientCallback; + @Mock + private FakeHal mHal; + @Captor + ArgumentCaptor<BaseClientMonitor.Callback> mStartCallback; + + private Handler mHandler; + private BiometricSchedulerOperation mOperation; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mHandler = new Handler(TestableLooper.get(this).getLooper()); + mOperation = new BiometricSchedulerOperation(mClientMonitor, mClientCallback); + } + + @Test + public void testStartWithCookie() { + final int cookie = 200; + when(mClientMonitor.getCookie()).thenReturn(cookie); + when(mClientMonitor.getFreshDaemon()).thenReturn(mHal); + + assertThat(mOperation.isReadyToStart()).isEqualTo(cookie); + assertThat(mOperation.isStarted()).isFalse(); + assertThat(mOperation.isCanceling()).isFalse(); + assertThat(mOperation.isFinished()).isFalse(); + + final boolean started = mOperation.startWithCookie( + mock(BaseClientMonitor.Callback.class), cookie); + + assertThat(started).isTrue(); + verify(mClientMonitor).start(mStartCallback.capture()); + mStartCallback.getValue().onClientStarted(mClientMonitor); + assertThat(mOperation.isStarted()).isTrue(); + } + + @Test + public void testNoStartWithoutCookie() { + final int goodCookie = 20; + final int badCookie = 22; + when(mClientMonitor.getCookie()).thenReturn(goodCookie); + when(mClientMonitor.getFreshDaemon()).thenReturn(mHal); + + assertThat(mOperation.isReadyToStart()).isEqualTo(goodCookie); + final boolean started = mOperation.startWithCookie( + mock(BaseClientMonitor.Callback.class), badCookie); + + assertThat(started).isFalse(); + assertThat(mOperation.isStarted()).isFalse(); + assertThat(mOperation.isCanceling()).isFalse(); + assertThat(mOperation.isFinished()).isFalse(); + } + + @Test + public void startsWhenReadyAndHalAvailable() { + when(mClientMonitor.getCookie()).thenReturn(0); + when(mClientMonitor.getFreshDaemon()).thenReturn(mHal); + + final BaseClientMonitor.Callback cb = mock(BaseClientMonitor.Callback.class); + mOperation.start(cb); + verify(mClientMonitor).start(mStartCallback.capture()); + mStartCallback.getValue().onClientStarted(mClientMonitor); + + assertThat(mOperation.isStarted()).isTrue(); + assertThat(mOperation.isCanceling()).isFalse(); + assertThat(mOperation.isFinished()).isFalse(); + + verify(mClientCallback).onClientStarted(eq(mClientMonitor)); + verify(cb).onClientStarted(eq(mClientMonitor)); + verify(mClientCallback, never()).onClientFinished(any(), anyBoolean()); + verify(cb, never()).onClientFinished(any(), anyBoolean()); + + mStartCallback.getValue().onClientFinished(mClientMonitor, true); + + assertThat(mOperation.isFinished()).isTrue(); + assertThat(mOperation.isCanceling()).isFalse(); + verify(mClientMonitor).destroy(); + verify(cb).onClientFinished(eq(mClientMonitor), eq(true)); + } + + @Test + public void startFailsWhenReadyButHalNotAvailable() { + when(mClientMonitor.getCookie()).thenReturn(0); + when(mClientMonitor.getFreshDaemon()).thenReturn(null); + + final BaseClientMonitor.Callback cb = mock(BaseClientMonitor.Callback.class); + mOperation.start(cb); + verify(mClientMonitor, never()).start(any()); + + assertThat(mOperation.isStarted()).isFalse(); + assertThat(mOperation.isCanceling()).isFalse(); + assertThat(mOperation.isFinished()).isTrue(); + + verify(mClientCallback, never()).onClientStarted(eq(mClientMonitor)); + verify(cb, never()).onClientStarted(eq(mClientMonitor)); + verify(mClientCallback).onClientFinished(eq(mClientMonitor), eq(false)); + verify(cb).onClientFinished(eq(mClientMonitor), eq(false)); + } + + @Test + public void doesNotStartWithCookie() { + when(mClientMonitor.getCookie()).thenReturn(9); + assertThrows(IllegalStateException.class, + () -> mOperation.start(mock(BaseClientMonitor.Callback.class))); + } + + @Test + public void cannotRestart() { + when(mClientMonitor.getFreshDaemon()).thenReturn(mHal); + + mOperation.start(mock(BaseClientMonitor.Callback.class)); + + assertThrows(IllegalStateException.class, + () -> mOperation.start(mock(BaseClientMonitor.Callback.class))); + } + + @Test + public void abortsNotRunning() { + when(mClientMonitor.getFreshDaemon()).thenReturn(mHal); + + mOperation.abort(); + + assertThat(mOperation.isFinished()).isTrue(); + verify(mClientMonitor).unableToStart(); + verify(mClientMonitor).destroy(); + assertThrows(IllegalStateException.class, + () -> mOperation.start(mock(BaseClientMonitor.Callback.class))); + } + + @Test + public void cannotAbortRunning() { + when(mClientMonitor.getFreshDaemon()).thenReturn(mHal); + + mOperation.start(mock(BaseClientMonitor.Callback.class)); + + assertThrows(IllegalStateException.class, () -> mOperation.abort()); + } + + @Test + public void cancel() { + when(mClientMonitor.getFreshDaemon()).thenReturn(mHal); + + final BaseClientMonitor.Callback startCb = mock(BaseClientMonitor.Callback.class); + final BaseClientMonitor.Callback cancelCb = mock(BaseClientMonitor.Callback.class); + mOperation.start(startCb); + verify(mClientMonitor).start(mStartCallback.capture()); + mStartCallback.getValue().onClientStarted(mClientMonitor); + mOperation.cancel(mHandler, cancelCb); + + assertThat(mOperation.isCanceling()).isTrue(); + verify(mClientMonitor).cancel(); + verify(mClientMonitor, never()).cancelWithoutStarting(any()); + verify(mClientMonitor, never()).destroy(); + + mStartCallback.getValue().onClientFinished(mClientMonitor, true); + + assertThat(mOperation.isFinished()).isTrue(); + assertThat(mOperation.isCanceling()).isFalse(); + verify(mClientMonitor).destroy(); + + // should be unused since the operation was started + verify(cancelCb, never()).onClientStarted(any()); + verify(cancelCb, never()).onClientFinished(any(), anyBoolean()); + } + + @Test + public void cancelWithoutStarting() { + when(mClientMonitor.getFreshDaemon()).thenReturn(mHal); + + final BaseClientMonitor.Callback cancelCb = mock(BaseClientMonitor.Callback.class); + mOperation.cancel(mHandler, cancelCb); + + assertThat(mOperation.isCanceling()).isTrue(); + ArgumentCaptor<BaseClientMonitor.Callback> cbCaptor = + ArgumentCaptor.forClass(BaseClientMonitor.Callback.class); + verify(mClientMonitor).cancelWithoutStarting(cbCaptor.capture()); + + cbCaptor.getValue().onClientFinished(mClientMonitor, true); + verify(cancelCb).onClientFinished(eq(mClientMonitor), eq(true)); + verify(mClientMonitor, never()).start(any()); + verify(mClientMonitor, never()).cancel(); + verify(mClientMonitor).destroy(); + } + + @Test + public void markCanceling() { + when(mClientMonitor.getFreshDaemon()).thenReturn(mHal); + + mOperation.markCanceling(); + + assertThat(mOperation.isMarkedCanceling()).isTrue(); + assertThat(mOperation.isCanceling()).isFalse(); + assertThat(mOperation.isFinished()).isFalse(); + verify(mClientMonitor, never()).start(any()); + verify(mClientMonitor, never()).cancel(); + verify(mClientMonitor, never()).cancelWithoutStarting(any()); + verify(mClientMonitor, never()).unableToStart(); + verify(mClientMonitor, never()).destroy(); + } + + @Test + public void cancelPendingWithCookie() { + markCancellingAndStart(2); + } + + @Test + public void cancelPendingWithoutCookie() { + markCancellingAndStart(null); + } + + private void markCancellingAndStart(Integer withCookie) { + when(mClientMonitor.getFreshDaemon()).thenReturn(mHal); + if (withCookie != null) { + when(mClientMonitor.getCookie()).thenReturn(withCookie); + } + + mOperation.markCanceling(); + final BaseClientMonitor.Callback cb = mock(BaseClientMonitor.Callback.class); + if (withCookie != null) { + mOperation.startWithCookie(cb, withCookie); + } else { + mOperation.start(cb); + } + + assertThat(mOperation.isFinished()).isTrue(); + verify(cb).onClientFinished(eq(mClientMonitor), eq(true)); + verify(mClientMonitor, never()).start(any()); + verify(mClientMonitor, never()).cancel(); + verify(mClientMonitor, never()).cancelWithoutStarting(any()); + verify(mClientMonitor, never()).unableToStart(); + verify(mClientMonitor).destroy(); + } + + @Test + public void cancelWatchdogWhenStarted() { + cancelWatchdog(true); + } + + @Test + public void cancelWatchdogWithoutStarting() { + cancelWatchdog(false); + } + + private void cancelWatchdog(boolean start) { + when(mClientMonitor.getFreshDaemon()).thenReturn(mHal); + + mOperation.start(mock(BaseClientMonitor.Callback.class)); + if (start) { + verify(mClientMonitor).start(mStartCallback.capture()); + mStartCallback.getValue().onClientStarted(mClientMonitor); + } + mOperation.cancel(mHandler, mock(BaseClientMonitor.Callback.class)); + + assertThat(mOperation.isCanceling()).isTrue(); + + // omit call to onClientFinished and trigger watchdog + mOperation.mCancelWatchdog.run(); + + assertThat(mOperation.isFinished()).isTrue(); + assertThat(mOperation.isCanceling()).isFalse(); + verify(mClientMonitor).destroy(); + } +} diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java index d192697827f6..ac0831983262 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java @@ -16,10 +16,14 @@ package com.android.server.biometrics.sensors; +import static android.testing.TestableLooper.RunWithLooper; + import static junit.framework.Assert.assertTrue; +import static junit.framework.Assert.fail; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNull; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; @@ -34,10 +38,13 @@ import android.content.Context; import android.hardware.biometrics.BiometricConstants; import android.hardware.biometrics.IBiometricService; import android.os.Binder; +import android.os.Handler; import android.os.IBinder; import android.os.RemoteException; import android.platform.test.annotations.Presubmit; +import android.testing.AndroidTestingRunner; import android.testing.TestableContext; +import android.testing.TestableLooper; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -46,16 +53,18 @@ import androidx.test.filters.SmallTest; import com.android.server.biometrics.nano.BiometricSchedulerProto; import com.android.server.biometrics.nano.BiometricsProto; -import com.android.server.biometrics.sensors.BiometricScheduler.Operation; import org.junit.Before; import org.junit.Rule; import org.junit.Test; +import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; @Presubmit @SmallTest +@RunWith(AndroidTestingRunner.class) +@RunWithLooper(setAsMainLooper = true) public class BiometricSchedulerTest { private static final String TAG = "BiometricSchedulerTest"; @@ -76,8 +85,9 @@ public class BiometricSchedulerTest { public void setUp() { MockitoAnnotations.initMocks(this); mToken = new Binder(); - mScheduler = new BiometricScheduler(TAG, BiometricScheduler.SENSOR_TYPE_UNKNOWN, - null /* gestureAvailabilityTracker */, mBiometricService, LOG_NUM_RECENT_OPERATIONS, + mScheduler = new BiometricScheduler(TAG, new Handler(TestableLooper.get(this).getLooper()), + BiometricScheduler.SENSOR_TYPE_UNKNOWN, null /* gestureAvailabilityTracker */, + mBiometricService, LOG_NUM_RECENT_OPERATIONS, CoexCoordinator.getInstance()); } @@ -86,9 +96,9 @@ public class BiometricSchedulerTest { final HalClientMonitor.LazyDaemon<Object> nonNullDaemon = () -> mock(Object.class); final HalClientMonitor<Object> client1 = - new TestClientMonitor(mContext, mToken, nonNullDaemon); + new TestHalClientMonitor(mContext, mToken, nonNullDaemon); final HalClientMonitor<Object> client2 = - new TestClientMonitor(mContext, mToken, nonNullDaemon); + new TestHalClientMonitor(mContext, mToken, nonNullDaemon); mScheduler.scheduleClientMonitor(client1); mScheduler.scheduleClientMonitor(client2); @@ -99,20 +109,17 @@ public class BiometricSchedulerTest { @Test public void testRemovesPendingOperations_whenNullHal_andNotBiometricPrompt() { // Even if second client has a non-null daemon, it needs to be canceled. - Object daemon2 = mock(Object.class); - - final HalClientMonitor.LazyDaemon<Object> lazyDaemon1 = () -> null; - final HalClientMonitor.LazyDaemon<Object> lazyDaemon2 = () -> daemon2; - - final TestClientMonitor client1 = new TestClientMonitor(mContext, mToken, lazyDaemon1); - final TestClientMonitor client2 = new TestClientMonitor(mContext, mToken, lazyDaemon2); + final TestHalClientMonitor client1 = new TestHalClientMonitor( + mContext, mToken, () -> null); + final TestHalClientMonitor client2 = new TestHalClientMonitor( + mContext, mToken, () -> mock(Object.class)); final BaseClientMonitor.Callback callback1 = mock(BaseClientMonitor.Callback.class); final BaseClientMonitor.Callback callback2 = mock(BaseClientMonitor.Callback.class); // Pretend the scheduler is busy so the first operation doesn't start right away. We want // to pretend like there are two operations in the queue before kicking things off - mScheduler.mCurrentOperation = new BiometricScheduler.Operation( + mScheduler.mCurrentOperation = new BiometricSchedulerOperation( mock(BaseClientMonitor.class), mock(BaseClientMonitor.Callback.class)); mScheduler.scheduleClientMonitor(client1, callback1); @@ -122,11 +129,11 @@ public class BiometricSchedulerTest { mScheduler.scheduleClientMonitor(client2, callback2); waitForIdle(); - assertTrue(client1.wasUnableToStart()); + assertTrue(client1.mUnableToStart); verify(callback1).onClientFinished(eq(client1), eq(false) /* success */); verify(callback1, never()).onClientStarted(any()); - assertTrue(client2.wasUnableToStart()); + assertTrue(client2.mUnableToStart); verify(callback2).onClientFinished(eq(client2), eq(false) /* success */); verify(callback2, never()).onClientStarted(any()); @@ -138,21 +145,19 @@ public class BiometricSchedulerTest { // Second non-BiometricPrompt client has a valid daemon final Object daemon2 = mock(Object.class); - final HalClientMonitor.LazyDaemon<Object> lazyDaemon1 = () -> null; - final HalClientMonitor.LazyDaemon<Object> lazyDaemon2 = () -> daemon2; - final ClientMonitorCallbackConverter listener1 = mock(ClientMonitorCallbackConverter.class); final TestAuthenticationClient client1 = - new TestAuthenticationClient(mContext, lazyDaemon1, mToken, listener1); - final TestClientMonitor client2 = new TestClientMonitor(mContext, mToken, lazyDaemon2); + new TestAuthenticationClient(mContext, () -> null, mToken, listener1); + final TestHalClientMonitor client2 = + new TestHalClientMonitor(mContext, mToken, () -> daemon2); final BaseClientMonitor.Callback callback1 = mock(BaseClientMonitor.Callback.class); final BaseClientMonitor.Callback callback2 = mock(BaseClientMonitor.Callback.class); // Pretend the scheduler is busy so the first operation doesn't start right away. We want // to pretend like there are two operations in the queue before kicking things off - mScheduler.mCurrentOperation = new BiometricScheduler.Operation( + mScheduler.mCurrentOperation = new BiometricSchedulerOperation( mock(BaseClientMonitor.class), mock(BaseClientMonitor.Callback.class)); mScheduler.scheduleClientMonitor(client1, callback1); @@ -172,8 +177,8 @@ public class BiometricSchedulerTest { verify(callback1, never()).onClientStarted(any()); // Client 2 was able to start - assertFalse(client2.wasUnableToStart()); - assertTrue(client2.hasStarted()); + assertFalse(client2.mUnableToStart); + assertTrue(client2.mStarted); verify(callback2).onClientStarted(eq(client2)); } @@ -187,16 +192,18 @@ public class BiometricSchedulerTest { // Schedule a BiometricPrompt authentication request mScheduler.scheduleClientMonitor(client1, callback1); - assertEquals(Operation.STATE_WAITING_FOR_COOKIE, mScheduler.mCurrentOperation.mState); - assertEquals(client1, mScheduler.mCurrentOperation.mClientMonitor); + assertNotEquals(0, mScheduler.mCurrentOperation.isReadyToStart()); + assertEquals(client1, mScheduler.mCurrentOperation.getClientMonitor()); assertEquals(0, mScheduler.mPendingOperations.size()); // Request it to be canceled. The operation can be canceled immediately, and the scheduler // should go back to idle, since in this case the framework has not even requested the HAL // to authenticate yet. mScheduler.cancelAuthenticationOrDetection(mToken, 1 /* requestId */); + waitForIdle(); assertTrue(client1.isAlreadyDone()); assertTrue(client1.mDestroyed); + assertFalse(client1.mStartedHal); assertNull(mScheduler.mCurrentOperation); } @@ -210,8 +217,8 @@ public class BiometricSchedulerTest { // assertEquals(0, bsp.recentOperations.length); // Pretend the scheduler is busy enrolling, and check the proto dump again. - final TestClientMonitor2 client = new TestClientMonitor2(mContext, mToken, - () -> mock(Object.class), BiometricsProto.CM_ENROLL); + final TestHalClientMonitor client = new TestHalClientMonitor(mContext, mToken, + () -> mock(Object.class), 0, BiometricsProto.CM_ENROLL); mScheduler.scheduleClientMonitor(client); waitForIdle(); bsp = getDump(true /* clearSchedulerBuffer */); @@ -230,8 +237,8 @@ public class BiometricSchedulerTest { @Test public void testProtoDump_fifo() throws Exception { // Add the first operation - final TestClientMonitor2 client = new TestClientMonitor2(mContext, mToken, - () -> mock(Object.class), BiometricsProto.CM_ENROLL); + final TestHalClientMonitor client = new TestHalClientMonitor(mContext, mToken, + () -> mock(Object.class), 0, BiometricsProto.CM_ENROLL); mScheduler.scheduleClientMonitor(client); waitForIdle(); BiometricSchedulerProto bsp = getDump(false /* clearSchedulerBuffer */); @@ -244,8 +251,8 @@ public class BiometricSchedulerTest { client.getCallback().onClientFinished(client, true); // Add another operation - final TestClientMonitor2 client2 = new TestClientMonitor2(mContext, mToken, - () -> mock(Object.class), BiometricsProto.CM_REMOVE); + final TestHalClientMonitor client2 = new TestHalClientMonitor(mContext, mToken, + () -> mock(Object.class), 0, BiometricsProto.CM_REMOVE); mScheduler.scheduleClientMonitor(client2); waitForIdle(); bsp = getDump(false /* clearSchedulerBuffer */); @@ -256,8 +263,8 @@ public class BiometricSchedulerTest { client2.getCallback().onClientFinished(client2, true); // And another operation - final TestClientMonitor2 client3 = new TestClientMonitor2(mContext, mToken, - () -> mock(Object.class), BiometricsProto.CM_AUTHENTICATE); + final TestHalClientMonitor client3 = new TestHalClientMonitor(mContext, mToken, + () -> mock(Object.class), 0, BiometricsProto.CM_AUTHENTICATE); mScheduler.scheduleClientMonitor(client3); waitForIdle(); bsp = getDump(false /* clearSchedulerBuffer */); @@ -290,8 +297,7 @@ public class BiometricSchedulerTest { @Test public void testCancelPendingAuth() throws RemoteException { final HalClientMonitor.LazyDaemon<Object> lazyDaemon = () -> mock(Object.class); - - final TestClientMonitor client1 = new TestClientMonitor(mContext, mToken, lazyDaemon); + final TestHalClientMonitor client1 = new TestHalClientMonitor(mContext, mToken, lazyDaemon); final ClientMonitorCallbackConverter callback = mock(ClientMonitorCallbackConverter.class); final TestAuthenticationClient client2 = new TestAuthenticationClient(mContext, lazyDaemon, mToken, callback); @@ -302,14 +308,12 @@ public class BiometricSchedulerTest { waitForIdle(); assertEquals(mScheduler.getCurrentClient(), client1); - assertEquals(Operation.STATE_WAITING_IN_QUEUE, - mScheduler.mPendingOperations.getFirst().mState); + assertFalse(mScheduler.mPendingOperations.getFirst().isStarted()); // Request cancel before the authentication client has started mScheduler.cancelAuthenticationOrDetection(mToken, 1 /* requestId */); waitForIdle(); - assertEquals(Operation.STATE_WAITING_IN_QUEUE_CANCELING, - mScheduler.mPendingOperations.getFirst().mState); + assertTrue(mScheduler.mPendingOperations.getFirst().isMarkedCanceling()); // Finish the blocking client. The authentication client should send ERROR_CANCELED client1.getCallback().onClientFinished(client1, true /* success */); @@ -326,67 +330,109 @@ public class BiometricSchedulerTest { @Test public void testCancels_whenAuthRequestIdNotSet() { - testCancelsWhenRequestId(null /* requestId */, 2, true /* started */); + testCancelsAuthDetectWhenRequestId(null /* requestId */, 2, true /* started */); } @Test public void testCancels_whenAuthRequestIdNotSet_notStarted() { - testCancelsWhenRequestId(null /* requestId */, 2, false /* started */); + testCancelsAuthDetectWhenRequestId(null /* requestId */, 2, false /* started */); } @Test public void testCancels_whenAuthRequestIdMatches() { - testCancelsWhenRequestId(200L, 200, true /* started */); + testCancelsAuthDetectWhenRequestId(200L, 200, true /* started */); } @Test public void testCancels_whenAuthRequestIdMatches_noStarted() { - testCancelsWhenRequestId(200L, 200, false /* started */); + testCancelsAuthDetectWhenRequestId(200L, 200, false /* started */); } @Test public void testDoesNotCancel_whenAuthRequestIdMismatched() { - testCancelsWhenRequestId(10L, 20, true /* started */); + testCancelsAuthDetectWhenRequestId(10L, 20, true /* started */); } @Test public void testDoesNotCancel_whenAuthRequestIdMismatched_notStarted() { - testCancelsWhenRequestId(10L, 20, false /* started */); + testCancelsAuthDetectWhenRequestId(10L, 20, false /* started */); } - private void testCancelsWhenRequestId(@Nullable Long requestId, long cancelRequestId, + private void testCancelsAuthDetectWhenRequestId(@Nullable Long requestId, long cancelRequestId, boolean started) { - final boolean matches = requestId == null || requestId == cancelRequestId; final HalClientMonitor.LazyDaemon<Object> lazyDaemon = () -> mock(Object.class); final ClientMonitorCallbackConverter callback = mock(ClientMonitorCallbackConverter.class); - final TestAuthenticationClient client = new TestAuthenticationClient( - mContext, lazyDaemon, mToken, callback); + testCancelsWhenRequestId(requestId, cancelRequestId, started, + new TestAuthenticationClient(mContext, lazyDaemon, mToken, callback)); + } + + @Test + public void testCancels_whenEnrollRequestIdNotSet() { + testCancelsEnrollWhenRequestId(null /* requestId */, 2, false /* started */); + } + + @Test + public void testCancels_whenEnrollRequestIdMatches() { + testCancelsEnrollWhenRequestId(200L, 200, false /* started */); + } + + @Test + public void testDoesNotCancel_whenEnrollRequestIdMismatched() { + testCancelsEnrollWhenRequestId(10L, 20, false /* started */); + } + + private void testCancelsEnrollWhenRequestId(@Nullable Long requestId, long cancelRequestId, + boolean started) { + final HalClientMonitor.LazyDaemon<Object> lazyDaemon = () -> mock(Object.class); + final ClientMonitorCallbackConverter callback = mock(ClientMonitorCallbackConverter.class); + testCancelsWhenRequestId(requestId, cancelRequestId, started, + new TestEnrollClient(mContext, lazyDaemon, mToken, callback)); + } + + private void testCancelsWhenRequestId(@Nullable Long requestId, long cancelRequestId, + boolean started, HalClientMonitor<?> client) { + final boolean matches = requestId == null || requestId == cancelRequestId; if (requestId != null) { client.setRequestId(requestId); } + final boolean isAuth = client instanceof TestAuthenticationClient; + final boolean isEnroll = client instanceof TestEnrollClient; + mScheduler.scheduleClientMonitor(client); if (started) { mScheduler.startPreparedClient(client.getCookie()); } waitForIdle(); - mScheduler.cancelAuthenticationOrDetection(mToken, cancelRequestId); + if (isAuth) { + mScheduler.cancelAuthenticationOrDetection(mToken, cancelRequestId); + } else if (isEnroll) { + mScheduler.cancelEnrollment(mToken, cancelRequestId); + } else { + fail("unexpected operation type"); + } waitForIdle(); - assertEquals(matches && started ? 1 : 0, client.mNumCancels); + if (isAuth) { + // auth clients that were waiting for cookie when canceled should never invoke the hal + final TestAuthenticationClient authClient = (TestAuthenticationClient) client; + assertEquals(matches && started ? 1 : 0, authClient.mNumCancels); + assertEquals(started, authClient.mStartedHal); + } else if (isEnroll) { + final TestEnrollClient enrollClient = (TestEnrollClient) client; + assertEquals(matches ? 1 : 0, enrollClient.mNumCancels); + assertTrue(enrollClient.mStartedHal); + } if (matches) { - if (started) { - assertEquals(Operation.STATE_STARTED_CANCELING, - mScheduler.mCurrentOperation.mState); + if (started || isEnroll) { // prep'd auth clients and enroll clients + assertTrue(mScheduler.mCurrentOperation.isCanceling()); } } else { - if (started) { - assertEquals(Operation.STATE_STARTED, - mScheduler.mCurrentOperation.mState); + if (started || isEnroll) { // prep'd auth clients and enroll clients + assertTrue(mScheduler.mCurrentOperation.isStarted()); } else { - assertEquals(Operation.STATE_WAITING_FOR_COOKIE, - mScheduler.mCurrentOperation.mState); + assertNotEquals(0, mScheduler.mCurrentOperation.isReadyToStart()); } } } @@ -411,18 +457,14 @@ public class BiometricSchedulerTest { mScheduler.cancelAuthenticationOrDetection(mToken, 9999); waitForIdle(); - assertEquals(Operation.STATE_STARTED, - mScheduler.mCurrentOperation.mState); - assertEquals(Operation.STATE_WAITING_IN_QUEUE, - mScheduler.mPendingOperations.getFirst().mState); + assertTrue(mScheduler.mCurrentOperation.isStarted()); + assertFalse(mScheduler.mPendingOperations.getFirst().isStarted()); mScheduler.cancelAuthenticationOrDetection(mToken, requestId2); waitForIdle(); - assertEquals(Operation.STATE_STARTED, - mScheduler.mCurrentOperation.mState); - assertEquals(Operation.STATE_WAITING_IN_QUEUE_CANCELING, - mScheduler.mPendingOperations.getFirst().mState); + assertTrue(mScheduler.mCurrentOperation.isStarted()); + assertTrue(mScheduler.mPendingOperations.getFirst().isMarkedCanceling()); } @Test @@ -459,12 +501,12 @@ public class BiometricSchedulerTest { @Test public void testClientDestroyed_afterFinish() { final HalClientMonitor.LazyDaemon<Object> nonNullDaemon = () -> mock(Object.class); - final TestClientMonitor client = - new TestClientMonitor(mContext, mToken, nonNullDaemon); + final TestHalClientMonitor client = + new TestHalClientMonitor(mContext, mToken, nonNullDaemon); mScheduler.scheduleClientMonitor(client); client.mCallback.onClientFinished(client, true /* success */); waitForIdle(); - assertTrue(client.wasDestroyed()); + assertTrue(client.mDestroyed); } private BiometricSchedulerProto getDump(boolean clearSchedulerBuffer) throws Exception { @@ -472,8 +514,10 @@ public class BiometricSchedulerTest { } private static class TestAuthenticationClient extends AuthenticationClient<Object> { - int mNumCancels = 0; + boolean mStartedHal = false; + boolean mStoppedHal = false; boolean mDestroyed = false; + int mNumCancels = 0; public TestAuthenticationClient(@NonNull Context context, @NonNull LazyDaemon<Object> lazyDaemon, @NonNull IBinder token, @@ -488,18 +532,16 @@ public class BiometricSchedulerTest { @Override protected void stopHalOperation() { - + mStoppedHal = true; } @Override protected void startHalOperation() { - + mStartedHal = true; } @Override - protected void handleLifecycleAfterAuth(boolean authenticated) { - - } + protected void handleLifecycleAfterAuth(boolean authenticated) {} @Override public boolean wasUserDetected() { @@ -519,36 +561,59 @@ public class BiometricSchedulerTest { } } - private static class TestClientMonitor2 extends TestClientMonitor { - private final int mProtoEnum; + private static class TestEnrollClient extends EnrollClient<Object> { + boolean mStartedHal = false; + boolean mStoppedHal = false; + int mNumCancels = 0; - public TestClientMonitor2(@NonNull Context context, @NonNull IBinder token, - @NonNull LazyDaemon<Object> lazyDaemon, int protoEnum) { - super(context, token, lazyDaemon); - mProtoEnum = protoEnum; + TestEnrollClient(@NonNull Context context, + @NonNull LazyDaemon<Object> lazyDaemon, @NonNull IBinder token, + @NonNull ClientMonitorCallbackConverter listener) { + super(context, lazyDaemon, token, listener, 0 /* userId */, new byte[69], + "test" /* owner */, mock(BiometricUtils.class), + 5 /* timeoutSec */, 0 /* statsModality */, TEST_SENSOR_ID, + true /* shouldVibrate */); } @Override - public int getProtoEnum() { - return mProtoEnum; + protected void stopHalOperation() { + mStoppedHal = true; + } + + @Override + protected void startHalOperation() { + mStartedHal = true; + } + + @Override + protected boolean hasReachedEnrollmentLimit() { + return false; + } + + @Override + public void cancel() { + mNumCancels++; + super.cancel(); } } - private static class TestClientMonitor extends HalClientMonitor<Object> { + private static class TestHalClientMonitor extends HalClientMonitor<Object> { + private final int mProtoEnum; private boolean mUnableToStart; private boolean mStarted; private boolean mDestroyed; - public TestClientMonitor(@NonNull Context context, @NonNull IBinder token, + TestHalClientMonitor(@NonNull Context context, @NonNull IBinder token, @NonNull LazyDaemon<Object> lazyDaemon) { - this(context, token, lazyDaemon, 0 /* cookie */); + this(context, token, lazyDaemon, 0 /* cookie */, BiometricsProto.CM_UPDATE_ACTIVE_USER); } - public TestClientMonitor(@NonNull Context context, @NonNull IBinder token, - @NonNull LazyDaemon<Object> lazyDaemon, int cookie) { + TestHalClientMonitor(@NonNull Context context, @NonNull IBinder token, + @NonNull LazyDaemon<Object> lazyDaemon, int cookie, int protoEnum) { super(context, lazyDaemon, token /* token */, null /* listener */, 0 /* userId */, TAG, cookie, TEST_SENSOR_ID, 0 /* statsModality */, 0 /* statsAction */, 0 /* statsClient */); + mProtoEnum = protoEnum; } @Override @@ -559,9 +624,7 @@ public class BiometricSchedulerTest { @Override public int getProtoEnum() { - // Anything other than CM_NONE, which is used to represent "idle". Tests that need - // real proto enums should use TestClientMonitor2 - return BiometricsProto.CM_UPDATE_ACTIVE_USER; + return mProtoEnum; } @Override @@ -573,7 +636,7 @@ public class BiometricSchedulerTest { @Override protected void startHalOperation() { - + mStarted = true; } @Override @@ -581,22 +644,9 @@ public class BiometricSchedulerTest { super.destroy(); mDestroyed = true; } - - public boolean wasUnableToStart() { - return mUnableToStart; - } - - public boolean hasStarted() { - return mStarted; - } - - public boolean wasDestroyed() { - return mDestroyed; - } - } - private static void waitForIdle() { - InstrumentationRegistry.getInstrumentation().waitForIdleSync(); + private void waitForIdle() { + TestableLooper.get(this).processAllMessages(); } } diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/UserAwareBiometricSchedulerTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/UserAwareBiometricSchedulerTest.java index 7fccd49db04b..407f5fb04adf 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/UserAwareBiometricSchedulerTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/UserAwareBiometricSchedulerTest.java @@ -16,6 +16,8 @@ package com.android.server.biometrics.sensors; +import static android.testing.TestableLooper.RunWithLooper; + import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; @@ -28,52 +30,53 @@ import static org.mockito.Mockito.when; import android.content.Context; import android.hardware.biometrics.IBiometricService; import android.os.Binder; +import android.os.Handler; import android.os.IBinder; import android.os.UserHandle; import android.platform.test.annotations.Presubmit; +import android.testing.AndroidTestingRunner; +import android.testing.TestableLooper; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.test.InstrumentationRegistry; import androidx.test.filters.SmallTest; import org.junit.Before; import org.junit.Test; +import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.MockitoAnnotations; @Presubmit +@RunWith(AndroidTestingRunner.class) +@RunWithLooper @SmallTest public class UserAwareBiometricSchedulerTest { - private static final String TAG = "BiometricSchedulerTest"; + private static final String TAG = "UserAwareBiometricSchedulerTest"; private static final int TEST_SENSOR_ID = 0; + private Handler mHandler; private UserAwareBiometricScheduler mScheduler; - private IBinder mToken; + private IBinder mToken = new Binder(); @Mock private Context mContext; @Mock private IBiometricService mBiometricService; - private TestUserStartedCallback mUserStartedCallback; - private TestUserStoppedCallback mUserStoppedCallback; + private TestUserStartedCallback mUserStartedCallback = new TestUserStartedCallback(); + private TestUserStoppedCallback mUserStoppedCallback = new TestUserStoppedCallback(); private int mCurrentUserId = UserHandle.USER_NULL; - private boolean mStartOperationsFinish; - private int mStartUserClientCount; + private boolean mStartOperationsFinish = true; + private int mStartUserClientCount = 0; @Before public void setUp() { MockitoAnnotations.initMocks(this); - - mToken = new Binder(); - mStartOperationsFinish = true; - mStartUserClientCount = 0; - mUserStartedCallback = new TestUserStartedCallback(); - mUserStoppedCallback = new TestUserStoppedCallback(); - + mHandler = new Handler(TestableLooper.get(this).getLooper()); mScheduler = new UserAwareBiometricScheduler(TAG, + mHandler, BiometricScheduler.SENSOR_TYPE_UNKNOWN, null /* gestureAvailabilityDispatcher */, mBiometricService, @@ -117,7 +120,7 @@ public class UserAwareBiometricSchedulerTest { mCurrentUserId = UserHandle.USER_NULL; mStartOperationsFinish = false; - final BaseClientMonitor[] nextClients = new BaseClientMonitor[] { + final BaseClientMonitor[] nextClients = new BaseClientMonitor[]{ mock(BaseClientMonitor.class), mock(BaseClientMonitor.class), mock(BaseClientMonitor.class) @@ -147,11 +150,11 @@ public class UserAwareBiometricSchedulerTest { waitForIdle(); final TestStartUserClient startUserClient = - (TestStartUserClient) mScheduler.mCurrentOperation.mClientMonitor; + (TestStartUserClient) mScheduler.mCurrentOperation.getClientMonitor(); mScheduler.reset(); assertNull(mScheduler.mCurrentOperation); - final BiometricScheduler.Operation fakeOperation = new BiometricScheduler.Operation( + final BiometricSchedulerOperation fakeOperation = new BiometricSchedulerOperation( mock(BaseClientMonitor.class), new BaseClientMonitor.Callback() {}); mScheduler.mCurrentOperation = fakeOperation; startUserClient.mCallback.onClientFinished(startUserClient, true); @@ -194,8 +197,8 @@ public class UserAwareBiometricSchedulerTest { verify(nextClient).start(any()); } - private static void waitForIdle() { - InstrumentationRegistry.getInstrumentation().waitForIdleSync(); + private void waitForIdle() { + TestableLooper.get(this).processAllMessages(); } private class TestUserStoppedCallback implements StopUserClient.UserStoppedCallback { diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/SensorTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/SensorTest.java index a13dff21439d..2718bf90d857 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/SensorTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/SensorTest.java @@ -33,6 +33,7 @@ import android.platform.test.annotations.Presubmit; import androidx.test.filters.SmallTest; import com.android.server.biometrics.sensors.BiometricScheduler; +import com.android.server.biometrics.sensors.CoexCoordinator; import com.android.server.biometrics.sensors.LockoutCache; import com.android.server.biometrics.sensors.LockoutResetDispatcher; import com.android.server.biometrics.sensors.LockoutTracker; @@ -79,10 +80,13 @@ public class SensorTest { when(mContext.getSystemService(Context.BIOMETRIC_SERVICE)).thenReturn(mBiometricService); mScheduler = new UserAwareBiometricScheduler(TAG, + new Handler(mLooper.getLooper()), BiometricScheduler.SENSOR_TYPE_FACE, null /* gestureAvailabilityDispatcher */, + mBiometricService, () -> USER_ID, - mUserSwitchCallback); + mUserSwitchCallback, + CoexCoordinator.getInstance()); mHalCallback = new Sensor.HalSessionCallback(mContext, new Handler(mLooper.getLooper()), TAG, mScheduler, SENSOR_ID, USER_ID, mLockoutCache, mLockoutResetDispatcher, mHalSessionCallback); diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/hidl/Face10Test.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/hidl/Face10Test.java index 39c51d5f5e5e..21a7a8ae65b9 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/hidl/Face10Test.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/hidl/Face10Test.java @@ -32,7 +32,9 @@ import android.hardware.face.FaceSensorProperties; import android.hardware.face.FaceSensorPropertiesInternal; import android.hardware.face.IFaceServiceReceiver; import android.os.Binder; +import android.os.Handler; import android.os.IBinder; +import android.os.Looper; import android.os.UserManager; import android.platform.test.annotations.Presubmit; @@ -69,6 +71,7 @@ public class Face10Test { @Mock private BiometricScheduler mScheduler; + private final Handler mHandler = new Handler(Looper.getMainLooper()); private LockoutResetDispatcher mLockoutResetDispatcher; private com.android.server.biometrics.sensors.face.hidl.Face10 mFace10; private IBinder mBinder; @@ -97,7 +100,7 @@ public class Face10Test { resetLockoutRequiresChallenge); Face10.sSystemClock = Clock.fixed(Instant.ofEpochMilli(100), ZoneId.of("PST")); - mFace10 = new Face10(mContext, sensorProps, mLockoutResetDispatcher, mScheduler); + mFace10 = new Face10(mContext, sensorProps, mLockoutResetDispatcher, mHandler, mScheduler); mBinder = new Binder(); } diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/SensorTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/SensorTest.java index 0d520ca9a4e4..d4609b55afba 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/SensorTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/SensorTest.java @@ -33,6 +33,7 @@ import android.platform.test.annotations.Presubmit; import androidx.test.filters.SmallTest; import com.android.server.biometrics.sensors.BiometricScheduler; +import com.android.server.biometrics.sensors.CoexCoordinator; import com.android.server.biometrics.sensors.LockoutCache; import com.android.server.biometrics.sensors.LockoutResetDispatcher; import com.android.server.biometrics.sensors.LockoutTracker; @@ -79,10 +80,13 @@ public class SensorTest { when(mContext.getSystemService(Context.BIOMETRIC_SERVICE)).thenReturn(mBiometricService); mScheduler = new UserAwareBiometricScheduler(TAG, + new Handler(mLooper.getLooper()), BiometricScheduler.SENSOR_TYPE_FP_OTHER, null /* gestureAvailabilityDispatcher */, + mBiometricService, () -> USER_ID, - mUserSwitchCallback); + mUserSwitchCallback, + CoexCoordinator.getInstance()); mHalCallback = new Sensor.HalSessionCallback(mContext, new Handler(mLooper.getLooper()), TAG, mScheduler, SENSOR_ID, USER_ID, mLockoutCache, mLockoutResetDispatcher, mHalSessionCallback); diff --git a/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java b/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java index 3151552fc4c9..0a5df410bcdb 100644 --- a/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java +++ b/services/tests/servicestests/src/com/android/server/display/BrightnessTrackerTest.java @@ -33,6 +33,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ParceledListSlice; import android.database.ContentObserver; +import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.display.AmbientBrightnessDayStats; @@ -42,6 +43,7 @@ import android.hardware.display.ColorDisplayManager; import android.hardware.display.DisplayManager; import android.hardware.display.DisplayedContentSample; import android.hardware.display.DisplayedContentSamplingAttributes; +import android.hardware.input.InputSensorInfo; import android.os.BatteryManager; import android.os.Handler; import android.os.HandlerThread; @@ -63,6 +65,8 @@ import com.android.internal.R; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -84,8 +88,11 @@ public class BrightnessTrackerTest { private static final String DEFAULT_DISPLAY_ID = "123"; private static final float FLOAT_DELTA = 0.01f; + @Mock private InputSensorInfo mInputSensorInfoMock; + private BrightnessTracker mTracker; private TestInjector mInjector; + private Sensor mLightSensorFake; private static Object sHandlerLock = new Object(); private static Handler sHandler; @@ -108,9 +115,12 @@ public class BrightnessTrackerTest { @Before public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); mInjector = new TestInjector(ensureHandler()); + mLightSensorFake = new Sensor(mInputSensorInfoMock); mTracker = new BrightnessTracker(InstrumentationRegistry.getContext(), mInjector); + mTracker.setLightSensor(mLightSensorFake); mDefaultNightModeColorTemperature = InstrumentationRegistry.getContext().getResources().getInteger( R.integer.config_nightDisplayColorTemperatureDefault); @@ -834,6 +844,47 @@ public class BrightnessTrackerTest { mTracker.stop(); } + @Test + public void testLightSensorChange() { + // verify the tracker started correctly and a listener registered + startTracker(mTracker); + assertNotNull(mInjector.mSensorListener); + assertEquals(mInjector.mLightSensor, mLightSensorFake); + + // Setting the sensor to null should stop the registered listener. + mTracker.setLightSensor(null); + mInjector.waitForHandler(); + assertNull(mInjector.mSensorListener); + assertNull(mInjector.mLightSensor); + + // Resetting sensor should start listener again + mTracker.setLightSensor(mLightSensorFake); + mInjector.waitForHandler(); + assertNotNull(mInjector.mSensorListener); + assertEquals(mInjector.mLightSensor, mLightSensorFake); + + Sensor secondSensor = new Sensor(mInputSensorInfoMock); + // Setting a different listener should keep things working + mTracker.setLightSensor(secondSensor); + mInjector.waitForHandler(); + assertNotNull(mInjector.mSensorListener); + assertEquals(mInjector.mLightSensor, secondSensor); + } + + @Test + public void testSetLightSensorDoesntStartListener() { + mTracker.setLightSensor(mLightSensorFake); + assertNull(mInjector.mSensorListener); + } + + @Test + public void testNullLightSensorWontRegister() { + mTracker.setLightSensor(null); + startTracker(mTracker); + assertNull(mInjector.mSensorListener); + assertNull(mInjector.mLightSensor); + } + private InputStream getInputStream(String data) { return new ByteArrayInputStream(data.getBytes(StandardCharsets.UTF_8)); } @@ -924,6 +975,7 @@ public class BrightnessTrackerTest { private class TestInjector extends BrightnessTracker.Injector { SensorEventListener mSensorListener; + Sensor mLightSensor; BroadcastReceiver mBroadcastReceiver; DisplayManager.DisplayListener mDisplayListener; Map<String, Integer> mSecureIntSettings = new HashMap<>(); @@ -974,14 +1026,16 @@ public class BrightnessTrackerTest { @Override public void registerSensorListener(Context context, - SensorEventListener sensorListener, Handler handler) { + SensorEventListener sensorListener, Sensor lightSensor, Handler handler) { mSensorListener = sensorListener; + mLightSensor = lightSensor; } @Override public void unregisterSensorListener(Context context, SensorEventListener sensorListener) { mSensorListener = null; + mLightSensor = null; } @Override diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java index 50ebffc31035..7c0f29dce1ab 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java @@ -24,10 +24,17 @@ import static com.android.server.notification.NotificationManagerService.Notific import static com.google.common.truth.Truth.assertThat; +import static junit.framework.Assert.assertFalse; +import static junit.framework.Assert.assertTrue; + import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.nullable; +import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.INotificationManager; @@ -37,8 +44,10 @@ import android.content.pm.PackageManager; import android.content.pm.ServiceInfo; import android.content.pm.VersionedPackage; import android.os.Bundle; +import android.os.UserHandle; import android.service.notification.NotificationListenerFilter; import android.service.notification.NotificationListenerService; +import android.testing.TestableContext; import android.util.ArraySet; import android.util.Pair; import android.util.Slog; @@ -69,6 +78,7 @@ public class NotificationListenersTest extends UiServiceTestCase { NotificationManagerService mNm; @Mock private INotificationManager mINm; + private TestableContext mContext = spy(getContext()); NotificationManagerService.NotificationListeners mListeners; @@ -80,6 +90,7 @@ public class NotificationListenersTest extends UiServiceTestCase { public void setUp() throws Exception { MockitoAnnotations.initMocks(this); getContext().setMockPackageManager(mPm); + doNothing().when(mContext).sendBroadcastAsUser(any(), any(), any()); mListeners = spy(mNm.new NotificationListeners( mContext, new Object(), mock(ManagedServices.UserProfiles.class), miPm)); @@ -355,4 +366,12 @@ public class NotificationListenersTest extends UiServiceTestCase { .getDisallowedPackages()).isEmpty(); } + @Test + public void testBroadcastUsers() { + int userId = 0; + mListeners.setPackageOrComponentEnabled(mCn1.flattenToString(), userId, true, false, true); + + verify(mContext).sendBroadcastAsUser( + any(), eq(UserHandle.of(userId)), nullable(String.class)); + } } diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java index 339a0a8606cb..b98401e76cc2 100755 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java @@ -60,6 +60,7 @@ import static android.service.notification.NotificationListenerService.FLAG_FILT import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_ONGOING; import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE; import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL; +import static android.view.WindowManager.LayoutParams.TYPE_TOAST; import static com.google.common.truth.Truth.assertThat; @@ -5573,6 +5574,39 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { } @Test + public void testRateLimitedToasts_windowsRemoved() throws Exception { + final String testPackage = "testPackageName"; + assertEquals(0, mService.mToastQueue.size()); + mService.isSystemUid = false; + setToastRateIsWithinQuota(false); // rate limit reached + setIfPackageHasPermissionToAvoidToastRateLimiting(testPackage, false); + setAppInForegroundForToasts(mUid, false); + + // package is not suspended + when(mPackageManager.isPackageSuspendedForUser(testPackage, UserHandle.getUserId(mUid))) + .thenReturn(false); + + Binder token = new Binder(); + INotificationManager nmService = (INotificationManager) mService.mService; + + nmService.enqueueTextToast(testPackage, token, "Text", 2000, 0, null); + + // window token was added when enqueued + ArgumentCaptor<Binder> binderCaptor = + ArgumentCaptor.forClass(Binder.class); + verify(mWindowManagerInternal).addWindowToken(binderCaptor.capture(), + eq(TYPE_TOAST), anyInt(), eq(null)); + + // but never shown + verify(mStatusBar, times(0)) + .showToast(anyInt(), any(), any(), any(), any(), anyInt(), any()); + + // and removed when rate limited + verify(mWindowManagerInternal) + .removeWindowToken(eq(binderCaptor.getValue()), eq(true), anyInt()); + } + + @Test public void backgroundSystemCustomToast_callsSetProcessImportantAsForegroundForToast() throws Exception { final String testPackage = "testPackageName"; diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java index 49b63863fec7..dfd8f48460c0 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationRecordTest.java @@ -66,6 +66,7 @@ import android.os.Vibrator; import android.provider.Settings; import android.service.notification.Adjustment; import android.service.notification.StatusBarNotification; +import android.util.ArraySet; import android.widget.RemoteViews; import androidx.test.filters.SmallTest; @@ -1328,4 +1329,45 @@ public class NotificationRecordTest extends UiServiceTestCase { assertFalse(record.isConversation()); } + + @Test + public void mergePhoneNumbers_nulls() { + // make sure nothing dies if we just don't have any phone numbers + StatusBarNotification sbn = getNotification(PKG_N_MR1, true /* noisy */, + true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */, + false /* lights */, false /* defaultLights */, null /* group */); + NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel); + + // by default, no phone numbers + assertNull(record.getPhoneNumbers()); + + // nothing happens if we attempt to merge phone numbers but there aren't any + record.mergePhoneNumbers(null); + assertNull(record.getPhoneNumbers()); + } + + @Test + public void mergePhoneNumbers_addNumbers() { + StatusBarNotification sbn = getNotification(PKG_N_MR1, true /* noisy */, + true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */, + false /* lights */, false /* defaultLights */, null /* group */); + NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel); + + // by default, no phone numbers + assertNull(record.getPhoneNumbers()); + + // make sure it behaves properly when we merge in some real content + record.mergePhoneNumbers(new ArraySet<>( + new String[]{"16175551212", "16175552121"})); + assertTrue(record.getPhoneNumbers().contains("16175551212")); + assertTrue(record.getPhoneNumbers().contains("16175552121")); + assertFalse(record.getPhoneNumbers().contains("16175553434")); + + // now merge in a new number, make sure old ones are still there and the new one + // is also there + record.mergePhoneNumbers(new ArraySet<>(new String[]{"16175553434"})); + assertTrue(record.getPhoneNumbers().contains("16175551212")); + assertTrue(record.getPhoneNumbers().contains("16175552121")); + assertTrue(record.getPhoneNumbers().contains("16175553434")); + } } diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ValidateNotificationPeopleTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ValidateNotificationPeopleTest.java index 0bf105d62053..c12f0a965146 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/ValidateNotificationPeopleTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/ValidateNotificationPeopleTest.java @@ -19,8 +19,13 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.contains; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.isNull; +import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -29,6 +34,7 @@ import android.app.Person; import android.content.ContentProvider; import android.content.ContentResolver; import android.content.Context; +import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.os.UserManager; @@ -43,6 +49,8 @@ import com.android.server.UiServiceTestCase; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; import java.util.ArrayList; import java.util.Arrays; @@ -240,6 +248,118 @@ public class ValidateNotificationPeopleTest extends UiServiceTestCase { assertFalse(ContentProvider.uriHasUserId(queryUri.getValue())); } + @Test + public void testMergePhoneNumbers_noPhoneNumber() { + // If merge phone number is called but the contacts lookup turned up no available + // phone number (HAS_PHONE_NUMBER is false), then no query should happen. + + // setup of various bits required for querying + final Context mockContext = mock(Context.class); + final ContentResolver mockContentResolver = mock(ContentResolver.class); + when(mockContext.getContentResolver()).thenReturn(mockContentResolver); + final int contactId = 12345; + final Uri lookupUri = Uri.withAppendedPath( + ContactsContract.Contacts.CONTENT_LOOKUP_URI, String.valueOf(contactId)); + + // when the contact is looked up, we return a cursor that has one entry whose info is: + // _ID: 1 + // LOOKUP_KEY: "testlookupkey" + // STARRED: 0 + // HAS_PHONE_NUMBER: 0 + Cursor cursor = makeMockCursor(1, "testlookupkey", 0, 0); + when(mockContentResolver.query(any(), any(), any(), any(), any())).thenReturn(cursor); + + // call searchContacts and then mergePhoneNumbers, make sure we never actually + // query the content resolver for a phone number + new ValidateNotificationPeople().searchContactsAndLookupNumbers(mockContext, lookupUri); + verify(mockContentResolver, never()).query( + eq(ContactsContract.CommonDataKinds.Phone.CONTENT_URI), + eq(ValidateNotificationPeople.PHONE_LOOKUP_PROJECTION), + contains(ContactsContract.Contacts.LOOKUP_KEY), + any(), // selection args + isNull()); // sort order + } + + @Test + public void testMergePhoneNumbers_hasNumber() { + // If merge phone number is called and the contact lookup has a phone number, + // make sure there's then a subsequent query for the phone number. + + // setup of various bits required for querying + final Context mockContext = mock(Context.class); + final ContentResolver mockContentResolver = mock(ContentResolver.class); + when(mockContext.getContentResolver()).thenReturn(mockContentResolver); + final int contactId = 12345; + final Uri lookupUri = Uri.withAppendedPath( + ContactsContract.Contacts.CONTENT_LOOKUP_URI, String.valueOf(contactId)); + + // when the contact is looked up, we return a cursor that has one entry whose info is: + // _ID: 1 + // LOOKUP_KEY: "testlookupkey" + // STARRED: 0 + // HAS_PHONE_NUMBER: 1 + Cursor cursor = makeMockCursor(1, "testlookupkey", 0, 1); + + // make sure to add some specifics so this cursor is only returned for the + // contacts database lookup. + when(mockContentResolver.query(eq(lookupUri), any(), + isNull(), isNull(), isNull())).thenReturn(cursor); + + // in the case of a phone lookup, return null cursor; that's not an error case + // and we're not checking the actual storing of the phone data here. + when(mockContentResolver.query(eq(ContactsContract.CommonDataKinds.Phone.CONTENT_URI), + eq(ValidateNotificationPeople.PHONE_LOOKUP_PROJECTION), + contains(ContactsContract.Contacts.LOOKUP_KEY), + any(), isNull())).thenReturn(null); + + // call searchContacts and then mergePhoneNumbers, and check that we query + // once for the + new ValidateNotificationPeople().searchContactsAndLookupNumbers(mockContext, lookupUri); + verify(mockContentResolver, times(1)).query( + eq(ContactsContract.CommonDataKinds.Phone.CONTENT_URI), + eq(ValidateNotificationPeople.PHONE_LOOKUP_PROJECTION), + contains(ContactsContract.Contacts.LOOKUP_KEY), + eq(new String[] { "testlookupkey" }), // selection args + isNull()); // sort order + } + + // Creates a cursor that points to one item of Contacts data with the specified + // columns. + private Cursor makeMockCursor(int id, String lookupKey, int starred, int hasPhone) { + Cursor mockCursor = mock(Cursor.class); + when(mockCursor.moveToFirst()).thenReturn(true); + doAnswer(new Answer<Boolean>() { + boolean mAccessed = false; + @Override + public Boolean answer(InvocationOnMock invocation) throws Throwable { + if (!mAccessed) { + mAccessed = true; + return true; + } + return false; + } + + }).when(mockCursor).moveToNext(); + + // id + when(mockCursor.getColumnIndex(ContactsContract.Contacts._ID)).thenReturn(0); + when(mockCursor.getInt(0)).thenReturn(id); + + // lookup key + when(mockCursor.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY)).thenReturn(1); + when(mockCursor.getString(1)).thenReturn(lookupKey); + + // starred + when(mockCursor.getColumnIndex(ContactsContract.Contacts.STARRED)).thenReturn(2); + when(mockCursor.getInt(2)).thenReturn(starred); + + // has phone number + when(mockCursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER)).thenReturn(3); + when(mockCursor.getInt(3)).thenReturn(hasPhone); + + return mockCursor; + } + private void assertStringArrayEquals(String message, String[] expected, String[] result) { String expectedString = Arrays.toString(expected); String resultString = Arrays.toString(result); diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeFilteringTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeFilteringTest.java index fb1508842c9d..8ac729e29424 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeFilteringTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeFilteringTest.java @@ -17,7 +17,6 @@ package com.android.server.notification; import static android.app.Notification.CATEGORY_CALL; -import static android.app.Notification.CATEGORY_MESSAGE; import static android.app.NotificationManager.IMPORTANCE_DEFAULT; import static android.app.NotificationManager.Policy.CONVERSATION_SENDERS_ANYONE; import static android.app.NotificationManager.Policy.CONVERSATION_SENDERS_IMPORTANT; @@ -25,6 +24,7 @@ import static android.app.NotificationManager.Policy.CONVERSATION_SENDERS_NONE; import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_CALLS; import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_CONVERSATIONS; import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES; +import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_REPEAT_CALLERS; import static android.app.NotificationManager.Policy.PRIORITY_SENDERS_ANY; import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR; import static android.provider.Settings.Global.ZEN_MODE_ALARMS; @@ -43,16 +43,20 @@ import android.app.Notification; import android.app.NotificationChannel; import android.app.NotificationManager.Policy; import android.media.AudioAttributes; +import android.os.Bundle; import android.os.UserHandle; import android.service.notification.StatusBarNotification; +import android.telephony.TelephonyManager; import android.test.suitebuilder.annotation.SmallTest; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; +import android.util.ArraySet; import com.android.internal.messages.nano.SystemMessageProto.SystemMessage; import com.android.internal.util.NotificationMessagingUtil; import com.android.server.UiServiceTestCase; +import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -68,10 +72,24 @@ public class ZenModeFilteringTest extends UiServiceTestCase { private NotificationMessagingUtil mMessagingUtil; private ZenModeFiltering mZenModeFiltering; + @Mock private TelephonyManager mTelephonyManager; + + private long mTestStartTime; + @Before public void setUp() { MockitoAnnotations.initMocks(this); mZenModeFiltering = new ZenModeFiltering(mContext, mMessagingUtil); + + // for repeat callers / matchesCallFilter + mContext.addMockSystemService(TelephonyManager.class, mTelephonyManager); + mTestStartTime = System.currentTimeMillis(); + } + + @After + public void tearDown() { + // make sure to get rid of any data stored in repeat callers + mZenModeFiltering.cleanUpCallersAfter(mTestStartTime); } private NotificationRecord getNotificationRecord() { @@ -95,6 +113,29 @@ public class ZenModeFilteringTest extends UiServiceTestCase { return r; } + private Bundle makeExtrasBundleWithPeople(String[] people) { + Bundle extras = new Bundle(); + extras.putObject(Notification.EXTRA_PEOPLE_LIST, people); + return extras; + } + + // Create a notification record with the people String array as the + // bundled extras, and the numbers ArraySet as additional phone numbers. + private NotificationRecord getCallRecordWithPeopleInfo(String[] people, + ArraySet<String> numbers) { + // set up notification record + NotificationRecord r = mock(NotificationRecord.class); + StatusBarNotification sbn = mock(StatusBarNotification.class); + Notification notification = mock(Notification.class); + notification.extras = makeExtrasBundleWithPeople(people); + when(sbn.getNotification()).thenReturn(notification); + when(r.getSbn()).thenReturn(sbn); + when(r.getPhoneNumbers()).thenReturn(numbers); + when(r.getCriticality()).thenReturn(CriticalNotificationExtractor.NORMAL); + when(r.isCategory(CATEGORY_CALL)).thenReturn(true); + return r; + } + @Test public void testIsMessage() { NotificationRecord r = getNotificationRecord(); @@ -309,4 +350,180 @@ public class ZenModeFilteringTest extends UiServiceTestCase { assertFalse(mZenModeFiltering.shouldIntercept(ZEN_MODE_IMPORTANT_INTERRUPTIONS, policy, r)); } + + @Test + public void testRepeatCallers_checksPhoneNumbers() { + // set up telephony manager behavior + when(mTelephonyManager.getNetworkCountryIso()).thenReturn("us"); + + // first, record a phone call from a telephone number + String[] callNumber = new String[]{"tel:12345678910"}; + mZenModeFiltering.recordCall(getCallRecordWithPeopleInfo(callNumber, null)); + + // set up policy to only allow repeat callers + Policy policy = new Policy( + PRIORITY_CATEGORY_REPEAT_CALLERS, 0, 0, 0, CONVERSATION_SENDERS_NONE); + + // make sure that a record with the phone number in extras is correctly allowed through + NotificationRecord r = getCallRecordWithPeopleInfo(callNumber, null); + assertFalse(mZenModeFiltering.shouldIntercept(ZEN_MODE_IMPORTANT_INTERRUPTIONS, policy, r)); + + // make sure that a record with the phone number in the phone numbers array is also + // allowed through + NotificationRecord r2 = getCallRecordWithPeopleInfo(new String[]{"some_contact_uri"}, + new ArraySet<>(new String[]{"12345678910"})); + assertFalse(mZenModeFiltering.shouldIntercept( + ZEN_MODE_IMPORTANT_INTERRUPTIONS, policy, r2)); + + // A record with the phone number in neither of the above should be intercepted + NotificationRecord r3 = getCallRecordWithPeopleInfo(new String[]{"tel:10987654321"}, + new ArraySet<>(new String[]{"15555555555"})); + assertTrue(mZenModeFiltering.shouldIntercept(ZEN_MODE_IMPORTANT_INTERRUPTIONS, policy, r3)); + } + + @Test + public void testMatchesCallFilter_repeatCallers_directMatch() { + // after calls given an email with an exact string match, make sure that + // matchesCallFilter returns the right thing + String[] mailSource = new String[]{"mailto:hello.world"}; + mZenModeFiltering.recordCall(getCallRecordWithPeopleInfo(mailSource, null)); + + // set up policy to only allow repeat callers + Policy policy = new Policy( + PRIORITY_CATEGORY_REPEAT_CALLERS, 0, 0, 0, CONVERSATION_SENDERS_NONE); + + // check whether matchesCallFilter returns the right thing + Bundle inputMatches = makeExtrasBundleWithPeople(new String[]{"mailto:hello.world"}); + Bundle inputWrong = makeExtrasBundleWithPeople(new String[]{"mailto:nope"}); + assertTrue(ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS, + policy, UserHandle.SYSTEM, + inputMatches, null, 0, 0)); + assertFalse(ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS, + policy, UserHandle.SYSTEM, + inputWrong, null, 0, 0)); + } + + @Test + public void testMatchesCallFilter_repeatCallers_telephoneVariants() { + // set up telephony manager behavior + when(mTelephonyManager.getNetworkCountryIso()).thenReturn("us"); + + String[] telSource = new String[]{"tel:+1-617-555-1212"}; + mZenModeFiltering.recordCall(getCallRecordWithPeopleInfo(telSource, null)); + + // set up policy to only allow repeat callers + Policy policy = new Policy( + PRIORITY_CATEGORY_REPEAT_CALLERS, 0, 0, 0, CONVERSATION_SENDERS_NONE); + + // cases to test: + // - identical number + // - same number, different formatting + // - different number + // - garbage + Bundle identical = makeExtrasBundleWithPeople(new String[]{"tel:+1-617-555-1212"}); + Bundle same = makeExtrasBundleWithPeople(new String[]{"tel:16175551212"}); + Bundle different = makeExtrasBundleWithPeople(new String[]{"tel:123-456-7890"}); + Bundle garbage = makeExtrasBundleWithPeople(new String[]{"asdfghjkl;"}); + + assertTrue("identical numbers should match", + ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS, + policy, UserHandle.SYSTEM, + identical, null, 0, 0)); + assertTrue("equivalent but non-identical numbers should match", + ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS, + policy, UserHandle.SYSTEM, + same, null, 0, 0)); + assertFalse("non-equivalent numbers should not match", + ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS, + policy, UserHandle.SYSTEM, + different, null, 0, 0)); + assertFalse("non-tel strings should not match", + ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS, + policy, UserHandle.SYSTEM, + garbage, null, 0, 0)); + } + + @Test + public void testMatchesCallFilter_repeatCallers_urlEncodedTels() { + // this is not intended to be a supported case but is one that we have seen + // sometimes in the wild, so make sure we handle url-encoded telephone numbers correctly + // when somebody provides one. + + // set up telephony manager behavior + when(mTelephonyManager.getNetworkCountryIso()).thenReturn("us"); + + String[] telSource = new String[]{"tel:%2B16175551212"}; + mZenModeFiltering.recordCall(getCallRecordWithPeopleInfo(telSource, null)); + + // set up policy to only allow repeat callers + Policy policy = new Policy( + PRIORITY_CATEGORY_REPEAT_CALLERS, 0, 0, 0, CONVERSATION_SENDERS_NONE); + + // test cases for various forms of the same phone number and different ones + Bundle same1 = makeExtrasBundleWithPeople(new String[]{"tel:+1-617-555-1212"}); + Bundle same2 = makeExtrasBundleWithPeople(new String[]{"tel:%2B1-617-555-1212"}); + Bundle same3 = makeExtrasBundleWithPeople(new String[]{"tel:6175551212"}); + Bundle different1 = makeExtrasBundleWithPeople(new String[]{"tel:%2B16175553434"}); + Bundle different2 = makeExtrasBundleWithPeople(new String[]{"tel:+16175553434"}); + + assertTrue("same number 1 should match", + ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS, + policy, UserHandle.SYSTEM, + same1, null, 0, 0)); + assertTrue("same number 2 should match", + ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS, + policy, UserHandle.SYSTEM, + same2, null, 0, 0)); + assertTrue("same number 3 should match", + ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS, + policy, UserHandle.SYSTEM, + same3, null, 0, 0)); + assertFalse("different number 1 should not match", + ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS, + policy, UserHandle.SYSTEM, + different1, null, 0, 0)); + assertFalse("different number 2 should not match", + ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS, + policy, UserHandle.SYSTEM, + different2, null, 0, 0)); + } + + @Test + public void testMatchesCallFilter_repeatCallers_viaRecordPhoneNumbers() { + // make sure that phone numbers that are passed in via the NotificationRecord's + // cached phone numbers field (from a contact lookup if the record is provided a contact + // uri) also get recorded in the repeat callers list. + + // set up telephony manager behavior + when(mTelephonyManager.getNetworkCountryIso()).thenReturn("us"); + + String[] contactSource = new String[]{"content://contacts/lookup/uri-here"}; + ArraySet<String> contactNumbers = new ArraySet<>( + new String[]{"1-617-555-1212", "1-617-555-3434"}); + NotificationRecord record = getCallRecordWithPeopleInfo(contactSource, contactNumbers); + record.mergePhoneNumbers(contactNumbers); + mZenModeFiltering.recordCall(record); + + // set up policy to only allow repeat callers + Policy policy = new Policy( + PRIORITY_CATEGORY_REPEAT_CALLERS, 0, 0, 0, CONVERSATION_SENDERS_NONE); + + // both phone numbers should register here + Bundle tel1 = makeExtrasBundleWithPeople(new String[]{"tel:+1-617-555-1212"}); + Bundle tel2 = makeExtrasBundleWithPeople(new String[]{"tel:16175553434"}); + Bundle different = makeExtrasBundleWithPeople(new String[]{"tel:16175555656"}); + + assertTrue("contact number 1 should match", + ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS, + policy, UserHandle.SYSTEM, + tel1, null, 0, 0)); + assertTrue("contact number 2 should match", + ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS, + policy, UserHandle.SYSTEM, + tel2, null, 0, 0)); + assertFalse("different number should not match", + ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS, + policy, UserHandle.SYSTEM, + different, null, 0, 0)); + } } diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java index 4410404b0cd7..e03cf1cd83a3 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java @@ -42,6 +42,7 @@ import static com.android.os.AtomsProto.DNDModeProto.ENABLED_FIELD_NUMBER; import static com.android.os.AtomsProto.DNDModeProto.ID_FIELD_NUMBER; import static com.android.os.AtomsProto.DNDModeProto.UID_FIELD_NUMBER; import static com.android.os.AtomsProto.DNDModeProto.ZEN_MODE_FIELD_NUMBER; +import static com.android.server.notification.ZenModeHelper.RULE_LIMIT_PER_PACKAGE; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertFalse; @@ -1607,6 +1608,35 @@ public class ZenModeHelperTest extends UiServiceTestCase { } @Test + public void testAddAutomaticZenRule_beyondSystemLimit() { + for (int i = 0; i < RULE_LIMIT_PER_PACKAGE; i++) { + ScheduleInfo si = new ScheduleInfo(); + si.startHour = i; + AutomaticZenRule zenRule = new AutomaticZenRule("name" + i, + null, + new ComponentName("android", "ScheduleConditionProvider"), + ZenModeConfig.toScheduleConditionId(si), + new ZenPolicy.Builder().build(), + NotificationManager.INTERRUPTION_FILTER_PRIORITY, true); + String id = mZenModeHelperSpy.addAutomaticZenRule("android", zenRule, "test"); + assertNotNull(id); + } + try { + AutomaticZenRule zenRule = new AutomaticZenRule("name", + null, + new ComponentName("android", "ScheduleConditionProvider"), + ZenModeConfig.toScheduleConditionId(new ScheduleInfo()), + new ZenPolicy.Builder().build(), + NotificationManager.INTERRUPTION_FILTER_PRIORITY, true); + String id = mZenModeHelperSpy.addAutomaticZenRule("android", zenRule, "test"); + fail("allowed too many rules to be created"); + } catch (IllegalArgumentException e) { + // yay + } + + } + + @Test public void testAddAutomaticZenRule_CA() { AutomaticZenRule zenRule = new AutomaticZenRule("name", null, diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java index b770b3e3a55b..32cee44ce6ff 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java @@ -3065,11 +3065,11 @@ public class ActivityRecordTests extends WindowTestsBase { // Simulate app re-start input or turning screen off/on then unlocked by un-secure // keyguard to back to the app, expect IME insets is not frozen + mDisplayContent.updateImeInputAndControlTarget(app); + assertFalse(app.mActivityRecord.mImeInsetsFrozenUntilStartInput); imeSource.setFrame(new Rect(100, 400, 500, 500)); app.getInsetsState().addSource(imeSource); app.getInsetsState().setSourceVisible(ITYPE_IME, true); - mDisplayContent.updateImeInputAndControlTarget(app); - assertFalse(app.mActivityRecord.mImeInsetsFrozenUntilStartInput); // Verify when IME is visible and the app can receive the right IME insets from policy. makeWindowVisibleAndDrawn(app, mImeWindow); diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java index f3c1ec5b200e..9c0c213c3efe 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java @@ -1075,6 +1075,21 @@ public class DisplayContentTests extends WindowTestsBase { assertEquals(dc.getImeContainer().getParentSurfaceControl(), dc.computeImeParent()); } + @UseTestDisplay(addWindows = W_ACTIVITY) + @Test + public void testComputeImeParent_inputTargetNotUpdate() throws Exception { + WindowState app1 = createWindow(null, TYPE_BASE_APPLICATION, "app1"); + WindowState app2 = createWindow(null, TYPE_BASE_APPLICATION, "app2"); + doReturn(true).when(mDisplayContent).shouldImeAttachedToApp(); + mDisplayContent.setImeLayeringTarget(app1); + mDisplayContent.setImeInputTarget(app1); + assertEquals(app1.mActivityRecord.getSurfaceControl(), mDisplayContent.computeImeParent()); + mDisplayContent.setImeLayeringTarget(app2); + // Expect null means no change IME parent when the IME layering target not yet + // request IME to be the input target. + assertNull(mDisplayContent.computeImeParent()); + } + @Test public void testInputMethodInputTarget_isClearedWhenWindowStateIsRemoved() throws Exception { final DisplayContent dc = createNewDisplay(); diff --git a/services/tests/wmtests/src/com/android/server/wm/PendingRemoteAnimationRegistryTest.java b/services/tests/wmtests/src/com/android/server/wm/PendingRemoteAnimationRegistryTest.java index f0071499a2f9..972567b10da7 100644 --- a/services/tests/wmtests/src/com/android/server/wm/PendingRemoteAnimationRegistryTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/PendingRemoteAnimationRegistryTest.java @@ -21,6 +21,7 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import android.app.ActivityOptions; +import android.os.IBinder; import android.platform.test.annotations.Presubmit; import android.view.RemoteAnimationAdapter; @@ -45,6 +46,7 @@ import org.mockito.MockitoAnnotations; public class PendingRemoteAnimationRegistryTest { @Mock RemoteAnimationAdapter mAdapter; + @Mock IBinder mLaunchCookie; private PendingRemoteAnimationRegistry mRegistry; private final OffsettableClock mClock = new OffsettableClock.Stopped(); private TestHandler mHandler; @@ -65,7 +67,7 @@ public class PendingRemoteAnimationRegistryTest { @Test public void testOverrideActivityOptions() { - mRegistry.addPendingAnimation("com.android.test", mAdapter); + mRegistry.addPendingAnimation("com.android.test", mAdapter, null /* launchCookie */); ActivityOptions opts = ActivityOptions.makeBasic(); opts = mRegistry.overrideOptionsIfNeeded("com.android.test", opts); assertEquals(mAdapter, opts.getRemoteAnimationAdapter()); @@ -73,15 +75,24 @@ public class PendingRemoteAnimationRegistryTest { @Test public void testOverrideActivityOptions_null() { - mRegistry.addPendingAnimation("com.android.test", mAdapter); + mRegistry.addPendingAnimation("com.android.test", mAdapter, null /* launchCookie */); final ActivityOptions opts = mRegistry.overrideOptionsIfNeeded("com.android.test", null); assertNotNull(opts); assertEquals(mAdapter, opts.getRemoteAnimationAdapter()); } @Test + public void testOverrideLaunchCookie() { + mRegistry.addPendingAnimation("com.android.test", mAdapter, mLaunchCookie); + ActivityOptions opts = ActivityOptions.makeBasic(); + opts = mRegistry.overrideOptionsIfNeeded("com.android.test", opts); + assertNotNull(opts); + assertEquals(mLaunchCookie, opts.getLaunchCookie()); + } + + @Test public void testTimeout() { - mRegistry.addPendingAnimation("com.android.test", mAdapter); + mRegistry.addPendingAnimation("com.android.test", mAdapter, null /* launchCookie */); mClock.fastForward(5000); mHandler.timeAdvance(); assertNull(mRegistry.overrideOptionsIfNeeded("com.android.test", null)); @@ -89,10 +100,10 @@ public class PendingRemoteAnimationRegistryTest { @Test public void testTimeout_overridenEntry() { - mRegistry.addPendingAnimation("com.android.test", mAdapter); + mRegistry.addPendingAnimation("com.android.test", mAdapter, null /* launchCookie */); mClock.fastForward(2500); mHandler.timeAdvance(); - mRegistry.addPendingAnimation("com.android.test", mAdapter); + mRegistry.addPendingAnimation("com.android.test", mAdapter, null /* launchCookie */); mClock.fastForward(1000); mHandler.timeAdvance(); final ActivityOptions opts = mRegistry.overrideOptionsIfNeeded("com.android.test", null); diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java index e6ad68aafaec..03b818843aa2 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java @@ -800,7 +800,6 @@ public class WindowStateTests extends WindowTestsBase { @Test public void testHasActiveVisibleWindow() { final int uid = ActivityBuilder.DEFAULT_FAKE_UID; - mAtm.mActiveUids.onUidActive(uid, 0 /* any proc state */); final WindowState app = createWindow(null, TYPE_APPLICATION, "app", uid); app.mActivityRecord.setVisible(false); @@ -828,6 +827,11 @@ public class WindowStateTests extends WindowTestsBase { // Make the application overlay window visible. It should be a valid active visible window. overlay.onSurfaceShownChanged(true); assertTrue(mAtm.hasActiveVisibleWindow(uid)); + + // The number of windows should be independent of the existence of uid state. + mAtm.mActiveUids.onUidInactive(uid); + mAtm.mActiveUids.onUidActive(uid, 0 /* any proc state */); + assertTrue(mAtm.mActiveUids.hasNonAppVisibleWindow(uid)); } @UseTestDisplay(addWindows = W_ACTIVITY) @@ -927,6 +931,47 @@ public class WindowStateTests extends WindowTestsBase { @UseTestDisplay(addWindows = { W_ACTIVITY }) @Test + public void testAdjustImeInsetsVisibilityWhenSwitchingApps_toAppInMultiWindowMode() { + final WindowState app = createWindow(null, TYPE_APPLICATION, "app"); + final WindowState app2 = createWindow(null, WINDOWING_MODE_MULTI_WINDOW, + ACTIVITY_TYPE_STANDARD, TYPE_APPLICATION, mDisplayContent, "app2"); + final WindowState imeWindow = createWindow(null, TYPE_APPLICATION, "imeWindow"); + spyOn(imeWindow); + doReturn(true).when(imeWindow).isVisible(); + mDisplayContent.mInputMethodWindow = imeWindow; + + final InsetsStateController controller = mDisplayContent.getInsetsStateController(); + controller.getImeSourceProvider().setWindow(imeWindow, null, null); + + // Simulate app2 in multi-window mode is going to background to switch to the fullscreen + // app which requests IME with updating all windows Insets State when IME is above app. + app2.mActivityRecord.mImeInsetsFrozenUntilStartInput = true; + mDisplayContent.setImeLayeringTarget(app); + mDisplayContent.setImeInputTarget(app); + assertTrue(mDisplayContent.shouldImeAttachedToApp()); + controller.getImeSourceProvider().scheduleShowImePostLayout(app); + controller.getImeSourceProvider().getSource().setVisible(true); + controller.updateAboveInsetsState(imeWindow, false); + + // Expect app windows behind IME can receive IME insets visible, + // but not for app2 in background. + assertTrue(app.getInsetsState().getSource(ITYPE_IME).isVisible()); + assertFalse(app2.getInsetsState().getSource(ITYPE_IME).isVisible()); + + // Simulate app plays closing transition to app2. + // And app2 is now IME layering target but not yet to be the IME input target. + mDisplayContent.setImeLayeringTarget(app2); + app.mActivityRecord.commitVisibility(false, false); + assertTrue(app.mActivityRecord.mLastImeShown); + assertTrue(app.mActivityRecord.mImeInsetsFrozenUntilStartInput); + + // Verify the IME insets is still visible on app, but not for app2 during task switching. + assertTrue(app.getInsetsState().getSource(ITYPE_IME).isVisible()); + assertFalse(app2.getInsetsState().getSource(ITYPE_IME).isVisible()); + } + + @UseTestDisplay(addWindows = {W_ACTIVITY}) + @Test public void testUpdateImeControlTargetWhenLeavingMultiWindow() { WindowState app = createWindow(null, TYPE_BASE_APPLICATION, mAppWindow.mToken, "app"); diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java index 36bb375be3c8..fd3b18a7b6d4 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java @@ -20,9 +20,30 @@ import static android.Manifest.permission.CAPTURE_AUDIO_HOTWORD; import static android.Manifest.permission.RECORD_AUDIO; import static android.service.voice.HotwordDetectionService.AUDIO_SOURCE_EXTERNAL; import static android.service.voice.HotwordDetectionService.AUDIO_SOURCE_MICROPHONE; +import static android.service.voice.HotwordDetectionService.INITIALIZATION_STATUS_SUCCESS; import static android.service.voice.HotwordDetectionService.INITIALIZATION_STATUS_UNKNOWN; import static android.service.voice.HotwordDetectionService.KEY_INITIALIZATION_STATUS; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTION_SERVICE_INIT_RESULT_REPORTED__RESULT__CALLBACK_INIT_STATE_ERROR; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTION_SERVICE_INIT_RESULT_REPORTED__RESULT__CALLBACK_INIT_STATE_SUCCESS; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTION_SERVICE_INIT_RESULT_REPORTED__RESULT__CALLBACK_INIT_STATE_UNKNOWN_NO_VALUE; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTION_SERVICE_INIT_RESULT_REPORTED__RESULT__CALLBACK_INIT_STATE_UNKNOWN_OVER_MAX_CUSTOM_VALUE; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTION_SERVICE_INIT_RESULT_REPORTED__RESULT__CALLBACK_INIT_STATE_UNKNOWN_TIMEOUT; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTION_SERVICE_RESTARTED__REASON__AUDIO_SERVICE_DIED; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTION_SERVICE_RESTARTED__REASON__SCHEDULE; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS__EVENT__CALLBACK_UPDATE_STATE_AFTER_TIMEOUT; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS__EVENT__ON_CONNECTED; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS__EVENT__REQUEST_BIND_SERVICE; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS__EVENT__REQUEST_BIND_SERVICE_FAIL; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS__EVENT__REQUEST_UPDATE_STATE; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__DETECTOR_TYPE__NORMAL_DETECTOR; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__DETECTOR_TYPE__TRUSTED_DETECTOR_DSP; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__DETECTED; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__DETECT_EXCEPTION; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__DETECT_TIMEOUT; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__KEYPHRASE_TRIGGER; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__REJECTED; + import android.annotation.NonNull; import android.annotation.Nullable; import android.content.ComponentName; @@ -46,6 +67,7 @@ import android.os.Process; import android.os.RemoteException; import android.os.ServiceManager; import android.os.SharedMemory; +import android.provider.DeviceConfig; import android.service.voice.HotwordDetectedResult; import android.service.voice.HotwordDetectionService; import android.service.voice.HotwordRejectedResult; @@ -88,21 +110,44 @@ final class HotwordDetectionConnection { private static final String TAG = "HotwordDetectionConnection"; static final boolean DEBUG = false; + private static final String KEY_RESTART_PERIOD_IN_SECONDS = "restart_period_in_seconds"; // TODO: These constants need to be refined. - private static final long VALIDATION_TIMEOUT_MILLIS = 3000; + private static final long VALIDATION_TIMEOUT_MILLIS = 4000; private static final long MAX_UPDATE_TIMEOUT_MILLIS = 6000; private static final Duration MAX_UPDATE_TIMEOUT_DURATION = Duration.ofMillis(MAX_UPDATE_TIMEOUT_MILLIS); private static final long RESET_DEBUG_HOTWORD_LOGGING_TIMEOUT_MILLIS = 60 * 60 * 1000; // 1 hour + /** + * Time after which each HotwordDetectionService process is stopped and replaced by a new one. + * 0 indicates no restarts. + */ + private static final int RESTART_PERIOD_SECONDS = + DeviceConfig.getInt(DeviceConfig.NAMESPACE_VOICE_INTERACTION, + KEY_RESTART_PERIOD_IN_SECONDS, 3600); // 60 minutes by default + private static final int MAX_ISOLATED_PROCESS_NUMBER = 10; + + // Hotword metrics + private static final int METRICS_INIT_UNKNOWN_TIMEOUT = + HOTWORD_DETECTION_SERVICE_INIT_RESULT_REPORTED__RESULT__CALLBACK_INIT_STATE_UNKNOWN_TIMEOUT; + private static final int METRICS_INIT_UNKNOWN_NO_VALUE = + HOTWORD_DETECTION_SERVICE_INIT_RESULT_REPORTED__RESULT__CALLBACK_INIT_STATE_UNKNOWN_NO_VALUE; + private static final int METRICS_INIT_UNKNOWN_OVER_MAX_CUSTOM_VALUE = + HOTWORD_DETECTION_SERVICE_INIT_RESULT_REPORTED__RESULT__CALLBACK_INIT_STATE_UNKNOWN_OVER_MAX_CUSTOM_VALUE; + private static final int METRICS_INIT_CALLBACK_STATE_ERROR = + HOTWORD_DETECTION_SERVICE_INIT_RESULT_REPORTED__RESULT__CALLBACK_INIT_STATE_ERROR; + private static final int METRICS_INIT_CALLBACK_STATE_SUCCESS = + HOTWORD_DETECTION_SERVICE_INIT_RESULT_REPORTED__RESULT__CALLBACK_INIT_STATE_SUCCESS; private final Executor mAudioCopyExecutor = Executors.newCachedThreadPool(); // TODO: This may need to be a Handler(looper) private final ScheduledExecutorService mScheduledExecutorService = Executors.newSingleThreadScheduledExecutor(); + @Nullable private final ScheduledFuture<?> mCancellationTaskFuture; private final AtomicBoolean mUpdateStateAfterStartFinished = new AtomicBoolean(false); private final IBinder.DeathRecipient mAudioServerDeathRecipient = this::audioServerDied; private final @NonNull ServiceConnectionFactory mServiceConnectionFactory; private final IHotwordRecognitionStatusCallback mCallback; + private final int mDetectorType; final Object mLock; final int mVoiceInteractionServiceUid; @@ -113,7 +158,7 @@ final class HotwordDetectionConnection { private IMicrophoneHotwordDetectionVoiceInteractionCallback mSoftwareCallback; private Instant mLastRestartInstant; - private ScheduledFuture<?> mCancellationTaskFuture; + private ScheduledFuture<?> mCancellationKeyPhraseDetectionFuture; private ScheduledFuture<?> mDebugHotwordLoggingTimeoutFuture = null; /** Identity used for attributing app ops when delivering data to the Interactor. */ @@ -134,7 +179,7 @@ final class HotwordDetectionConnection { Identity voiceInteractorIdentity, ComponentName serviceName, int userId, boolean bindInstantServiceAllowed, @Nullable PersistableBundle options, @Nullable SharedMemory sharedMemory, - @NonNull IHotwordRecognitionStatusCallback callback) { + @NonNull IHotwordRecognitionStatusCallback callback, int detectorType) { if (callback == null) { Slog.w(TAG, "Callback is null while creating connection"); throw new IllegalArgumentException("Callback is null while creating connection"); @@ -146,6 +191,7 @@ final class HotwordDetectionConnection { mDetectionComponentName = serviceName; mUser = userId; mCallback = callback; + mDetectorType = detectorType; final Intent intent = new Intent(HotwordDetectionService.SERVICE_INTERFACE); intent.setComponent(mDetectionComponentName); initAudioFlingerLocked(); @@ -157,14 +203,20 @@ final class HotwordDetectionConnection { mLastRestartInstant = Instant.now(); updateStateAfterProcessStart(options, sharedMemory); - // TODO(volnov): we need to be smarter here, e.g. schedule it a bit more often, but wait - // until the current session is closed. - mCancellationTaskFuture = mScheduledExecutorService.scheduleAtFixedRate(() -> { - Slog.v(TAG, "Time to restart the process, TTL has passed"); - synchronized (mLock) { - restartProcessLocked(); - } - }, 30, 30, TimeUnit.MINUTES); + if (RESTART_PERIOD_SECONDS <= 0) { + mCancellationTaskFuture = null; + } else { + // TODO(volnov): we need to be smarter here, e.g. schedule it a bit more often, but wait + // until the current session is closed. + mCancellationTaskFuture = mScheduledExecutorService.scheduleAtFixedRate(() -> { + Slog.v(TAG, "Time to restart the process, TTL has passed"); + synchronized (mLock) { + restartProcessLocked(); + HotwordMetricsLogger.writeServiceRestartEvent(mDetectorType, + HOTWORD_DETECTION_SERVICE_RESTARTED__REASON__SCHEDULE); + } + }, RESTART_PERIOD_SECONDS, RESTART_PERIOD_SECONDS, TimeUnit.SECONDS); + } } private void initAudioFlingerLocked() { @@ -195,6 +247,8 @@ final class HotwordDetectionConnection { // We restart the process instead of simply sending over the new binder, to avoid race // conditions with audio reading in the service. restartProcessLocked(); + HotwordMetricsLogger.writeServiceRestartEvent(mDetectorType, + HOTWORD_DETECTION_SERVICE_RESTARTED__REASON__AUDIO_SERVICE_DIED); } } @@ -214,26 +268,30 @@ final class HotwordDetectionConnection { future.complete(null); if (mUpdateStateAfterStartFinished.getAndSet(true)) { Slog.w(TAG, "call callback after timeout"); + HotwordMetricsLogger.writeDetectorEvent(mDetectorType, + HOTWORD_DETECTOR_EVENTS__EVENT__CALLBACK_UPDATE_STATE_AFTER_TIMEOUT, + mVoiceInteractionServiceUid); return; } - int status = bundle != null ? bundle.getInt( - KEY_INITIALIZATION_STATUS, - INITIALIZATION_STATUS_UNKNOWN) - : INITIALIZATION_STATUS_UNKNOWN; - // Add the protection to avoid unexpected status - if (status > HotwordDetectionService.getMaxCustomInitializationStatus() - && status != INITIALIZATION_STATUS_UNKNOWN) { - status = INITIALIZATION_STATUS_UNKNOWN; - } + Pair<Integer, Integer> statusResultPair = getInitStatusAndMetricsResult(bundle); + int status = statusResultPair.first; + int initResultMetricsResult = statusResultPair.second; try { mCallback.onStatusReported(status); + HotwordMetricsLogger.writeServiceInitResultEvent(mDetectorType, + initResultMetricsResult); } catch (RemoteException e) { Slog.w(TAG, "Failed to report initialization status: " + e); + HotwordMetricsLogger.writeServiceInitResultEvent(mDetectorType, + METRICS_INIT_CALLBACK_STATE_ERROR); } } }; try { service.updateState(options, sharedMemory, statusCallback); + HotwordMetricsLogger.writeDetectorEvent(mDetectorType, + HOTWORD_DETECTOR_EVENTS__EVENT__REQUEST_UPDATE_STATE, + mVoiceInteractionServiceUid); } catch (RemoteException e) { // TODO: (b/181842909) Report an error to voice interactor Slog.w(TAG, "Failed to updateState for HotwordDetectionService", e); @@ -248,8 +306,12 @@ final class HotwordDetectionConnection { } try { mCallback.onStatusReported(INITIALIZATION_STATUS_UNKNOWN); + HotwordMetricsLogger.writeServiceInitResultEvent(mDetectorType, + METRICS_INIT_UNKNOWN_TIMEOUT); } catch (RemoteException e) { Slog.w(TAG, "Failed to report initialization status UNKNOWN", e); + HotwordMetricsLogger.writeServiceInitResultEvent(mDetectorType, + METRICS_INIT_CALLBACK_STATE_ERROR); } } else if (err != null) { Slog.w(TAG, "Failed to update state: " + err); @@ -259,6 +321,24 @@ final class HotwordDetectionConnection { }); } + private static Pair<Integer, Integer> getInitStatusAndMetricsResult(Bundle bundle) { + if (bundle == null) { + return new Pair<>(INITIALIZATION_STATUS_UNKNOWN, METRICS_INIT_UNKNOWN_NO_VALUE); + } + int status = bundle.getInt(KEY_INITIALIZATION_STATUS, INITIALIZATION_STATUS_UNKNOWN); + if (status > HotwordDetectionService.getMaxCustomInitializationStatus()) { + return new Pair<>(INITIALIZATION_STATUS_UNKNOWN, + status == INITIALIZATION_STATUS_UNKNOWN + ? METRICS_INIT_UNKNOWN_NO_VALUE + :METRICS_INIT_UNKNOWN_OVER_MAX_CUSTOM_VALUE); + } + // TODO: should guard against negative here + int metricsResult = status == INITIALIZATION_STATUS_SUCCESS + ? METRICS_INIT_CALLBACK_STATE_SUCCESS + : METRICS_INIT_CALLBACK_STATE_ERROR; + return new Pair<>(status, metricsResult); + } + private boolean isBound() { synchronized (mLock) { return mRemoteHotwordDetectionService.isBound(); @@ -274,7 +354,9 @@ final class HotwordDetectionConnection { .setHotwordDetectionServiceProvider(null); mIdentity = null; updateServiceUidForAudioPolicy(Process.INVALID_UID); - mCancellationTaskFuture.cancel(/* may interrupt */ true); + if (mCancellationTaskFuture != null) { + mCancellationTaskFuture.cancel(/* may interrupt */ true); + } if (mAudioFlinger != null) { mAudioFlinger.unlinkToDeath(mAudioServerDeathRecipient, /* flags= */ 0); } @@ -473,12 +555,31 @@ final class HotwordDetectionConnection { Slog.d(TAG, "onDetected"); } synchronized (mLock) { + // TODO: If the dsp trigger comes in after the timeout, we will log both events. + // Because we don't enforce the timeout yet. We should add some synchronizations + // within the runnable to prevent the race condition to log both events. + if (mCancellationKeyPhraseDetectionFuture != null) { + mCancellationKeyPhraseDetectionFuture.cancel(true); + } + HotwordMetricsLogger.writeKeyphraseTriggerEvent( + mDetectorType, + HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__DETECTED); if (!mValidatingDspTrigger) { Slog.i(TAG, "Ignoring #onDetected due to a process restart"); + HotwordMetricsLogger.writeKeyphraseTriggerEvent( + mDetectorType, + HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__DETECT_EXCEPTION); return; } mValidatingDspTrigger = false; - enforcePermissionsForDataDelivery(); + try { + enforcePermissionsForDataDelivery(); + } catch (SecurityException e) { + HotwordMetricsLogger.writeKeyphraseTriggerEvent( + mDetectorType, + HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__DETECT_EXCEPTION); + throw e; + } externalCallback.onKeyphraseDetected(recognitionEvent, result); if (result != null) { Slog.i(TAG, "Egressed " + HotwordDetectedResult.getUsageSize(result) @@ -496,8 +597,17 @@ final class HotwordDetectionConnection { Slog.d(TAG, "onRejected"); } synchronized (mLock) { + if (mCancellationKeyPhraseDetectionFuture != null) { + mCancellationKeyPhraseDetectionFuture.cancel(true); + } + HotwordMetricsLogger.writeKeyphraseTriggerEvent( + mDetectorType, + HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__REJECTED); if (!mValidatingDspTrigger) { Slog.i(TAG, "Ignoring #onRejected due to a process restart"); + HotwordMetricsLogger.writeKeyphraseTriggerEvent( + mDetectorType, + HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__DETECT_EXCEPTION); return; } mValidatingDspTrigger = false; @@ -512,11 +622,20 @@ final class HotwordDetectionConnection { synchronized (mLock) { mValidatingDspTrigger = true; mRemoteHotwordDetectionService.run( - service -> service.detectFromDspSource( - recognitionEvent, - recognitionEvent.getCaptureFormat(), - VALIDATION_TIMEOUT_MILLIS, - internalCallback)); + service -> { + // TODO: avoid allocate every time + mCancellationKeyPhraseDetectionFuture = mScheduledExecutorService.schedule( + () -> HotwordMetricsLogger + .writeKeyphraseTriggerEvent(mDetectorType, + HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__DETECT_TIMEOUT), + VALIDATION_TIMEOUT_MILLIS, + TimeUnit.MILLISECONDS); + service.detectFromDspSource( + recognitionEvent, + recognitionEvent.getCaptureFormat(), + VALIDATION_TIMEOUT_MILLIS, + internalCallback); + }); } } @@ -617,10 +736,16 @@ final class HotwordDetectionConnection { } final boolean useHotwordDetectionService = mHotwordDetectionConnection != null; if (useHotwordDetectionService) { + HotwordMetricsLogger.writeKeyphraseTriggerEvent( + HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__DETECTOR_TYPE__TRUSTED_DETECTOR_DSP, + HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__KEYPHRASE_TRIGGER); mRecognitionEvent = recognitionEvent; mHotwordDetectionConnection.detectFromDspSource( recognitionEvent, mExternalCallback); } else { + HotwordMetricsLogger.writeKeyphraseTriggerEvent( + HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__DETECTOR_TYPE__NORMAL_DETECTOR, + HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__KEYPHRASE_TRIGGER); mExternalCallback.onKeyphraseDetected(recognitionEvent, null); } } @@ -649,6 +774,7 @@ final class HotwordDetectionConnection { } public void dump(String prefix, PrintWriter pw) { + pw.print(prefix); pw.print("RESTART_PERIOD_SECONDS="); pw.println(RESTART_PERIOD_SECONDS); pw.print(prefix); pw.print("mBound=" + mRemoteHotwordDetectionService.isBound()); pw.print(", mValidatingDspTrigger=" + mValidatingDspTrigger); @@ -764,7 +890,8 @@ final class HotwordDetectionConnection { ServiceConnection createLocked() { ServiceConnection connection = new ServiceConnection(mContext, mIntent, mBindingFlags, mUser, - IHotwordDetectionService.Stub::asInterface, ++mRestartCount); + IHotwordDetectionService.Stub::asInterface, + mRestartCount++ % MAX_ISOLATED_PROCESS_NUMBER); connection.connect(); updateAudioFlinger(connection, mAudioFlinger); @@ -783,6 +910,7 @@ final class HotwordDetectionConnection { private boolean mRespectServiceConnectionStatusChanged = true; private boolean mIsBound = false; + private boolean mIsLoggedFirstConnect = false; ServiceConnection(@NonNull Context context, @NonNull Intent intent, int bindingFlags, int userId, @@ -806,6 +934,12 @@ final class HotwordDetectionConnection { return; } mIsBound = connected; + if (connected && !mIsLoggedFirstConnect) { + mIsLoggedFirstConnect = true; + HotwordMetricsLogger.writeDetectorEvent(mDetectorType, + HOTWORD_DETECTOR_EVENTS__EVENT__ON_CONNECTED, + mVoiceInteractionServiceUid); + } } } @@ -836,13 +970,25 @@ final class HotwordDetectionConnection { protected boolean bindService( @NonNull android.content.ServiceConnection serviceConnection) { try { - return mContext.bindIsolatedService( + HotwordMetricsLogger.writeDetectorEvent(mDetectorType, + HOTWORD_DETECTOR_EVENTS__EVENT__REQUEST_BIND_SERVICE, + mVoiceInteractionServiceUid); + boolean bindResult = mContext.bindIsolatedService( mIntent, Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE | mBindingFlags, "hotword_detector_" + mInstanceNumber, mExecutor, serviceConnection); + if (!bindResult) { + HotwordMetricsLogger.writeDetectorEvent(mDetectorType, + HOTWORD_DETECTOR_EVENTS__EVENT__REQUEST_BIND_SERVICE_FAIL, + mVoiceInteractionServiceUid); + } + return bindResult; } catch (IllegalArgumentException e) { + HotwordMetricsLogger.writeDetectorEvent(mDetectorType, + HOTWORD_DETECTOR_EVENTS__EVENT__REQUEST_BIND_SERVICE_FAIL, + mVoiceInteractionServiceUid); Slog.wtf(TAG, "Can't bind to the hotword detection service!", e); return false; } diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordMetricsLogger.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordMetricsLogger.java new file mode 100644 index 000000000000..940aed34b7fb --- /dev/null +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordMetricsLogger.java @@ -0,0 +1,154 @@ +/* + * 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.server.voiceinteraction; + +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTION_SERVICE_INIT_RESULT_REPORTED__DETECTOR_TYPE__NORMAL_DETECTOR; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTION_SERVICE_INIT_RESULT_REPORTED__DETECTOR_TYPE__TRUSTED_DETECTOR_DSP; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTION_SERVICE_INIT_RESULT_REPORTED__DETECTOR_TYPE__TRUSTED_DETECTOR_SOFTWARE; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTION_SERVICE_RESTARTED__DETECTOR_TYPE__NORMAL_DETECTOR; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTION_SERVICE_RESTARTED__DETECTOR_TYPE__TRUSTED_DETECTOR_DSP; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTION_SERVICE_RESTARTED__DETECTOR_TYPE__TRUSTED_DETECTOR_SOFTWARE; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_CREATE_REQUESTED__DETECTOR_TYPE__NORMAL_DETECTOR; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_CREATE_REQUESTED__DETECTOR_TYPE__TRUSTED_DETECTOR_DSP; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_CREATE_REQUESTED__DETECTOR_TYPE__TRUSTED_DETECTOR_SOFTWARE; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS__DETECTOR_TYPE__NORMAL_DETECTOR; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS__DETECTOR_TYPE__TRUSTED_DETECTOR_DSP; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS__DETECTOR_TYPE__TRUSTED_DETECTOR_SOFTWARE; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__DETECTOR_TYPE__NORMAL_DETECTOR; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__DETECTOR_TYPE__TRUSTED_DETECTOR_DSP; +import static com.android.internal.util.FrameworkStatsLog.HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__DETECTOR_TYPE__TRUSTED_DETECTOR_SOFTWARE; + +import android.service.voice.HotwordDetector; + +import com.android.internal.util.FrameworkStatsLog; + +/** + * A utility class for logging hotword statistics event. + */ +public final class HotwordMetricsLogger { + + private static final int METRICS_INIT_DETECTOR_SOFTWARE = + HOTWORD_DETECTION_SERVICE_INIT_RESULT_REPORTED__DETECTOR_TYPE__TRUSTED_DETECTOR_SOFTWARE; + private static final int METRICS_INIT_DETECTOR_DSP = + HOTWORD_DETECTION_SERVICE_INIT_RESULT_REPORTED__DETECTOR_TYPE__TRUSTED_DETECTOR_DSP; + private static final int METRICS_INIT_NORMAL_DETECTOR = + HOTWORD_DETECTION_SERVICE_INIT_RESULT_REPORTED__DETECTOR_TYPE__NORMAL_DETECTOR; + + private HotwordMetricsLogger() { + // Class only contains static utility functions, and should not be instantiated + } + + /** + * Logs information related to create hotword detector. + */ + public static void writeDetectorCreateEvent(int detectorType, boolean isCreated, int uid) { + int metricsDetectorType = getCreateMetricsDetectorType(detectorType); + FrameworkStatsLog.write(FrameworkStatsLog.HOTWORD_DETECTOR_CREATE_REQUESTED, + metricsDetectorType, isCreated, uid); + } + + /** + * Logs information related to hotword detection service init result. + */ + public static void writeServiceInitResultEvent(int detectorType, int result) { + int metricsDetectorType = getInitMetricsDetectorType(detectorType); + FrameworkStatsLog.write(FrameworkStatsLog.HOTWORD_DETECTION_SERVICE_INIT_RESULT_REPORTED, + metricsDetectorType, result); + } + + /** + * Logs information related to hotword detection service restarting. + */ + public static void writeServiceRestartEvent(int detectorType, int reason) { + int metricsDetectorType = getRestartMetricsDetectorType(detectorType); + FrameworkStatsLog.write(FrameworkStatsLog.HOTWORD_DETECTION_SERVICE_RESTARTED, + metricsDetectorType, reason); + } + + /** + * Logs information related to keyphrase trigger. + */ + public static void writeKeyphraseTriggerEvent(int detectorType, int result) { + int metricsDetectorType = getKeyphraseMetricsDetectorType(detectorType); + FrameworkStatsLog.write(FrameworkStatsLog.HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED, + metricsDetectorType, result); + } + + /** + * Logs information related to hotword detector events. + */ + public static void writeDetectorEvent(int detectorType, int event, int uid) { + int metricsDetectorType = getDetectorMetricsDetectorType(detectorType); + FrameworkStatsLog.write(FrameworkStatsLog.HOTWORD_DETECTOR_EVENTS, + metricsDetectorType, event, uid); + } + + private static int getCreateMetricsDetectorType(int detectorType) { + switch (detectorType) { + case HotwordDetector.DETECTOR_TYPE_TRUSTED_HOTWORD_SOFTWARE: + return HOTWORD_DETECTOR_CREATE_REQUESTED__DETECTOR_TYPE__TRUSTED_DETECTOR_SOFTWARE; + case HotwordDetector.DETECTOR_TYPE_TRUSTED_HOTWORD_DSP: + return HOTWORD_DETECTOR_CREATE_REQUESTED__DETECTOR_TYPE__TRUSTED_DETECTOR_DSP; + default: + return HOTWORD_DETECTOR_CREATE_REQUESTED__DETECTOR_TYPE__NORMAL_DETECTOR; + } + } + + private static int getRestartMetricsDetectorType(int detectorType) { + switch (detectorType) { + case HotwordDetector.DETECTOR_TYPE_TRUSTED_HOTWORD_SOFTWARE: + return HOTWORD_DETECTION_SERVICE_RESTARTED__DETECTOR_TYPE__TRUSTED_DETECTOR_SOFTWARE; + case HotwordDetector.DETECTOR_TYPE_TRUSTED_HOTWORD_DSP: + return HOTWORD_DETECTION_SERVICE_RESTARTED__DETECTOR_TYPE__TRUSTED_DETECTOR_DSP; + default: + return HOTWORD_DETECTION_SERVICE_RESTARTED__DETECTOR_TYPE__NORMAL_DETECTOR; + } + } + + private static int getInitMetricsDetectorType(int detectorType) { + switch (detectorType) { + case HotwordDetector.DETECTOR_TYPE_TRUSTED_HOTWORD_SOFTWARE: + return METRICS_INIT_DETECTOR_SOFTWARE; + case HotwordDetector.DETECTOR_TYPE_TRUSTED_HOTWORD_DSP: + return METRICS_INIT_DETECTOR_DSP; + default: + return METRICS_INIT_NORMAL_DETECTOR; + } + } + + private static int getKeyphraseMetricsDetectorType(int detectorType) { + switch (detectorType) { + case HotwordDetector.DETECTOR_TYPE_TRUSTED_HOTWORD_SOFTWARE: + return HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__DETECTOR_TYPE__TRUSTED_DETECTOR_SOFTWARE; + case HotwordDetector.DETECTOR_TYPE_TRUSTED_HOTWORD_DSP: + return HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__DETECTOR_TYPE__TRUSTED_DETECTOR_DSP; + default: + return HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__DETECTOR_TYPE__NORMAL_DETECTOR; + } + } + + private static int getDetectorMetricsDetectorType(int detectorType) { + switch (detectorType) { + case HotwordDetector.DETECTOR_TYPE_TRUSTED_HOTWORD_SOFTWARE: + return HOTWORD_DETECTOR_EVENTS__DETECTOR_TYPE__TRUSTED_DETECTOR_SOFTWARE; + case HotwordDetector.DETECTOR_TYPE_TRUSTED_HOTWORD_DSP: + return HOTWORD_DETECTOR_EVENTS__DETECTOR_TYPE__TRUSTED_DETECTOR_DSP; + default: + return HOTWORD_DETECTOR_EVENTS__DETECTOR_TYPE__NORMAL_DETECTOR; + } + } +} diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java index 8445ed4884e2..1285a84ea752 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java @@ -1168,7 +1168,8 @@ public class VoiceInteractionManagerService extends SystemService { @NonNull Identity voiceInteractorIdentity, @Nullable PersistableBundle options, @Nullable SharedMemory sharedMemory, - IHotwordRecognitionStatusCallback callback) { + IHotwordRecognitionStatusCallback callback, + int detectorType) { enforceCallingPermission(Manifest.permission.MANAGE_HOTWORD_DETECTION); synchronized (this) { enforceIsCurrentVoiceInteractionService(); @@ -1184,7 +1185,7 @@ public class VoiceInteractionManagerService extends SystemService { final long caller = Binder.clearCallingIdentity(); try { mImpl.updateStateLocked( - voiceInteractorIdentity, options, sharedMemory, callback); + voiceInteractorIdentity, options, sharedMemory, callback, detectorType); } finally { Binder.restoreCallingIdentity(caller); } diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java index 52c5b6bbc239..20cf16aea18e 100644 --- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java +++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java @@ -53,6 +53,7 @@ import android.os.RemoteException; import android.os.ServiceManager; import android.os.SharedMemory; import android.os.UserHandle; +import android.service.voice.HotwordDetector; import android.service.voice.IMicrophoneHotwordDetectionVoiceInteractionCallback; import android.service.voice.IVoiceInteractionService; import android.service.voice.IVoiceInteractionSession; @@ -102,6 +103,7 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne VoiceInteractionSessionConnection mActiveSession; int mDisabledShowContext; + int mDetectorType; final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { @Override @@ -456,26 +458,36 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne @NonNull Identity voiceInteractorIdentity, @Nullable PersistableBundle options, @Nullable SharedMemory sharedMemory, - IHotwordRecognitionStatusCallback callback) { + IHotwordRecognitionStatusCallback callback, + int detectorType) { Slog.v(TAG, "updateStateLocked"); + int voiceInteractionServiceUid = mInfo.getServiceInfo().applicationInfo.uid; if (mHotwordDetectionComponentName == null) { Slog.w(TAG, "Hotword detection service name not found"); + logDetectorCreateEventIfNeeded(callback, detectorType, false, + voiceInteractionServiceUid); throw new IllegalStateException("Hotword detection service name not found"); } ServiceInfo hotwordDetectionServiceInfo = getServiceInfoLocked( mHotwordDetectionComponentName, mUser); if (hotwordDetectionServiceInfo == null) { Slog.w(TAG, "Hotword detection service info not found"); + logDetectorCreateEventIfNeeded(callback, detectorType, false, + voiceInteractionServiceUid); throw new IllegalStateException("Hotword detection service info not found"); } if (!isIsolatedProcessLocked(hotwordDetectionServiceInfo)) { Slog.w(TAG, "Hotword detection service not in isolated process"); + logDetectorCreateEventIfNeeded(callback, detectorType, false, + voiceInteractionServiceUid); throw new IllegalStateException("Hotword detection service not in isolated process"); } if (!Manifest.permission.BIND_HOTWORD_DETECTION_SERVICE.equals( hotwordDetectionServiceInfo.permission)) { Slog.w(TAG, "Hotword detection service does not require permission " + Manifest.permission.BIND_HOTWORD_DETECTION_SERVICE); + logDetectorCreateEventIfNeeded(callback, detectorType, false, + voiceInteractionServiceUid); throw new SecurityException("Hotword detection service does not require permission " + Manifest.permission.BIND_HOTWORD_DETECTION_SERVICE); } @@ -484,25 +496,40 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne mInfo.getServiceInfo().packageName) == PackageManager.PERMISSION_GRANTED) { Slog.w(TAG, "Voice interaction service should not hold permission " + Manifest.permission.BIND_HOTWORD_DETECTION_SERVICE); + logDetectorCreateEventIfNeeded(callback, detectorType, false, + voiceInteractionServiceUid); throw new SecurityException("Voice interaction service should not hold permission " + Manifest.permission.BIND_HOTWORD_DETECTION_SERVICE); } if (sharedMemory != null && !sharedMemory.setProtect(OsConstants.PROT_READ)) { Slog.w(TAG, "Can't set sharedMemory to be read-only"); + logDetectorCreateEventIfNeeded(callback, detectorType, false, + voiceInteractionServiceUid); throw new IllegalStateException("Can't set sharedMemory to be read-only"); } + mDetectorType = detectorType; + logDetectorCreateEventIfNeeded(callback, detectorType, true, + voiceInteractionServiceUid); if (mHotwordDetectionConnection == null) { mHotwordDetectionConnection = new HotwordDetectionConnection(mServiceStub, mContext, mInfo.getServiceInfo().applicationInfo.uid, voiceInteractorIdentity, mHotwordDetectionComponentName, mUser, /* bindInstantServiceAllowed= */ false, - options, sharedMemory, callback); + options, sharedMemory, callback, detectorType); } else { mHotwordDetectionConnection.updateStateLocked(options, sharedMemory); } } + private void logDetectorCreateEventIfNeeded(IHotwordRecognitionStatusCallback callback, + int detectorType, boolean isCreated, int voiceInteractionServiceUid) { + if (callback != null) { + HotwordMetricsLogger.writeDetectorCreateEvent(detectorType, true, + voiceInteractionServiceUid); + } + } + public void shutdownHotwordDetectionServiceLocked() { if (DEBUG) { Slog.d(TAG, "shutdownHotwordDetectionServiceLocked"); @@ -667,6 +694,8 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne pw.println(Integer.toHexString(mDisabledShowContext)); } pw.print(" mBound="); pw.print(mBound); pw.print(" mService="); pw.println(mService); + pw.print(" mDetectorType="); + pw.println(HotwordDetector.detectorTypeToString(mDetectorType)); if (mHotwordDetectionConnection != null) { pw.println(" Hotword detection connection:"); mHotwordDetectionConnection.dump(" ", pw); diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java index 8a8cdb0c5f3b..845dfaee2bac 100644 --- a/telecomm/java/android/telecom/TelecomManager.java +++ b/telecomm/java/android/telecom/TelecomManager.java @@ -1452,9 +1452,14 @@ public class TelecomManager { * when placing calls. The user may still need to enable the {@link PhoneAccount} within * the phone app settings before the account is usable. * <p> + * Note: Each package is limited to 10 {@link PhoneAccount} registrations. + * <p> * A {@link SecurityException} will be thrown if an app tries to register a * {@link PhoneAccountHandle} where the package name specified within * {@link PhoneAccountHandle#getComponentName()} does not match the package name of the app. + * <p> + * A {@link IllegalArgumentException} will be thrown if an app tries to register a + * {@link PhoneAccount} when the upper bound limit, 10, has already been reached. * * @param account The complete {@link PhoneAccount}. */ diff --git a/tools/codegen/OWNERS b/tools/codegen/OWNERS index e69de29bb2d1..da723b3b67da 100644 --- a/tools/codegen/OWNERS +++ b/tools/codegen/OWNERS @@ -0,0 +1 @@ +eugenesusla@google.com
\ No newline at end of file |