From 8b79dcc20d1a43f78478e8f22d5ca8559a642f3a Mon Sep 17 00:00:00 2001 From: Marcello Galhardo Date: Fri, 11 Nov 2022 10:43:52 +0000 Subject: [PATCH 01/38] Use `UnreleasedFlag` instead of `SysPropBooleanFlag`. A `UnreleasedFlag` is safer as it can not be changed in released builds or with public APIs (i.e., System Properties). Test: manual Fixes: b/257976997 Change-Id: I17eddcc77a14b16b31f67e5675932f4690b9ffb8 --- packages/SystemUI/src/com/android/systemui/flags/Flags.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt index 002ffdb68682a..ec2a8438ea005 100644 --- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt +++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt @@ -406,8 +406,8 @@ object Flags { val LEAVE_SHADE_OPEN_FOR_BUGREPORT = unreleasedFlag(1800, "leave_shade_open_for_bugreport", teamfood = true) - // 1900 - note task - @JvmField val NOTE_TASKS = sysPropBooleanFlag(1900, "persist.sysui.debug.note_tasks") + // 1900 + @JvmField val NOTE_TASKS = unreleasedFlag(1900, "keycode_flag") // 2000 - device controls @Keep @JvmField val USE_APP_PANELS = unreleasedFlag(2000, "use_app_panels", teamfood = true) From 9d09846798bce7253ed1202adb61257d4eefbd1d Mon Sep 17 00:00:00 2001 From: Nate Myren Date: Thu, 10 Nov 2022 14:07:28 -0800 Subject: [PATCH 02/38] RESTRICT AUTOMERGE Use chain start token in performOpTransaction Bug: 258672042 Test: atest CtsPermission4TestCases Change-Id: I1d484ed7c72d4ae73f4cbec47522a18ae9088f6e --- core/java/android/app/AppOpsManager.java | 22 ++++--- .../android/app/AppOpsManagerInternal.java | 23 ++++--- .../android/internal/app/IAppOpsService.aidl | 11 ++-- .../server/am/ActivityManagerService.java | 24 ++++---- .../android/server/appop/AppOpsService.java | 61 +++++++++---------- .../permission/PermissionManagerService.java | 39 ++++++------ .../android/server/policy/AppOpsPolicy.java | 18 +++--- 7 files changed, 103 insertions(+), 95 deletions(-) diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index fc89e1395073b..5b1666935ba89 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -8888,8 +8888,9 @@ public class AppOpsManager { */ public int startProxyOpNoThrow(int op, @NonNull AttributionSource attributionSource, @Nullable String message, boolean skipProxyOperation) { - return startProxyOpNoThrow(op, attributionSource, message, skipProxyOperation, - ATTRIBUTION_FLAGS_NONE, ATTRIBUTION_FLAGS_NONE, ATTRIBUTION_CHAIN_ID_NONE); + return startProxyOpNoThrow(attributionSource.getToken(), op, attributionSource, message, + skipProxyOperation, ATTRIBUTION_FLAGS_NONE, ATTRIBUTION_FLAGS_NONE, + ATTRIBUTION_CHAIN_ID_NONE); } /** @@ -8901,7 +8902,8 @@ public class AppOpsManager { * * @hide */ - public int startProxyOpNoThrow(int op, @NonNull AttributionSource attributionSource, + public int startProxyOpNoThrow(@NonNull IBinder clientId, int op, + @NonNull AttributionSource attributionSource, @Nullable String message, boolean skipProxyOperation, @AttributionFlags int proxyAttributionFlags, @AttributionFlags int proxiedAttributionFlags, int attributionChainId) { @@ -8919,7 +8921,7 @@ public class AppOpsManager { } } - SyncNotedAppOp syncOp = mService.startProxyOperation(op, + SyncNotedAppOp syncOp = mService.startProxyOperation(clientId, op, attributionSource, false, collectionMode == COLLECT_ASYNC, message, shouldCollectMessage, skipProxyOperation, proxyAttributionFlags, proxiedAttributionFlags, attributionChainId); @@ -9017,9 +9019,10 @@ public class AppOpsManager { */ public void finishProxyOp(@NonNull String op, int proxiedUid, @NonNull String proxiedPackageName, @Nullable String proxiedAttributionTag) { - finishProxyOp(op, new AttributionSource(mContext.getAttributionSource(), + IBinder token = mContext.getAttributionSource().getToken(); + finishProxyOp(token, op, new AttributionSource(mContext.getAttributionSource(), new AttributionSource(proxiedUid, proxiedPackageName, proxiedAttributionTag, - mContext.getAttributionSource().getToken())), /*skipProxyOperation*/ false); + token)), /*skipProxyOperation*/ false); } /** @@ -9034,10 +9037,11 @@ public class AppOpsManager { * * @hide */ - public void finishProxyOp(@NonNull String op, @NonNull AttributionSource attributionSource, - boolean skipProxyOperation) { + public void finishProxyOp(@NonNull IBinder clientId, @NonNull String op, + @NonNull AttributionSource attributionSource, boolean skipProxyOperation) { try { - mService.finishProxyOperation(strOpToOp(op), attributionSource, skipProxyOperation); + mService.finishProxyOperation(clientId, strOpToOp(op), attributionSource, + skipProxyOperation); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/app/AppOpsManagerInternal.java b/core/java/android/app/AppOpsManagerInternal.java index 4d6e4aedba66c..43023fe9c2abb 100644 --- a/core/java/android/app/AppOpsManagerInternal.java +++ b/core/java/android/app/AppOpsManagerInternal.java @@ -26,13 +26,11 @@ import android.util.SparseArray; import android.util.SparseIntArray; import com.android.internal.app.IAppOpsCallback; -import com.android.internal.util.function.DecFunction; import com.android.internal.util.function.HeptFunction; import com.android.internal.util.function.HexFunction; import com.android.internal.util.function.QuadFunction; import com.android.internal.util.function.QuintConsumer; import com.android.internal.util.function.QuintFunction; -import com.android.internal.util.function.TriFunction; import com.android.internal.util.function.UndecFunction; /** @@ -135,6 +133,7 @@ public abstract class AppOpsManagerInternal { /** * Allows overriding start proxy operation behavior. * + * @param clientId The client calling start, represented by an IBinder * @param code The op code to start. * @param attributionSource The permission identity of the caller. * @param startIfModeDefault Whether to start the op of the mode is default. @@ -148,11 +147,12 @@ public abstract class AppOpsManagerInternal { * @param superImpl The super implementation. * @return The app op note result. */ - SyncNotedAppOp startProxyOperation(int code, @NonNull AttributionSource attributionSource, - boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, String message, - boolean shouldCollectMessage, boolean skipProxyOperation, @AttributionFlags - int proxyAttributionFlags, @AttributionFlags int proxiedAttributionFlags, - int attributionChainId, @NonNull DecFunction superImpl); @@ -176,10 +176,15 @@ public abstract class AppOpsManagerInternal { * * @param code The op code to finish. * @param attributionSource The permission identity of the caller. + * @param skipProxyOperation Whether to skip the proxy in the proxy/proxied operation + * @param clientId The client calling finishProxyOperation + * @param superImpl The "standard" implementation to potentially call */ - void finishProxyOperation(int code, @NonNull AttributionSource attributionSource, + void finishProxyOperation(@NonNull IBinder clientId, int code, + @NonNull AttributionSource attributionSource, boolean skipProxyOperation, - @NonNull TriFunction superImpl); + @NonNull QuadFunction superImpl); } /** diff --git a/core/java/com/android/internal/app/IAppOpsService.aidl b/core/java/com/android/internal/app/IAppOpsService.aidl index 30da4b470ab6d..88447daf73388 100644 --- a/core/java/com/android/internal/app/IAppOpsService.aidl +++ b/core/java/com/android/internal/app/IAppOpsService.aidl @@ -58,11 +58,12 @@ interface IAppOpsService { SyncNotedAppOp noteProxyOperation(int code, in AttributionSource attributionSource, boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage, boolean skipProxyOperation); - SyncNotedAppOp startProxyOperation(int code, in AttributionSource attributionSource, - boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, String message, - boolean shouldCollectMessage, boolean skipProxyOperation, int proxyAttributionFlags, - int proxiedAttributionFlags, int attributionChainId); - void finishProxyOperation(int code, in AttributionSource attributionSource, + SyncNotedAppOp startProxyOperation(IBinder clientId, int code, + in AttributionSource attributionSource, boolean startIfModeDefault, + boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage, + boolean skipProxyOperation, int proxyAttributionFlags, int proxiedAttributionFlags, + int attributionChainId); + void finishProxyOperation(IBinder clientId, int code, in AttributionSource attributionSource, boolean skipProxyOperation); // Remaining methods are only used in Java. diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 641f09da4b98b..5e2180d5f40c1 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -348,12 +348,10 @@ import com.android.internal.util.FastPrintWriter; import com.android.internal.util.FrameworkStatsLog; import com.android.internal.util.MemInfoReader; import com.android.internal.util.Preconditions; -import com.android.internal.util.function.DecFunction; import com.android.internal.util.function.HeptFunction; import com.android.internal.util.function.HexFunction; import com.android.internal.util.function.QuadFunction; import com.android.internal.util.function.QuintFunction; -import com.android.internal.util.function.TriFunction; import com.android.internal.util.function.UndecFunction; import com.android.server.AlarmManagerInternal; import com.android.server.DeviceIdleInternal; @@ -17062,19 +17060,20 @@ public class ActivityManagerService extends IActivityManager.Stub } @Override - public SyncNotedAppOp startProxyOperation(int code, + public SyncNotedAppOp startProxyOperation(@NonNull IBinder clientId, int code, @NonNull AttributionSource attributionSource, boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage, boolean skipProxyOperation, @AttributionFlags int proxyAttributionFlags, @AttributionFlags int proxiedAttributionFlags, int attributionChainId, - @NonNull DecFunction superImpl) { + @NonNull UndecFunction superImpl) { if (attributionSource.getUid() == mTargetUid && isTargetOp(code)) { final int shellUid = UserHandle.getUid(UserHandle.getUserId( attributionSource.getUid()), Process.SHELL_UID); final long identity = Binder.clearCallingIdentity(); try { - return superImpl.apply(code, new AttributionSource(shellUid, + return superImpl.apply(clientId, code, new AttributionSource(shellUid, "com.android.shell", attributionSource.getAttributionTag(), attributionSource.getToken(), attributionSource.getNext()), startIfModeDefault, shouldCollectAsyncNotedOp, message, @@ -17084,21 +17083,22 @@ public class ActivityManagerService extends IActivityManager.Stub Binder.restoreCallingIdentity(identity); } } - return superImpl.apply(code, attributionSource, startIfModeDefault, + return superImpl.apply(clientId, code, attributionSource, startIfModeDefault, shouldCollectAsyncNotedOp, message, shouldCollectMessage, skipProxyOperation, proxyAttributionFlags, proxiedAttributionFlags, attributionChainId); } @Override - public void finishProxyOperation(int code, @NonNull AttributionSource attributionSource, - boolean skipProxyOperation, @NonNull TriFunction superImpl) { + public void finishProxyOperation(@NonNull IBinder clientId, int code, + @NonNull AttributionSource attributionSource, boolean skipProxyOperation, + @NonNull QuadFunction superImpl) { if (attributionSource.getUid() == mTargetUid && isTargetOp(code)) { final int shellUid = UserHandle.getUid(UserHandle.getUserId( attributionSource.getUid()), Process.SHELL_UID); final long identity = Binder.clearCallingIdentity(); try { - superImpl.apply(code, new AttributionSource(shellUid, + superImpl.apply(clientId, code, new AttributionSource(shellUid, "com.android.shell", attributionSource.getAttributionTag(), attributionSource.getToken(), attributionSource.getNext()), skipProxyOperation); @@ -17106,7 +17106,7 @@ public class ActivityManagerService extends IActivityManager.Stub Binder.restoreCallingIdentity(identity); } } - superImpl.apply(code, attributionSource, skipProxyOperation); + superImpl.apply(clientId, code, attributionSource, skipProxyOperation); } private boolean isTargetOp(int code) { diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java index 3808e0c93a38f..759099f89b761 100644 --- a/services/core/java/com/android/server/appop/AppOpsService.java +++ b/services/core/java/com/android/server/appop/AppOpsService.java @@ -3839,18 +3839,18 @@ public class AppOpsService extends IAppOpsService.Stub { } @Override - public SyncNotedAppOp startProxyOperation(int code, + public SyncNotedAppOp startProxyOperation(@NonNull IBinder clientId, int code, @NonNull AttributionSource attributionSource, boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage, boolean skipProxyOperation, @AttributionFlags int proxyAttributionFlags, @AttributionFlags int proxiedAttributionFlags, int attributionChainId) { - return mCheckOpsDelegateDispatcher.startProxyOperation(code, attributionSource, + return mCheckOpsDelegateDispatcher.startProxyOperation(clientId, code, attributionSource, startIfModeDefault, shouldCollectAsyncNotedOp, message, shouldCollectMessage, skipProxyOperation, proxyAttributionFlags, proxiedAttributionFlags, attributionChainId); } - private SyncNotedAppOp startProxyOperationImpl(int code, + private SyncNotedAppOp startProxyOperationImpl(@NonNull IBinder clientId, int code, @NonNull AttributionSource attributionSource, boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage, boolean skipProxyOperation, @AttributionFlags @@ -3859,11 +3859,9 @@ public class AppOpsService extends IAppOpsService.Stub { final int proxyUid = attributionSource.getUid(); final String proxyPackageName = attributionSource.getPackageName(); final String proxyAttributionTag = attributionSource.getAttributionTag(); - final IBinder proxyToken = attributionSource.getToken(); final int proxiedUid = attributionSource.getNextUid(); final String proxiedPackageName = attributionSource.getNextPackageName(); final String proxiedAttributionTag = attributionSource.getNextAttributionTag(); - final IBinder proxiedToken = attributionSource.getNextToken(); verifyIncomingProxyUid(attributionSource); verifyIncomingOp(code); @@ -3902,7 +3900,7 @@ public class AppOpsService extends IAppOpsService.Stub { if (!skipProxyOperation) { // Test if the proxied operation will succeed before starting the proxy operation - final SyncNotedAppOp testProxiedOp = startOperationUnchecked(proxiedToken, code, + final SyncNotedAppOp testProxiedOp = startOperationUnchecked(clientId, code, proxiedUid, resolvedProxiedPackageName, proxiedAttributionTag, proxyUid, resolvedProxyPackageName, proxyAttributionTag, proxiedFlags, startIfModeDefault, shouldCollectAsyncNotedOp, message, shouldCollectMessage, @@ -3914,7 +3912,7 @@ public class AppOpsService extends IAppOpsService.Stub { final int proxyFlags = isProxyTrusted ? AppOpsManager.OP_FLAG_TRUSTED_PROXY : AppOpsManager.OP_FLAG_UNTRUSTED_PROXY; - final SyncNotedAppOp proxyAppOp = startOperationUnchecked(proxyToken, code, proxyUid, + final SyncNotedAppOp proxyAppOp = startOperationUnchecked(clientId, code, proxyUid, resolvedProxyPackageName, proxyAttributionTag, Process.INVALID_UID, null, null, proxyFlags, startIfModeDefault, !isProxyTrusted, "proxy " + message, shouldCollectMessage, proxyAttributionFlags, attributionChainId, @@ -3924,7 +3922,7 @@ public class AppOpsService extends IAppOpsService.Stub { } } - return startOperationUnchecked(proxiedToken, code, proxiedUid, resolvedProxiedPackageName, + return startOperationUnchecked(clientId, code, proxiedUid, resolvedProxiedPackageName, proxiedAttributionTag, proxyUid, resolvedProxyPackageName, proxyAttributionTag, proxiedFlags, startIfModeDefault, shouldCollectAsyncNotedOp, message, shouldCollectMessage, proxiedAttributionFlags, attributionChainId, @@ -4065,22 +4063,20 @@ public class AppOpsService extends IAppOpsService.Stub { } @Override - public void finishProxyOperation(int code, @NonNull AttributionSource attributionSource, - boolean skipProxyOperation) { - mCheckOpsDelegateDispatcher.finishProxyOperation(code, attributionSource, + public void finishProxyOperation(@NonNull IBinder clientId, int code, + @NonNull AttributionSource attributionSource, boolean skipProxyOperation) { + mCheckOpsDelegateDispatcher.finishProxyOperation(clientId, code, attributionSource, skipProxyOperation); } - private Void finishProxyOperationImpl(int code, @NonNull AttributionSource attributionSource, - boolean skipProxyOperation) { + private Void finishProxyOperationImpl(IBinder clientId, int code, + @NonNull AttributionSource attributionSource, boolean skipProxyOperation) { final int proxyUid = attributionSource.getUid(); final String proxyPackageName = attributionSource.getPackageName(); final String proxyAttributionTag = attributionSource.getAttributionTag(); - final IBinder proxyToken = attributionSource.getToken(); final int proxiedUid = attributionSource.getNextUid(); final String proxiedPackageName = attributionSource.getNextPackageName(); final String proxiedAttributionTag = attributionSource.getNextAttributionTag(); - final IBinder proxiedToken = attributionSource.getNextToken(); skipProxyOperation = skipProxyOperation && isCallerAndAttributionTrusted(attributionSource); @@ -4097,7 +4093,7 @@ public class AppOpsService extends IAppOpsService.Stub { } if (!skipProxyOperation) { - finishOperationUnchecked(proxyToken, code, proxyUid, resolvedProxyPackageName, + finishOperationUnchecked(clientId, code, proxyUid, resolvedProxyPackageName, proxyAttributionTag); } @@ -4107,7 +4103,7 @@ public class AppOpsService extends IAppOpsService.Stub { return null; } - finishOperationUnchecked(proxiedToken, code, proxiedUid, resolvedProxiedPackageName, + finishOperationUnchecked(clientId, code, proxiedUid, resolvedProxiedPackageName, proxiedAttributionTag); return null; @@ -7642,42 +7638,42 @@ public class AppOpsService extends IAppOpsService.Stub { attributionFlags, attributionChainId, AppOpsService.this::startOperationImpl); } - public SyncNotedAppOp startProxyOperation(int code, + public SyncNotedAppOp startProxyOperation(@NonNull IBinder clientId, int code, @NonNull AttributionSource attributionSource, boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage, boolean skipProxyOperation, @AttributionFlags int proxyAttributionFlags, @AttributionFlags int proxiedAttributionFlags, int attributionChainId) { if (mPolicy != null) { if (mCheckOpsDelegate != null) { - return mPolicy.startProxyOperation(code, attributionSource, + return mPolicy.startProxyOperation(clientId, code, attributionSource, startIfModeDefault, shouldCollectAsyncNotedOp, message, shouldCollectMessage, skipProxyOperation, proxyAttributionFlags, proxiedAttributionFlags, attributionChainId, this::startDelegateProxyOperationImpl); } else { - return mPolicy.startProxyOperation(code, attributionSource, + return mPolicy.startProxyOperation(clientId, code, attributionSource, startIfModeDefault, shouldCollectAsyncNotedOp, message, shouldCollectMessage, skipProxyOperation, proxyAttributionFlags, proxiedAttributionFlags, attributionChainId, AppOpsService.this::startProxyOperationImpl); } } else if (mCheckOpsDelegate != null) { - return startDelegateProxyOperationImpl(code, attributionSource, + return startDelegateProxyOperationImpl(clientId, code, attributionSource, startIfModeDefault, shouldCollectAsyncNotedOp, message, shouldCollectMessage, skipProxyOperation, proxyAttributionFlags, proxiedAttributionFlags, attributionChainId); } - return startProxyOperationImpl(code, attributionSource, startIfModeDefault, + return startProxyOperationImpl(clientId, code, attributionSource, startIfModeDefault, shouldCollectAsyncNotedOp, message, shouldCollectMessage, skipProxyOperation, proxyAttributionFlags, proxiedAttributionFlags, attributionChainId); } - private SyncNotedAppOp startDelegateProxyOperationImpl(int code, + private SyncNotedAppOp startDelegateProxyOperationImpl(@NonNull IBinder clientId, int code, @NonNull AttributionSource attributionSource, boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage, boolean skipProxyOperation, @AttributionFlags int proxyAttributionFlags, @AttributionFlags int proxiedAttributionFlsgs, int attributionChainId) { - return mCheckOpsDelegate.startProxyOperation(code, attributionSource, + return mCheckOpsDelegate.startProxyOperation(clientId, code, attributionSource, startIfModeDefault, shouldCollectAsyncNotedOp, message, shouldCollectMessage, skipProxyOperation, proxyAttributionFlags, proxiedAttributionFlsgs, attributionChainId, AppOpsService.this::startProxyOperationImpl); @@ -7706,27 +7702,28 @@ public class AppOpsService extends IAppOpsService.Stub { AppOpsService.this::finishOperationImpl); } - public void finishProxyOperation(int code, + public void finishProxyOperation(@NonNull IBinder clientId, int code, @NonNull AttributionSource attributionSource, boolean skipProxyOperation) { if (mPolicy != null) { if (mCheckOpsDelegate != null) { - mPolicy.finishProxyOperation(code, attributionSource, + mPolicy.finishProxyOperation(clientId, code, attributionSource, skipProxyOperation, this::finishDelegateProxyOperationImpl); } else { - mPolicy.finishProxyOperation(code, attributionSource, + mPolicy.finishProxyOperation(clientId, code, attributionSource, skipProxyOperation, AppOpsService.this::finishProxyOperationImpl); } } else if (mCheckOpsDelegate != null) { - finishDelegateProxyOperationImpl(code, attributionSource, skipProxyOperation); + finishDelegateProxyOperationImpl(clientId, code, attributionSource, + skipProxyOperation); } else { - finishProxyOperationImpl(code, attributionSource, skipProxyOperation); + finishProxyOperationImpl(clientId, code, attributionSource, skipProxyOperation); } } - private Void finishDelegateProxyOperationImpl(int code, + private Void finishDelegateProxyOperationImpl(@NonNull IBinder clientId, int code, @NonNull AttributionSource attributionSource, boolean skipProxyOperation) { - mCheckOpsDelegate.finishProxyOperation(code, attributionSource, skipProxyOperation, - AppOpsService.this::finishProxyOperationImpl); + mCheckOpsDelegate.finishProxyOperation(clientId, code, attributionSource, + skipProxyOperation, AppOpsService.this::finishProxyOperationImpl); return null; } } diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java index 5e54f937fc983..9d0b2543e5efc 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java @@ -5650,7 +5650,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { if (resolvedPackageName == null) { return; } - appOpsManager.finishOp(accessorSource.getToken(), op, + appOpsManager.finishOp(attributionSourceState.token, op, accessorSource.getUid(), resolvedPackageName, accessorSource.getAttributionTag()); } else { @@ -5659,8 +5659,9 @@ public class PermissionManagerService extends IPermissionManager.Stub { if (resolvedAttributionSource.getPackageName() == null) { return; } - appOpsManager.finishProxyOp(AppOpsManager.opToPublicName(op), - resolvedAttributionSource, skipCurrentFinish); + appOpsManager.finishProxyOp(attributionSourceState.token, + AppOpsManager.opToPublicName(op), resolvedAttributionSource, + skipCurrentFinish); } if (next == null || next.getNext() == null) { @@ -5770,10 +5771,11 @@ public class PermissionManagerService extends IPermissionManager.Stub { && next.getNext() == null); final boolean selfAccess = singleReceiverFromDatasource || next == null; - final int opMode = performOpTransaction(context, op, current, message, - forDataDelivery, /*startDataDelivery*/ false, skipCurrentChecks, - selfAccess, singleReceiverFromDatasource, AppOpsManager.OP_NONE, - AppOpsManager.ATTRIBUTION_FLAGS_NONE, AppOpsManager.ATTRIBUTION_FLAGS_NONE, + final int opMode = performOpTransaction(context, attributionSource.getToken(), op, + current, message, forDataDelivery, /*startDataDelivery*/ false, + skipCurrentChecks, selfAccess, singleReceiverFromDatasource, + AppOpsManager.OP_NONE, AppOpsManager.ATTRIBUTION_FLAGS_NONE, + AppOpsManager.ATTRIBUTION_FLAGS_NONE, AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE); switch (opMode) { @@ -5875,10 +5877,10 @@ public class PermissionManagerService extends IPermissionManager.Stub { attributionSource, next, fromDatasource, startDataDelivery, selfAccess, isLinkTrusted) : ATTRIBUTION_FLAGS_NONE; - final int opMode = performOpTransaction(context, op, current, message, - forDataDelivery, startDataDelivery, skipCurrentChecks, selfAccess, - singleReceiverFromDatasource, attributedOp, proxyAttributionFlags, - proxiedAttributionFlags, attributionChainId); + final int opMode = performOpTransaction(context, attributionSource.getToken(), op, + current, message, forDataDelivery, startDataDelivery, skipCurrentChecks, + selfAccess, singleReceiverFromDatasource, attributedOp, + proxyAttributionFlags, proxiedAttributionFlags, attributionChainId); switch (opMode) { case AppOpsManager.MODE_ERRORED: { @@ -6023,8 +6025,8 @@ public class PermissionManagerService extends IPermissionManager.Stub { attributionSource, next, /*fromDatasource*/ false, startDataDelivery, selfAccess, isLinkTrusted) : ATTRIBUTION_FLAGS_NONE; - final int opMode = performOpTransaction(context, op, current, message, - forDataDelivery, startDataDelivery, skipCurrentChecks, selfAccess, + final int opMode = performOpTransaction(context, current.getToken(), op, current, + message, forDataDelivery, startDataDelivery, skipCurrentChecks, selfAccess, /*fromDatasource*/ false, AppOpsManager.OP_NONE, proxyAttributionFlags, proxiedAttributionFlags, attributionChainId); @@ -6046,7 +6048,8 @@ public class PermissionManagerService extends IPermissionManager.Stub { } @SuppressWarnings("ConstantConditions") - private static int performOpTransaction(@NonNull Context context, int op, + private static int performOpTransaction(@NonNull Context context, + @NonNull IBinder chainStartToken, int op, @NonNull AttributionSource attributionSource, @Nullable String message, boolean forDataDelivery, boolean startDataDelivery, boolean skipProxyOperation, boolean selfAccess, boolean singleReceiverFromDatasource, int attributedOp, @@ -6108,7 +6111,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { if (selfAccess) { try { startedOpResult = appOpsManager.startOpNoThrow( - resolvedAttributionSource.getToken(), startedOp, + chainStartToken, startedOp, resolvedAttributionSource.getUid(), resolvedAttributionSource.getPackageName(), /*startIfModeDefault*/ false, @@ -6119,12 +6122,12 @@ public class PermissionManagerService extends IPermissionManager.Stub { + " platform defined runtime permission " + AppOpsManager.opToPermission(op) + " while not having " + Manifest.permission.UPDATE_APP_OPS_STATS); - startedOpResult = appOpsManager.startProxyOpNoThrow(attributedOp, - attributionSource, message, skipProxyOperation, + startedOpResult = appOpsManager.startProxyOpNoThrow(chainStartToken, + attributedOp, attributionSource, message, skipProxyOperation, proxyAttributionFlags, proxiedAttributionFlags, attributionChainId); } } else { - startedOpResult = appOpsManager.startProxyOpNoThrow(startedOp, + startedOpResult = appOpsManager.startProxyOpNoThrow(chainStartToken, startedOp, resolvedAttributionSource, message, skipProxyOperation, proxyAttributionFlags, proxiedAttributionFlags, attributionChainId); } diff --git a/services/core/java/com/android/server/policy/AppOpsPolicy.java b/services/core/java/com/android/server/policy/AppOpsPolicy.java index 8b4690629ec5e..b31216d05e3e2 100644 --- a/services/core/java/com/android/server/policy/AppOpsPolicy.java +++ b/services/core/java/com/android/server/policy/AppOpsPolicy.java @@ -44,13 +44,11 @@ import android.util.Log; import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; -import com.android.internal.util.function.DecFunction; import com.android.internal.util.function.HeptFunction; import com.android.internal.util.function.HexFunction; import com.android.internal.util.function.QuadFunction; import com.android.internal.util.function.QuintConsumer; import com.android.internal.util.function.QuintFunction; -import com.android.internal.util.function.TriFunction; import com.android.internal.util.function.UndecFunction; import com.android.server.LocalServices; @@ -250,14 +248,14 @@ public final class AppOpsPolicy implements AppOpsManagerInternal.CheckOpsDelegat } @Override - public SyncNotedAppOp startProxyOperation(int code, + public SyncNotedAppOp startProxyOperation(@NonNull IBinder clientId, int code, @NonNull AttributionSource attributionSource, boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage, boolean skipProxyOperation, @AttributionFlags int proxyAttributionFlags, @AttributionFlags int proxiedAttributionFlags, int attributionChainId, - @NonNull DecFunction superImpl) { - return superImpl.apply(resolveDatasourceOp(code, attributionSource.getUid(), + @NonNull UndecFunction superImpl) { + return superImpl.apply(clientId, resolveDatasourceOp(code, attributionSource.getUid(), attributionSource.getPackageName(), attributionSource.getAttributionTag()), attributionSource, startIfModeDefault, shouldCollectAsyncNotedOp, message, shouldCollectMessage, skipProxyOperation, proxyAttributionFlags, @@ -273,10 +271,10 @@ public final class AppOpsPolicy implements AppOpsManagerInternal.CheckOpsDelegat } @Override - public void finishProxyOperation(int code, @NonNull AttributionSource attributionSource, - boolean skipProxyOperation, @NonNull TriFunction superImpl) { - superImpl.apply(resolveDatasourceOp(code, attributionSource.getUid(), + public void finishProxyOperation(@NonNull IBinder clientId, int code, + @NonNull AttributionSource attributionSource, boolean skipProxyOperation, + @NonNull QuadFunction superImpl) { + superImpl.apply(clientId, resolveDatasourceOp(code, attributionSource.getUid(), attributionSource.getPackageName(), attributionSource.getAttributionTag()), attributionSource, skipProxyOperation); } From d436036b23a27d66ee04755a7a01a878849b33fa Mon Sep 17 00:00:00 2001 From: Chris Li Date: Wed, 23 Nov 2022 16:02:53 +0800 Subject: [PATCH 03/38] Handle ActivityEmbedding container in remote transition adapter 1. When embedded TaskFragment is open/close with Task, we should only animate the Task. 2. When there is only a non-fullscreen embedded TaskFragment in the transition, we don't want to animate it, otherwise it may only animate partial of the Task. Fix: 260156661 Test: verify with opening Settings from quick settings. Change-Id: I6f3ae7c880ddbb17b33040c9ba19beb4d865fc35 --- .../systemui/animation/RemoteTransitionAdapter.kt | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteTransitionAdapter.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteTransitionAdapter.kt index f9c6841f96b56..86d4b12ea082a 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteTransitionAdapter.kt +++ b/packages/SystemUI/animation/src/com/android/systemui/animation/RemoteTransitionAdapter.kt @@ -195,8 +195,16 @@ class RemoteTransitionAdapter { val out = ArrayList() for (i in info.changes.indices) { val change = info.changes[i] - val changeIsWallpaper = change.flags and TransitionInfo.FLAG_IS_WALLPAPER != 0 - if (wallpapers != changeIsWallpaper) continue + if (change.hasFlags(TransitionInfo.FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY)) { + // For embedded container, when the parent Task is also in the transition, we + // should only animate the parent Task. + if (change.parent != null) continue + // For embedded container without parent, we should only animate if it fills + // the Task. Otherwise we may animate only partial of the Task. + if (!change.hasFlags(TransitionInfo.FLAG_FILLS_TASK)) continue + } + // Check if it is wallpaper + if (wallpapers != change.hasFlags(TransitionInfo.FLAG_IS_WALLPAPER)) continue out.add(createTarget(change, info.changes.size - i, info, t)) if (leashMap != null) { leashMap[change.leash] = out[out.size - 1].leash From 8b9da561acfd07493aed5f45f04fdb31c83bbff3 Mon Sep 17 00:00:00 2001 From: Michael Mikhail Date: Mon, 21 Nov 2022 22:09:26 +0000 Subject: [PATCH 04/38] Modify tablet recommendation card dimensions adds overlays for the existing values in the sw720dp-land file. And makes sure that media players are getting recreated when configuration changed (orientation changes) Fixes: 233569483 Bug: 243972769 Test: manual - checked that albums sizes are matching the updated dimensions in figma specs. Change-Id: Iec2d15db285ee6ed184ececfddd7aa2661d889b2 Change-Id: Icda17079c972a90b63c2833170382bba844cd48a --- .../res/layout/media_smartspace_recommendations.xml | 2 +- packages/SystemUI/res/values-sw720dp-land/dimens.xml | 5 +++++ packages/SystemUI/res/values/dimens.xml | 1 + .../systemui/media/controls/ui/MediaCarouselController.kt | 8 +++++--- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/packages/SystemUI/res/layout/media_smartspace_recommendations.xml b/packages/SystemUI/res/layout/media_smartspace_recommendations.xml index 79ba7ead1ec3e..aa655e6b35644 100644 --- a/packages/SystemUI/res/layout/media_smartspace_recommendations.xml +++ b/packages/SystemUI/res/layout/media_smartspace_recommendations.xml @@ -41,7 +41,7 @@ android:layout_width="@dimen/qs_media_app_icon_size" android:layout_height="@dimen/qs_media_app_icon_size" android:layout_marginStart="@dimen/qs_media_padding" - android:layout_marginTop="@dimen/qs_media_padding" + android:layout_marginTop="@dimen/qs_media_rec_icon_top_margin" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> diff --git a/packages/SystemUI/res/values-sw720dp-land/dimens.xml b/packages/SystemUI/res/values-sw720dp-land/dimens.xml index 868c003d99a5d..3fc59e38ec6c5 100644 --- a/packages/SystemUI/res/values-sw720dp-land/dimens.xml +++ b/packages/SystemUI/res/values-sw720dp-land/dimens.xml @@ -35,6 +35,11 @@ not appear immediately after user swipes to the side --> 20dp + + 27dp + 152dp + 16dp + 42dp + 16dp 88dp 16dp 8dp diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt index 8aaee81a57ddb..1fdbc99333cb0 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaCarouselController.kt @@ -184,6 +184,7 @@ constructor( private val configListener = object : ConfigurationController.ConfigurationListener { + override fun onDensityOrFontScaleChanged() { // System font changes should only happen when UMO is offscreen or a flicker may // occur @@ -199,6 +200,7 @@ constructor( override fun onConfigChanged(newConfig: Configuration?) { if (newConfig == null) return isRtl = newConfig.layoutDirection == View.LAYOUT_DIRECTION_RTL + updatePlayers(recreateMedia = true) } override fun onUiModeChanged() { @@ -635,7 +637,7 @@ constructor( val existingSmartspaceMediaKey = MediaPlayerData.smartspaceMediaKey() existingSmartspaceMediaKey?.let { val removedPlayer = - MediaPlayerData.removeMediaPlayer(existingSmartspaceMediaKey, true) + removePlayer(existingSmartspaceMediaKey, dismissMediaData = false) removedPlayer?.run { debugLogger.logPotentialMemoryLeak(existingSmartspaceMediaKey) } @@ -685,7 +687,7 @@ constructor( key: String, dismissMediaData: Boolean = true, dismissRecommendation: Boolean = true - ) { + ): MediaControlPanel? { if (key == MediaPlayerData.smartspaceMediaKey()) { MediaPlayerData.smartspaceMediaData?.let { logger.logRecommendationRemoved(it.packageName, it.instanceId) @@ -693,7 +695,7 @@ constructor( } val removed = MediaPlayerData.removeMediaPlayer(key, dismissMediaData || dismissRecommendation) - removed?.apply { + return removed?.apply { mediaCarouselScrollHandler.onPrePlayerRemoved(removed) mediaContent.removeView(removed.mediaViewHolder?.player) mediaContent.removeView(removed.recommendationViewHolder?.recommendations) From d94681b39442d7575e0cd381dda330e09bbce48d Mon Sep 17 00:00:00 2001 From: Jordan Demeulenaere Date: Thu, 24 Nov 2022 15:26:27 +0100 Subject: [PATCH 05/38] Introduce TestScope.collectLastValue(Flow) This CL introduces a helper function to easily collect value from an infinite Flow from a test. See ag/20562448 for an example. Bug: 242040009 Test: atest FooterActionsViewModelTest Change-Id: Ie87220a7382424dc9c25728fca03c601952da5c0 --- .../com/android/systemui/coroutines/Flow.kt | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 packages/SystemUI/tests/utils/src/com/android/systemui/coroutines/Flow.kt diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/coroutines/Flow.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/coroutines/Flow.kt new file mode 100644 index 0000000000000..b7a8d2e9f6844 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/coroutines/Flow.kt @@ -0,0 +1,40 @@ +/* + * 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.coroutines + +import kotlin.coroutines.CoroutineContext +import kotlin.coroutines.EmptyCoroutineContext +import kotlinx.coroutines.CoroutineStart +import kotlinx.coroutines.Job +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.launch +import kotlinx.coroutines.test.TestScope +import kotlinx.coroutines.test.runCurrent + +/** Collect [flow] in a new [Job] and return a getter for the last collected value. */ +fun TestScope.collectLastValue( + flow: Flow, + context: CoroutineContext = EmptyCoroutineContext, + start: CoroutineStart = CoroutineStart.DEFAULT, +): () -> T? { + var lastValue: T? = null + backgroundScope.launch(context, start) { flow.collect { lastValue = it } } + return { + runCurrent() + lastValue + } +} From 09e8750a91ebfd4ac9a77b5fc882536fbdb53374 Mon Sep 17 00:00:00 2001 From: Jordan Demeulenaere Date: Thu, 24 Nov 2022 15:27:36 +0100 Subject: [PATCH 06/38] Clean-up FooterActionsViewModelTest This CL cleans up FooterActionsViewModelTest and FooterActionsTestUtils by making sure that the same TestCoroutineScheduler is used by all TestDispatchers, and by using the new collectLastValue(Flow) API instead of manually collecting each Flow. Bug: 242040009 Test: atest FooterActionsViewModelTest Change-Id: Ia3b1ae8fba05c2ed9cf3a46d3cc7546161092f42 --- .../interactor/FooterActionsInteractorTest.kt | 3 +- .../viewmodel/FooterActionsViewModelTest.kt | 65 +++++-------------- .../qs/footer/FooterActionsTestUtils.kt | 10 +-- 3 files changed, 24 insertions(+), 54 deletions(-) diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/footer/domain/interactor/FooterActionsInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/footer/domain/interactor/FooterActionsInteractorTest.kt index 645b1cde632f5..23466cc20f449 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/footer/domain/interactor/FooterActionsInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/footer/domain/interactor/FooterActionsInteractorTest.kt @@ -41,6 +41,7 @@ import com.android.systemui.util.mockito.eq import com.android.systemui.util.mockito.mock import com.android.systemui.util.mockito.nullable import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.test.TestCoroutineScheduler import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -55,7 +56,7 @@ class FooterActionsInteractorTest : SysuiTestCase() { @Before fun setUp() { - utils = FooterActionsTestUtils(context, TestableLooper.get(this)) + utils = FooterActionsTestUtils(context, TestableLooper.get(this), TestCoroutineScheduler()) } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModelTest.kt index 081a2181cfe5c..47afa70fa84b8 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModelTest.kt @@ -29,6 +29,7 @@ import com.android.systemui.SysuiTestCase import com.android.systemui.broadcast.BroadcastDispatcher import com.android.systemui.common.shared.model.ContentDescription import com.android.systemui.common.shared.model.Icon +import com.android.systemui.coroutines.collectLastValue import com.android.systemui.qs.FakeFgsManagerController import com.android.systemui.qs.QSSecurityFooterUtils import com.android.systemui.qs.footer.FooterActionsTestUtils @@ -44,12 +45,9 @@ import com.android.systemui.util.mockito.mock import com.android.systemui.util.mockito.nullable import com.android.systemui.util.settings.FakeSettings import com.google.common.truth.Truth.assertThat -import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.launch -import kotlinx.coroutines.test.TestCoroutineScheduler import kotlinx.coroutines.test.TestScope -import kotlinx.coroutines.test.UnconfinedTestDispatcher import kotlinx.coroutines.test.advanceUntilIdle import kotlinx.coroutines.test.runTest import org.junit.Before @@ -62,16 +60,20 @@ import org.mockito.Mockito.`when` as whenever @RunWith(AndroidTestingRunner::class) @RunWithLooper class FooterActionsViewModelTest : SysuiTestCase() { + private val testScope = TestScope() private lateinit var utils: FooterActionsTestUtils - private val testDispatcher = UnconfinedTestDispatcher(TestCoroutineScheduler()) @Before fun setUp() { - utils = FooterActionsTestUtils(context, TestableLooper.get(this)) + utils = FooterActionsTestUtils(context, TestableLooper.get(this), testScope.testScheduler) + } + + private fun runTest(block: suspend TestScope.() -> Unit) { + testScope.runTest(testBody = block) } @Test - fun settingsButton() = runBlockingTest { + fun settingsButton() = runTest { val underTest = utils.footerActionsViewModel(showPowerButton = false) val settings = underTest.settings @@ -87,7 +89,7 @@ class FooterActionsViewModelTest : SysuiTestCase() { } @Test - fun powerButton() = runBlockingTest { + fun powerButton() = runTest { // Without power button. val underTestWithoutPower = utils.footerActionsViewModel(showPowerButton = false) assertThat(underTestWithoutPower.power).isNull() @@ -114,7 +116,7 @@ class FooterActionsViewModelTest : SysuiTestCase() { } @Test - fun userSwitcher() = runBlockingTest { + fun userSwitcher() = runTest { val picture: Drawable = mock() val userInfoController = FakeUserInfoController(FakeInfo(picture = picture)) val settings = FakeSettings() @@ -135,7 +137,6 @@ class FooterActionsViewModelTest : SysuiTestCase() { showPowerButton = false, footerActionsInteractor = utils.footerActionsInteractor( - bgDispatcher = testDispatcher, userSwitcherRepository = utils.userSwitcherRepository( userTracker = userTracker, @@ -143,22 +144,12 @@ class FooterActionsViewModelTest : SysuiTestCase() { userManager = userManager, userInfoController = userInfoController, userSwitcherController = userSwitcherControllerWrapper.controller, - bgDispatcher = testDispatcher, ), ) ) // Collect the user switcher into currentUserSwitcher. - var currentUserSwitcher: FooterActionsButtonViewModel? = null - val job = launch { underTest.userSwitcher.collect { currentUserSwitcher = it } } - fun currentUserSwitcher(): FooterActionsButtonViewModel? { - // Make sure we finish collecting the current user switcher. This is necessary because - // combined flows launch multiple coroutines in the current scope so we need to make - // sure we process all coroutines triggered by our flow collection before we make - // assertions on the current buttons. - advanceUntilIdle() - return currentUserSwitcher - } + val currentUserSwitcher = collectLastValue(underTest.userSwitcher) // The user switcher is disabled. assertThat(currentUserSwitcher()).isNull() @@ -203,12 +194,10 @@ class FooterActionsViewModelTest : SysuiTestCase() { // in guest mode. userInfoController.updateInfo { this.picture = mock() } assertThat(iconTint()).isNull() - - job.cancel() } @Test - fun security() = runBlockingTest { + fun security() = runTest { val securityController = FakeSecurityController() val qsSecurityFooterUtils = mock() @@ -224,22 +213,15 @@ class FooterActionsViewModelTest : SysuiTestCase() { footerActionsInteractor = utils.footerActionsInteractor( qsSecurityFooterUtils = qsSecurityFooterUtils, - bgDispatcher = testDispatcher, securityRepository = utils.securityRepository( securityController = securityController, - bgDispatcher = testDispatcher, ), ), ) // Collect the security model into currentSecurity. - var currentSecurity: FooterActionsSecurityButtonViewModel? = null - val job = launch { underTest.security.collect { currentSecurity = it } } - fun currentSecurity(): FooterActionsSecurityButtonViewModel? { - advanceUntilIdle() - return currentSecurity - } + val currentSecurity = collectLastValue(underTest.security) // By default, we always return a null SecurityButtonConfig. assertThat(currentSecurity()).isNull() @@ -270,12 +252,10 @@ class FooterActionsViewModelTest : SysuiTestCase() { security = currentSecurity() assertThat(security).isNotNull() assertThat(security!!.onClick).isNull() - - job.cancel() } @Test - fun foregroundServices() = runBlockingTest { + fun foregroundServices() = runTest { val securityController = FakeSecurityController() val fgsManagerController = FakeFgsManagerController( @@ -300,21 +280,14 @@ class FooterActionsViewModelTest : SysuiTestCase() { securityRepository = utils.securityRepository( securityController, - bgDispatcher = testDispatcher, ), foregroundServicesRepository = utils.foregroundServicesRepository(fgsManagerController), - bgDispatcher = testDispatcher, ), ) // Collect the security model into currentSecurity. - var currentForegroundServices: FooterActionsForegroundServicesButtonViewModel? = null - val job = launch { underTest.foregroundServices.collect { currentForegroundServices = it } } - fun currentForegroundServices(): FooterActionsForegroundServicesButtonViewModel? { - advanceUntilIdle() - return currentForegroundServices - } + val currentForegroundServices = collectLastValue(underTest.foregroundServices) // We don't show the foreground services button if the number of running packages is not // > 1. @@ -356,12 +329,10 @@ class FooterActionsViewModelTest : SysuiTestCase() { } securityController.updateState {} assertThat(currentForegroundServices()?.displayText).isFalse() - - job.cancel() } @Test - fun observeDeviceMonitoringDialogRequests() = runBlockingTest { + fun observeDeviceMonitoringDialogRequests() = runTest { val qsSecurityFooterUtils = mock() val broadcastDispatcher = mock() @@ -390,7 +361,6 @@ class FooterActionsViewModelTest : SysuiTestCase() { utils.footerActionsInteractor( qsSecurityFooterUtils = qsSecurityFooterUtils, broadcastDispatcher = broadcastDispatcher, - bgDispatcher = testDispatcher, ), ) @@ -415,7 +385,4 @@ class FooterActionsViewModelTest : SysuiTestCase() { underTest.onVisibilityChangeRequested(visible = true) assertThat(underTest.isVisible.value).isTrue() } - - private fun runBlockingTest(block: suspend TestScope.() -> Unit) = - runTest(testDispatcher) { block() } } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/footer/FooterActionsTestUtils.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/footer/FooterActionsTestUtils.kt index 63448e236867c..1a893f8c523c0 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/qs/footer/FooterActionsTestUtils.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/qs/footer/FooterActionsTestUtils.kt @@ -56,7 +56,8 @@ import com.android.systemui.util.mockito.mock import com.android.systemui.util.settings.FakeSettings import com.android.systemui.util.settings.GlobalSettings import kotlinx.coroutines.CoroutineDispatcher -import kotlinx.coroutines.test.TestCoroutineDispatcher +import kotlinx.coroutines.test.StandardTestDispatcher +import kotlinx.coroutines.test.TestCoroutineScheduler /** * Util class to create real implementations of the FooterActions repositories, viewModel and @@ -65,6 +66,7 @@ import kotlinx.coroutines.test.TestCoroutineDispatcher class FooterActionsTestUtils( private val context: Context, private val testableLooper: TestableLooper, + private val scheduler: TestCoroutineScheduler, ) { /** Enable or disable the user switcher in the settings. */ fun setUserSwitcherEnabled(settings: GlobalSettings, enabled: Boolean, userId: Int) { @@ -105,7 +107,7 @@ class FooterActionsTestUtils( foregroundServicesRepository: ForegroundServicesRepository = foregroundServicesRepository(), userSwitcherRepository: UserSwitcherRepository = userSwitcherRepository(), broadcastDispatcher: BroadcastDispatcher = mock(), - bgDispatcher: CoroutineDispatcher = TestCoroutineDispatcher(), + bgDispatcher: CoroutineDispatcher = StandardTestDispatcher(scheduler), ): FooterActionsInteractor { return FooterActionsInteractorImpl( activityStarter, @@ -126,7 +128,7 @@ class FooterActionsTestUtils( /** Create a [SecurityRepository] to be used in tests. */ fun securityRepository( securityController: SecurityController = FakeSecurityController(), - bgDispatcher: CoroutineDispatcher = TestCoroutineDispatcher(), + bgDispatcher: CoroutineDispatcher = StandardTestDispatcher(scheduler), ): SecurityRepository { return SecurityRepositoryImpl( securityController, @@ -145,7 +147,7 @@ class FooterActionsTestUtils( fun userSwitcherRepository( @Application context: Context = this.context.applicationContext, bgHandler: Handler = Handler(testableLooper.looper), - bgDispatcher: CoroutineDispatcher = TestCoroutineDispatcher(), + bgDispatcher: CoroutineDispatcher = StandardTestDispatcher(scheduler), userManager: UserManager = mock(), userTracker: UserTracker = FakeUserTracker(), userSwitcherController: UserSwitcherController = mock(), From 0cd96a9eed0e6af0252ef1ddf06ee9c2afd95c65 Mon Sep 17 00:00:00 2001 From: Jorge Gil Date: Mon, 28 Nov 2022 21:56:04 +0000 Subject: [PATCH 07/38] Create window decors for leaf tasks & skip non-leafs Fixes the logic that intended to filter out window decorations for non-leaf tasks. Previously, non-root leafs were mistakenly skipped instead of their parents, which went unnoticed until freeform tasks were nested and the non-root leafs were missing the caption bar. Bug: None Test: nest freeform tasks, leaf tasks have window decorations. Change-Id: Ia958fb43319d17a0e33e28497e52293954706416 --- .../wm/shell/freeform/FreeformTaskTransitionObserver.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionObserver.java b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionObserver.java index 168f6d79a3901..3be97c4998563 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionObserver.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionObserver.java @@ -90,7 +90,7 @@ public class FreeformTaskTransitionObserver implements Transitions.TransitionObs // This logic relies on 2 assumptions: 1 is that child tasks will be visited before // parents (due to how z-order works). 2 is that no non-tasks are interleaved // between tasks (hierarchically). - taskParents.add(change.getContainer()); + taskParents.add(change.getParent()); } if (taskParents.contains(change.getContainer())) { continue; From 3d563d27aa809f416621e715e12e8e3426b03f33 Mon Sep 17 00:00:00 2001 From: Nate Myren Date: Thu, 10 Nov 2022 14:07:28 -0800 Subject: [PATCH 08/38] RESTRICT AUTOMERGE Use chain start token in performOpTransaction Bug: 258672042 Test: atest CtsPermission4TestCases Change-Id: I1d484ed7c72d4ae73f4cbec47522a18ae9088f6e --- core/java/android/app/AppOpsManager.java | 22 ++++--- .../android/app/AppOpsManagerInternal.java | 23 ++++--- .../android/internal/app/IAppOpsService.aidl | 11 ++-- .../server/am/ActivityManagerService.java | 24 ++++---- .../android/server/appop/AppOpsService.java | 61 +++++++++---------- .../permission/PermissionManagerService.java | 39 ++++++------ .../android/server/policy/AppOpsPolicy.java | 18 +++--- 7 files changed, 103 insertions(+), 95 deletions(-) diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java index fc89e1395073b..5b1666935ba89 100644 --- a/core/java/android/app/AppOpsManager.java +++ b/core/java/android/app/AppOpsManager.java @@ -8888,8 +8888,9 @@ public class AppOpsManager { */ public int startProxyOpNoThrow(int op, @NonNull AttributionSource attributionSource, @Nullable String message, boolean skipProxyOperation) { - return startProxyOpNoThrow(op, attributionSource, message, skipProxyOperation, - ATTRIBUTION_FLAGS_NONE, ATTRIBUTION_FLAGS_NONE, ATTRIBUTION_CHAIN_ID_NONE); + return startProxyOpNoThrow(attributionSource.getToken(), op, attributionSource, message, + skipProxyOperation, ATTRIBUTION_FLAGS_NONE, ATTRIBUTION_FLAGS_NONE, + ATTRIBUTION_CHAIN_ID_NONE); } /** @@ -8901,7 +8902,8 @@ public class AppOpsManager { * * @hide */ - public int startProxyOpNoThrow(int op, @NonNull AttributionSource attributionSource, + public int startProxyOpNoThrow(@NonNull IBinder clientId, int op, + @NonNull AttributionSource attributionSource, @Nullable String message, boolean skipProxyOperation, @AttributionFlags int proxyAttributionFlags, @AttributionFlags int proxiedAttributionFlags, int attributionChainId) { @@ -8919,7 +8921,7 @@ public class AppOpsManager { } } - SyncNotedAppOp syncOp = mService.startProxyOperation(op, + SyncNotedAppOp syncOp = mService.startProxyOperation(clientId, op, attributionSource, false, collectionMode == COLLECT_ASYNC, message, shouldCollectMessage, skipProxyOperation, proxyAttributionFlags, proxiedAttributionFlags, attributionChainId); @@ -9017,9 +9019,10 @@ public class AppOpsManager { */ public void finishProxyOp(@NonNull String op, int proxiedUid, @NonNull String proxiedPackageName, @Nullable String proxiedAttributionTag) { - finishProxyOp(op, new AttributionSource(mContext.getAttributionSource(), + IBinder token = mContext.getAttributionSource().getToken(); + finishProxyOp(token, op, new AttributionSource(mContext.getAttributionSource(), new AttributionSource(proxiedUid, proxiedPackageName, proxiedAttributionTag, - mContext.getAttributionSource().getToken())), /*skipProxyOperation*/ false); + token)), /*skipProxyOperation*/ false); } /** @@ -9034,10 +9037,11 @@ public class AppOpsManager { * * @hide */ - public void finishProxyOp(@NonNull String op, @NonNull AttributionSource attributionSource, - boolean skipProxyOperation) { + public void finishProxyOp(@NonNull IBinder clientId, @NonNull String op, + @NonNull AttributionSource attributionSource, boolean skipProxyOperation) { try { - mService.finishProxyOperation(strOpToOp(op), attributionSource, skipProxyOperation); + mService.finishProxyOperation(clientId, strOpToOp(op), attributionSource, + skipProxyOperation); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/core/java/android/app/AppOpsManagerInternal.java b/core/java/android/app/AppOpsManagerInternal.java index 4d6e4aedba66c..43023fe9c2abb 100644 --- a/core/java/android/app/AppOpsManagerInternal.java +++ b/core/java/android/app/AppOpsManagerInternal.java @@ -26,13 +26,11 @@ import android.util.SparseArray; import android.util.SparseIntArray; import com.android.internal.app.IAppOpsCallback; -import com.android.internal.util.function.DecFunction; import com.android.internal.util.function.HeptFunction; import com.android.internal.util.function.HexFunction; import com.android.internal.util.function.QuadFunction; import com.android.internal.util.function.QuintConsumer; import com.android.internal.util.function.QuintFunction; -import com.android.internal.util.function.TriFunction; import com.android.internal.util.function.UndecFunction; /** @@ -135,6 +133,7 @@ public abstract class AppOpsManagerInternal { /** * Allows overriding start proxy operation behavior. * + * @param clientId The client calling start, represented by an IBinder * @param code The op code to start. * @param attributionSource The permission identity of the caller. * @param startIfModeDefault Whether to start the op of the mode is default. @@ -148,11 +147,12 @@ public abstract class AppOpsManagerInternal { * @param superImpl The super implementation. * @return The app op note result. */ - SyncNotedAppOp startProxyOperation(int code, @NonNull AttributionSource attributionSource, - boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, String message, - boolean shouldCollectMessage, boolean skipProxyOperation, @AttributionFlags - int proxyAttributionFlags, @AttributionFlags int proxiedAttributionFlags, - int attributionChainId, @NonNull DecFunction superImpl); @@ -176,10 +176,15 @@ public abstract class AppOpsManagerInternal { * * @param code The op code to finish. * @param attributionSource The permission identity of the caller. + * @param skipProxyOperation Whether to skip the proxy in the proxy/proxied operation + * @param clientId The client calling finishProxyOperation + * @param superImpl The "standard" implementation to potentially call */ - void finishProxyOperation(int code, @NonNull AttributionSource attributionSource, + void finishProxyOperation(@NonNull IBinder clientId, int code, + @NonNull AttributionSource attributionSource, boolean skipProxyOperation, - @NonNull TriFunction superImpl); + @NonNull QuadFunction superImpl); } /** diff --git a/core/java/com/android/internal/app/IAppOpsService.aidl b/core/java/com/android/internal/app/IAppOpsService.aidl index 30da4b470ab6d..88447daf73388 100644 --- a/core/java/com/android/internal/app/IAppOpsService.aidl +++ b/core/java/com/android/internal/app/IAppOpsService.aidl @@ -58,11 +58,12 @@ interface IAppOpsService { SyncNotedAppOp noteProxyOperation(int code, in AttributionSource attributionSource, boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage, boolean skipProxyOperation); - SyncNotedAppOp startProxyOperation(int code, in AttributionSource attributionSource, - boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, String message, - boolean shouldCollectMessage, boolean skipProxyOperation, int proxyAttributionFlags, - int proxiedAttributionFlags, int attributionChainId); - void finishProxyOperation(int code, in AttributionSource attributionSource, + SyncNotedAppOp startProxyOperation(IBinder clientId, int code, + in AttributionSource attributionSource, boolean startIfModeDefault, + boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage, + boolean skipProxyOperation, int proxyAttributionFlags, int proxiedAttributionFlags, + int attributionChainId); + void finishProxyOperation(IBinder clientId, int code, in AttributionSource attributionSource, boolean skipProxyOperation); // Remaining methods are only used in Java. diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 10b52e6bf529b..336433bbad898 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -351,12 +351,10 @@ import com.android.internal.util.FastPrintWriter; import com.android.internal.util.FrameworkStatsLog; import com.android.internal.util.MemInfoReader; import com.android.internal.util.Preconditions; -import com.android.internal.util.function.DecFunction; import com.android.internal.util.function.HeptFunction; import com.android.internal.util.function.HexFunction; import com.android.internal.util.function.QuadFunction; import com.android.internal.util.function.QuintFunction; -import com.android.internal.util.function.TriFunction; import com.android.internal.util.function.UndecFunction; import com.android.server.AlarmManagerInternal; import com.android.server.DeviceIdleInternal; @@ -17162,19 +17160,20 @@ public class ActivityManagerService extends IActivityManager.Stub } @Override - public SyncNotedAppOp startProxyOperation(int code, + public SyncNotedAppOp startProxyOperation(@NonNull IBinder clientId, int code, @NonNull AttributionSource attributionSource, boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage, boolean skipProxyOperation, @AttributionFlags int proxyAttributionFlags, @AttributionFlags int proxiedAttributionFlags, int attributionChainId, - @NonNull DecFunction superImpl) { + @NonNull UndecFunction superImpl) { if (attributionSource.getUid() == mTargetUid && isTargetOp(code)) { final int shellUid = UserHandle.getUid(UserHandle.getUserId( attributionSource.getUid()), Process.SHELL_UID); final long identity = Binder.clearCallingIdentity(); try { - return superImpl.apply(code, new AttributionSource(shellUid, + return superImpl.apply(clientId, code, new AttributionSource(shellUid, "com.android.shell", attributionSource.getAttributionTag(), attributionSource.getToken(), attributionSource.getNext()), startIfModeDefault, shouldCollectAsyncNotedOp, message, @@ -17184,21 +17183,22 @@ public class ActivityManagerService extends IActivityManager.Stub Binder.restoreCallingIdentity(identity); } } - return superImpl.apply(code, attributionSource, startIfModeDefault, + return superImpl.apply(clientId, code, attributionSource, startIfModeDefault, shouldCollectAsyncNotedOp, message, shouldCollectMessage, skipProxyOperation, proxyAttributionFlags, proxiedAttributionFlags, attributionChainId); } @Override - public void finishProxyOperation(int code, @NonNull AttributionSource attributionSource, - boolean skipProxyOperation, @NonNull TriFunction superImpl) { + public void finishProxyOperation(@NonNull IBinder clientId, int code, + @NonNull AttributionSource attributionSource, boolean skipProxyOperation, + @NonNull QuadFunction superImpl) { if (attributionSource.getUid() == mTargetUid && isTargetOp(code)) { final int shellUid = UserHandle.getUid(UserHandle.getUserId( attributionSource.getUid()), Process.SHELL_UID); final long identity = Binder.clearCallingIdentity(); try { - superImpl.apply(code, new AttributionSource(shellUid, + superImpl.apply(clientId, code, new AttributionSource(shellUid, "com.android.shell", attributionSource.getAttributionTag(), attributionSource.getToken(), attributionSource.getNext()), skipProxyOperation); @@ -17206,7 +17206,7 @@ public class ActivityManagerService extends IActivityManager.Stub Binder.restoreCallingIdentity(identity); } } - superImpl.apply(code, attributionSource, skipProxyOperation); + superImpl.apply(clientId, code, attributionSource, skipProxyOperation); } private boolean isTargetOp(int code) { diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java index 3808e0c93a38f..759099f89b761 100644 --- a/services/core/java/com/android/server/appop/AppOpsService.java +++ b/services/core/java/com/android/server/appop/AppOpsService.java @@ -3839,18 +3839,18 @@ public class AppOpsService extends IAppOpsService.Stub { } @Override - public SyncNotedAppOp startProxyOperation(int code, + public SyncNotedAppOp startProxyOperation(@NonNull IBinder clientId, int code, @NonNull AttributionSource attributionSource, boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage, boolean skipProxyOperation, @AttributionFlags int proxyAttributionFlags, @AttributionFlags int proxiedAttributionFlags, int attributionChainId) { - return mCheckOpsDelegateDispatcher.startProxyOperation(code, attributionSource, + return mCheckOpsDelegateDispatcher.startProxyOperation(clientId, code, attributionSource, startIfModeDefault, shouldCollectAsyncNotedOp, message, shouldCollectMessage, skipProxyOperation, proxyAttributionFlags, proxiedAttributionFlags, attributionChainId); } - private SyncNotedAppOp startProxyOperationImpl(int code, + private SyncNotedAppOp startProxyOperationImpl(@NonNull IBinder clientId, int code, @NonNull AttributionSource attributionSource, boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage, boolean skipProxyOperation, @AttributionFlags @@ -3859,11 +3859,9 @@ public class AppOpsService extends IAppOpsService.Stub { final int proxyUid = attributionSource.getUid(); final String proxyPackageName = attributionSource.getPackageName(); final String proxyAttributionTag = attributionSource.getAttributionTag(); - final IBinder proxyToken = attributionSource.getToken(); final int proxiedUid = attributionSource.getNextUid(); final String proxiedPackageName = attributionSource.getNextPackageName(); final String proxiedAttributionTag = attributionSource.getNextAttributionTag(); - final IBinder proxiedToken = attributionSource.getNextToken(); verifyIncomingProxyUid(attributionSource); verifyIncomingOp(code); @@ -3902,7 +3900,7 @@ public class AppOpsService extends IAppOpsService.Stub { if (!skipProxyOperation) { // Test if the proxied operation will succeed before starting the proxy operation - final SyncNotedAppOp testProxiedOp = startOperationUnchecked(proxiedToken, code, + final SyncNotedAppOp testProxiedOp = startOperationUnchecked(clientId, code, proxiedUid, resolvedProxiedPackageName, proxiedAttributionTag, proxyUid, resolvedProxyPackageName, proxyAttributionTag, proxiedFlags, startIfModeDefault, shouldCollectAsyncNotedOp, message, shouldCollectMessage, @@ -3914,7 +3912,7 @@ public class AppOpsService extends IAppOpsService.Stub { final int proxyFlags = isProxyTrusted ? AppOpsManager.OP_FLAG_TRUSTED_PROXY : AppOpsManager.OP_FLAG_UNTRUSTED_PROXY; - final SyncNotedAppOp proxyAppOp = startOperationUnchecked(proxyToken, code, proxyUid, + final SyncNotedAppOp proxyAppOp = startOperationUnchecked(clientId, code, proxyUid, resolvedProxyPackageName, proxyAttributionTag, Process.INVALID_UID, null, null, proxyFlags, startIfModeDefault, !isProxyTrusted, "proxy " + message, shouldCollectMessage, proxyAttributionFlags, attributionChainId, @@ -3924,7 +3922,7 @@ public class AppOpsService extends IAppOpsService.Stub { } } - return startOperationUnchecked(proxiedToken, code, proxiedUid, resolvedProxiedPackageName, + return startOperationUnchecked(clientId, code, proxiedUid, resolvedProxiedPackageName, proxiedAttributionTag, proxyUid, resolvedProxyPackageName, proxyAttributionTag, proxiedFlags, startIfModeDefault, shouldCollectAsyncNotedOp, message, shouldCollectMessage, proxiedAttributionFlags, attributionChainId, @@ -4065,22 +4063,20 @@ public class AppOpsService extends IAppOpsService.Stub { } @Override - public void finishProxyOperation(int code, @NonNull AttributionSource attributionSource, - boolean skipProxyOperation) { - mCheckOpsDelegateDispatcher.finishProxyOperation(code, attributionSource, + public void finishProxyOperation(@NonNull IBinder clientId, int code, + @NonNull AttributionSource attributionSource, boolean skipProxyOperation) { + mCheckOpsDelegateDispatcher.finishProxyOperation(clientId, code, attributionSource, skipProxyOperation); } - private Void finishProxyOperationImpl(int code, @NonNull AttributionSource attributionSource, - boolean skipProxyOperation) { + private Void finishProxyOperationImpl(IBinder clientId, int code, + @NonNull AttributionSource attributionSource, boolean skipProxyOperation) { final int proxyUid = attributionSource.getUid(); final String proxyPackageName = attributionSource.getPackageName(); final String proxyAttributionTag = attributionSource.getAttributionTag(); - final IBinder proxyToken = attributionSource.getToken(); final int proxiedUid = attributionSource.getNextUid(); final String proxiedPackageName = attributionSource.getNextPackageName(); final String proxiedAttributionTag = attributionSource.getNextAttributionTag(); - final IBinder proxiedToken = attributionSource.getNextToken(); skipProxyOperation = skipProxyOperation && isCallerAndAttributionTrusted(attributionSource); @@ -4097,7 +4093,7 @@ public class AppOpsService extends IAppOpsService.Stub { } if (!skipProxyOperation) { - finishOperationUnchecked(proxyToken, code, proxyUid, resolvedProxyPackageName, + finishOperationUnchecked(clientId, code, proxyUid, resolvedProxyPackageName, proxyAttributionTag); } @@ -4107,7 +4103,7 @@ public class AppOpsService extends IAppOpsService.Stub { return null; } - finishOperationUnchecked(proxiedToken, code, proxiedUid, resolvedProxiedPackageName, + finishOperationUnchecked(clientId, code, proxiedUid, resolvedProxiedPackageName, proxiedAttributionTag); return null; @@ -7642,42 +7638,42 @@ public class AppOpsService extends IAppOpsService.Stub { attributionFlags, attributionChainId, AppOpsService.this::startOperationImpl); } - public SyncNotedAppOp startProxyOperation(int code, + public SyncNotedAppOp startProxyOperation(@NonNull IBinder clientId, int code, @NonNull AttributionSource attributionSource, boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage, boolean skipProxyOperation, @AttributionFlags int proxyAttributionFlags, @AttributionFlags int proxiedAttributionFlags, int attributionChainId) { if (mPolicy != null) { if (mCheckOpsDelegate != null) { - return mPolicy.startProxyOperation(code, attributionSource, + return mPolicy.startProxyOperation(clientId, code, attributionSource, startIfModeDefault, shouldCollectAsyncNotedOp, message, shouldCollectMessage, skipProxyOperation, proxyAttributionFlags, proxiedAttributionFlags, attributionChainId, this::startDelegateProxyOperationImpl); } else { - return mPolicy.startProxyOperation(code, attributionSource, + return mPolicy.startProxyOperation(clientId, code, attributionSource, startIfModeDefault, shouldCollectAsyncNotedOp, message, shouldCollectMessage, skipProxyOperation, proxyAttributionFlags, proxiedAttributionFlags, attributionChainId, AppOpsService.this::startProxyOperationImpl); } } else if (mCheckOpsDelegate != null) { - return startDelegateProxyOperationImpl(code, attributionSource, + return startDelegateProxyOperationImpl(clientId, code, attributionSource, startIfModeDefault, shouldCollectAsyncNotedOp, message, shouldCollectMessage, skipProxyOperation, proxyAttributionFlags, proxiedAttributionFlags, attributionChainId); } - return startProxyOperationImpl(code, attributionSource, startIfModeDefault, + return startProxyOperationImpl(clientId, code, attributionSource, startIfModeDefault, shouldCollectAsyncNotedOp, message, shouldCollectMessage, skipProxyOperation, proxyAttributionFlags, proxiedAttributionFlags, attributionChainId); } - private SyncNotedAppOp startDelegateProxyOperationImpl(int code, + private SyncNotedAppOp startDelegateProxyOperationImpl(@NonNull IBinder clientId, int code, @NonNull AttributionSource attributionSource, boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage, boolean skipProxyOperation, @AttributionFlags int proxyAttributionFlags, @AttributionFlags int proxiedAttributionFlsgs, int attributionChainId) { - return mCheckOpsDelegate.startProxyOperation(code, attributionSource, + return mCheckOpsDelegate.startProxyOperation(clientId, code, attributionSource, startIfModeDefault, shouldCollectAsyncNotedOp, message, shouldCollectMessage, skipProxyOperation, proxyAttributionFlags, proxiedAttributionFlsgs, attributionChainId, AppOpsService.this::startProxyOperationImpl); @@ -7706,27 +7702,28 @@ public class AppOpsService extends IAppOpsService.Stub { AppOpsService.this::finishOperationImpl); } - public void finishProxyOperation(int code, + public void finishProxyOperation(@NonNull IBinder clientId, int code, @NonNull AttributionSource attributionSource, boolean skipProxyOperation) { if (mPolicy != null) { if (mCheckOpsDelegate != null) { - mPolicy.finishProxyOperation(code, attributionSource, + mPolicy.finishProxyOperation(clientId, code, attributionSource, skipProxyOperation, this::finishDelegateProxyOperationImpl); } else { - mPolicy.finishProxyOperation(code, attributionSource, + mPolicy.finishProxyOperation(clientId, code, attributionSource, skipProxyOperation, AppOpsService.this::finishProxyOperationImpl); } } else if (mCheckOpsDelegate != null) { - finishDelegateProxyOperationImpl(code, attributionSource, skipProxyOperation); + finishDelegateProxyOperationImpl(clientId, code, attributionSource, + skipProxyOperation); } else { - finishProxyOperationImpl(code, attributionSource, skipProxyOperation); + finishProxyOperationImpl(clientId, code, attributionSource, skipProxyOperation); } } - private Void finishDelegateProxyOperationImpl(int code, + private Void finishDelegateProxyOperationImpl(@NonNull IBinder clientId, int code, @NonNull AttributionSource attributionSource, boolean skipProxyOperation) { - mCheckOpsDelegate.finishProxyOperation(code, attributionSource, skipProxyOperation, - AppOpsService.this::finishProxyOperationImpl); + mCheckOpsDelegate.finishProxyOperation(clientId, code, attributionSource, + skipProxyOperation, AppOpsService.this::finishProxyOperationImpl); return null; } } diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java index 5e54f937fc983..9d0b2543e5efc 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java @@ -5650,7 +5650,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { if (resolvedPackageName == null) { return; } - appOpsManager.finishOp(accessorSource.getToken(), op, + appOpsManager.finishOp(attributionSourceState.token, op, accessorSource.getUid(), resolvedPackageName, accessorSource.getAttributionTag()); } else { @@ -5659,8 +5659,9 @@ public class PermissionManagerService extends IPermissionManager.Stub { if (resolvedAttributionSource.getPackageName() == null) { return; } - appOpsManager.finishProxyOp(AppOpsManager.opToPublicName(op), - resolvedAttributionSource, skipCurrentFinish); + appOpsManager.finishProxyOp(attributionSourceState.token, + AppOpsManager.opToPublicName(op), resolvedAttributionSource, + skipCurrentFinish); } if (next == null || next.getNext() == null) { @@ -5770,10 +5771,11 @@ public class PermissionManagerService extends IPermissionManager.Stub { && next.getNext() == null); final boolean selfAccess = singleReceiverFromDatasource || next == null; - final int opMode = performOpTransaction(context, op, current, message, - forDataDelivery, /*startDataDelivery*/ false, skipCurrentChecks, - selfAccess, singleReceiverFromDatasource, AppOpsManager.OP_NONE, - AppOpsManager.ATTRIBUTION_FLAGS_NONE, AppOpsManager.ATTRIBUTION_FLAGS_NONE, + final int opMode = performOpTransaction(context, attributionSource.getToken(), op, + current, message, forDataDelivery, /*startDataDelivery*/ false, + skipCurrentChecks, selfAccess, singleReceiverFromDatasource, + AppOpsManager.OP_NONE, AppOpsManager.ATTRIBUTION_FLAGS_NONE, + AppOpsManager.ATTRIBUTION_FLAGS_NONE, AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE); switch (opMode) { @@ -5875,10 +5877,10 @@ public class PermissionManagerService extends IPermissionManager.Stub { attributionSource, next, fromDatasource, startDataDelivery, selfAccess, isLinkTrusted) : ATTRIBUTION_FLAGS_NONE; - final int opMode = performOpTransaction(context, op, current, message, - forDataDelivery, startDataDelivery, skipCurrentChecks, selfAccess, - singleReceiverFromDatasource, attributedOp, proxyAttributionFlags, - proxiedAttributionFlags, attributionChainId); + final int opMode = performOpTransaction(context, attributionSource.getToken(), op, + current, message, forDataDelivery, startDataDelivery, skipCurrentChecks, + selfAccess, singleReceiverFromDatasource, attributedOp, + proxyAttributionFlags, proxiedAttributionFlags, attributionChainId); switch (opMode) { case AppOpsManager.MODE_ERRORED: { @@ -6023,8 +6025,8 @@ public class PermissionManagerService extends IPermissionManager.Stub { attributionSource, next, /*fromDatasource*/ false, startDataDelivery, selfAccess, isLinkTrusted) : ATTRIBUTION_FLAGS_NONE; - final int opMode = performOpTransaction(context, op, current, message, - forDataDelivery, startDataDelivery, skipCurrentChecks, selfAccess, + final int opMode = performOpTransaction(context, current.getToken(), op, current, + message, forDataDelivery, startDataDelivery, skipCurrentChecks, selfAccess, /*fromDatasource*/ false, AppOpsManager.OP_NONE, proxyAttributionFlags, proxiedAttributionFlags, attributionChainId); @@ -6046,7 +6048,8 @@ public class PermissionManagerService extends IPermissionManager.Stub { } @SuppressWarnings("ConstantConditions") - private static int performOpTransaction(@NonNull Context context, int op, + private static int performOpTransaction(@NonNull Context context, + @NonNull IBinder chainStartToken, int op, @NonNull AttributionSource attributionSource, @Nullable String message, boolean forDataDelivery, boolean startDataDelivery, boolean skipProxyOperation, boolean selfAccess, boolean singleReceiverFromDatasource, int attributedOp, @@ -6108,7 +6111,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { if (selfAccess) { try { startedOpResult = appOpsManager.startOpNoThrow( - resolvedAttributionSource.getToken(), startedOp, + chainStartToken, startedOp, resolvedAttributionSource.getUid(), resolvedAttributionSource.getPackageName(), /*startIfModeDefault*/ false, @@ -6119,12 +6122,12 @@ public class PermissionManagerService extends IPermissionManager.Stub { + " platform defined runtime permission " + AppOpsManager.opToPermission(op) + " while not having " + Manifest.permission.UPDATE_APP_OPS_STATS); - startedOpResult = appOpsManager.startProxyOpNoThrow(attributedOp, - attributionSource, message, skipProxyOperation, + startedOpResult = appOpsManager.startProxyOpNoThrow(chainStartToken, + attributedOp, attributionSource, message, skipProxyOperation, proxyAttributionFlags, proxiedAttributionFlags, attributionChainId); } } else { - startedOpResult = appOpsManager.startProxyOpNoThrow(startedOp, + startedOpResult = appOpsManager.startProxyOpNoThrow(chainStartToken, startedOp, resolvedAttributionSource, message, skipProxyOperation, proxyAttributionFlags, proxiedAttributionFlags, attributionChainId); } diff --git a/services/core/java/com/android/server/policy/AppOpsPolicy.java b/services/core/java/com/android/server/policy/AppOpsPolicy.java index e5db2e4dab35e..55f9a59b866b8 100644 --- a/services/core/java/com/android/server/policy/AppOpsPolicy.java +++ b/services/core/java/com/android/server/policy/AppOpsPolicy.java @@ -44,13 +44,11 @@ import android.util.Log; import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; -import com.android.internal.util.function.DecFunction; import com.android.internal.util.function.HeptFunction; import com.android.internal.util.function.HexFunction; import com.android.internal.util.function.QuadFunction; import com.android.internal.util.function.QuintConsumer; import com.android.internal.util.function.QuintFunction; -import com.android.internal.util.function.TriFunction; import com.android.internal.util.function.UndecFunction; import com.android.server.LocalServices; @@ -255,14 +253,14 @@ public final class AppOpsPolicy implements AppOpsManagerInternal.CheckOpsDelegat } @Override - public SyncNotedAppOp startProxyOperation(int code, + public SyncNotedAppOp startProxyOperation(@NonNull IBinder clientId, int code, @NonNull AttributionSource attributionSource, boolean startIfModeDefault, boolean shouldCollectAsyncNotedOp, String message, boolean shouldCollectMessage, boolean skipProxyOperation, @AttributionFlags int proxyAttributionFlags, @AttributionFlags int proxiedAttributionFlags, int attributionChainId, - @NonNull DecFunction superImpl) { - return superImpl.apply(resolveDatasourceOp(code, attributionSource.getUid(), + @NonNull UndecFunction superImpl) { + return superImpl.apply(clientId, resolveDatasourceOp(code, attributionSource.getUid(), attributionSource.getPackageName(), attributionSource.getAttributionTag()), attributionSource, startIfModeDefault, shouldCollectAsyncNotedOp, message, shouldCollectMessage, skipProxyOperation, proxyAttributionFlags, @@ -278,10 +276,10 @@ public final class AppOpsPolicy implements AppOpsManagerInternal.CheckOpsDelegat } @Override - public void finishProxyOperation(int code, @NonNull AttributionSource attributionSource, - boolean skipProxyOperation, @NonNull TriFunction superImpl) { - superImpl.apply(resolveDatasourceOp(code, attributionSource.getUid(), + public void finishProxyOperation(@NonNull IBinder clientId, int code, + @NonNull AttributionSource attributionSource, boolean skipProxyOperation, + @NonNull QuadFunction superImpl) { + superImpl.apply(clientId, resolveDatasourceOp(code, attributionSource.getUid(), attributionSource.getPackageName(), attributionSource.getAttributionTag()), attributionSource, skipProxyOperation); } From f2b189458541e22b24c02426353c4b0288365a72 Mon Sep 17 00:00:00 2001 From: Peter Kalauskas Date: Wed, 16 Nov 2022 15:14:17 -0800 Subject: [PATCH 09/38] New javadoc for SysUI CoreStartables Test: n/a Bug: 259474752 Change-Id: Ide39a7bef9852980f5d8ad4c075edd0e4b53386b --- .../src/com/android/systemui/CoreStartable.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/CoreStartable.java b/packages/SystemUI/src/com/android/systemui/CoreStartable.java index 929ebea37eef0..becf5b39e9dfc 100644 --- a/packages/SystemUI/src/com/android/systemui/CoreStartable.java +++ b/packages/SystemUI/src/com/android/systemui/CoreStartable.java @@ -39,10 +39,13 @@ import java.io.PrintWriter; */ public interface CoreStartable extends Dumpable { - /** Main entry point for implementations. Called shortly after app startup. */ + /** Main entry point for implementations. Called shortly after SysUI startup. */ void start(); - /** */ + /** Called when the device configuration changes. This will not be called before + * {@link #start()}, but it could be called before {@link #onBootCompleted()}. + * + * @see android.app.Application#onConfigurationChanged(Configuration) */ default void onConfigurationChanged(Configuration newConfig) { } @@ -50,7 +53,11 @@ public interface CoreStartable extends Dumpable { default void dump(@NonNull PrintWriter pw, @NonNull String[] args) { } - /** Called when the device reports BOOT_COMPLETED. */ + /** Called immediately after the system broadcasts + * {@link android.content.Intent#ACTION_LOCKED_BOOT_COMPLETED} or during SysUI startup if the + * property {@code sys.boot_completed} is already set to 1. The latter typically occurs when + * starting a new SysUI instance, such as when starting SysUI for a secondary user. + * {@link #onBootCompleted()} will never be called before {@link #start()}. */ default void onBootCompleted() { } } From 0f31aa29c2ff311c1ae0c4c4cca6f5539173e8ec Mon Sep 17 00:00:00 2001 From: Jerry Chang Date: Wed, 30 Nov 2022 04:13:43 +0000 Subject: [PATCH 10/38] Consolidate leaving split screen to pip mode behavior Stop always putting another side to the bottom when a splitting task is entering pip mode. Leave it to onStageHasChildrenChanged to handle, and prevent expanding non-visible side to the top after dismissed the split screen, so flows of leaving split to pip like swipe-to-home or launching another fullscreen app won't expand another side to top unexpectedly. When swipe-to-home from a split pair, it dismisses split screen. However, it also performs fling divider to dismiss animation if one side of the split is empty due to entering pip. Which might be conflicting with each other and leaves the split layout modified with the fling animation but not preperly reset divide position. Update to make sure it always resets divide position and cancel running fling animation after split screen dismissed. Fix: 227727673 Test: atest WMShellUnitTests Test: verify entering pip from split behavior with back-key, home-key and launching another fullscreen app. Video: http://recall/-/fLARJNt42LVxc3tt86SneW/gvATxkQhdJ0APek6RwRHel http://recall/-/fLARJNt42LVxc3tt86SneW/QfHt9H0XtDNDSP3h1AA8K http://recall/-/fLARJNt42LVxc3tt86SneW/QnbdeWo2007s8ZuMf1Syn Change-Id: I2c53ed21e4766d06180e670ee21534cd622db081 --- .../wm/shell/common/split/SplitLayout.java | 23 ++++++++++++++----- .../shell/splitscreen/StageCoordinator.java | 15 +----------- .../shell/splitscreen/StageTaskListener.java | 6 ----- 3 files changed, 18 insertions(+), 26 deletions(-) diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java index ae496165028f5..45b234a6398a7 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java @@ -122,6 +122,7 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange private int mDensity; private final boolean mDimNonImeSide; + private ValueAnimator mDividerFlingAnimator; public SplitLayout(String windowName, Context context, Configuration configuration, SplitLayoutHandler splitLayoutHandler, @@ -395,6 +396,10 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange mSplitWindowManager.release(t); mDisplayImeController.removePositionProcessor(mImePositionProcessor); mImePositionProcessor.reset(); + if (mDividerFlingAnimator != null) { + mDividerFlingAnimator.cancel(); + } + resetDividerPosition(); } public void release() { @@ -577,13 +582,18 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange CUJ_SPLIT_SCREEN_RESIZE); return; } - ValueAnimator animator = ValueAnimator + + if (mDividerFlingAnimator != null) { + mDividerFlingAnimator.cancel(); + } + + mDividerFlingAnimator = ValueAnimator .ofInt(from, to) .setDuration(duration); - animator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN); - animator.addUpdateListener( + mDividerFlingAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN); + mDividerFlingAnimator.addUpdateListener( animation -> updateDivideBounds((int) animation.getAnimatedValue())); - animator.addListener(new AnimatorListenerAdapter() { + mDividerFlingAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { if (flingFinishedCallback != null) { @@ -591,14 +601,15 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange } InteractionJankMonitorUtils.endTracing( CUJ_SPLIT_SCREEN_RESIZE); + mDividerFlingAnimator = null; } @Override public void onAnimationCancel(Animator animation) { - setDividePosition(to, true /* applyLayoutChange */); + mDividerFlingAnimator = null; } }); - animator.start(); + mDividerFlingAnimator.start(); } /** Switch both surface position with animation. */ 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 acb71a80ee8a0..d805a5a262ecf 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 @@ -1035,7 +1035,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, mIsDividerRemoteAnimating = false; mSplitLayout.getInvisibleBounds(mTempRect1); - if (childrenToTop == null) { + if (childrenToTop == null || childrenToTop.getTopVisibleChildTaskId() == INVALID_TASK_ID) { mSideStage.removeAllTasks(wct, false /* toTop */); mMainStage.deactivate(wct, false /* toTop */); wct.reorder(mRootTaskInfo.token, false /* onTop */); @@ -1294,13 +1294,6 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, } } - private void onStageChildTaskEnterPip() { - // When the exit split-screen is caused by one of the task enters auto pip, - // we want both tasks to be put to bottom instead of top, otherwise it will end up - // a fullscreen plus a pinned task instead of pinned only at the end of the transition. - exitSplitScreen(null, EXIT_REASON_CHILD_TASK_ENTER_PIP); - } - private void updateRecentTasksSplitPair() { if (!mShouldUpdateRecents) { return; @@ -2063,7 +2056,6 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, // Update divider state after animation so that it is still around and positioned // properly for the animation itself. mSplitLayout.release(); - mSplitLayout.resetDividerPosition(); mTopStageAfterFoldDismiss = STAGE_TYPE_UNDEFINED; } } @@ -2339,11 +2331,6 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, StageCoordinator.this.onStageChildTaskStatusChanged(this, taskId, present, visible); } - @Override - public void onChildTaskEnterPip() { - StageCoordinator.this.onStageChildTaskEnterPip(); - } - @Override public void onRootTaskVanished() { reset(); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java index bcf900b99c69e..358f712f76b5c 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java @@ -18,7 +18,6 @@ package com.android.wm.shell.splitscreen; import static android.app.ActivityTaskManager.INVALID_TASK_ID; import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; -import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.view.RemoteAnimationTarget.MODE_OPENING; @@ -74,8 +73,6 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener { void onChildTaskStatusChanged(int taskId, boolean present, boolean visible); - void onChildTaskEnterPip(); - void onRootTaskVanished(); void onNoLongerSupportMultiWindow(); @@ -257,9 +254,6 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener { // Status is managed/synchronized by the transition lifecycle. return; } - if (taskInfo.getWindowingMode() == WINDOWING_MODE_PINNED) { - mCallbacks.onChildTaskEnterPip(); - } sendStatusChanged(); } else { throw new IllegalArgumentException(this + "\n Unknown task: " + taskInfo From b5cb17d008e28f528dae3a79f2232a0e3fe07950 Mon Sep 17 00:00:00 2001 From: Bill Yi Date: Wed, 30 Nov 2022 01:03:58 -0800 Subject: [PATCH 11/38] Import translations. DO NOT MERGE ANYWHERE Auto-generated-cl: translation import Change-Id: Iac5322a27c67416345fbf63f8a46c10daac13aab --- packages/SettingsLib/res/values-vi/strings.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml index f868c694cef9d..e66e3a175336e 100644 --- a/packages/SettingsLib/res/values-vi/strings.xml +++ b/packages/SettingsLib/res/values-vi/strings.xml @@ -278,7 +278,7 @@ "Ứng dụng vị trí mô phỏng: %1$s" "Mạng" "Chứng nhận hiển thị không dây" - "Bật ghi nhật ký chi tiết Wi‑Fi" + "Bật tính năng ghi nhật ký chi tiết Wi‑Fi" "Hạn chế quét tìm Wi-Fi" "Tạo địa chỉ MAC ngẫu nhiên, không cố định mỗi khi kết nối Wi-Fi" "Dữ liệu di động luôn hoạt động" @@ -290,7 +290,7 @@ "Chọn phiên bản Bluetooth AVRCP" "Phiên bản Bluetooth MAP" "Chọn phiên bản Bluetooth MAP" - "Codec âm thanh Bluetooth" + "Bộ mã hoá và giải mã âm thanh qua Bluetooth" "Kích hoạt chế độ chọn codec\nâm thanh Bluetooth" "Tốc độ lấy mẫu âm thanh Bluetooth" "Kích hoạt chế độ chọn codec\nâm thanh Bluetooth: Tần số lấy mẫu" @@ -384,7 +384,7 @@ "Cho phép làm mờ cửa sổ" "Bắt buộc 4x MSAA" "Bật 4x MSAA trong ứng dụng OpenGL ES 2.0" - "Gỡ lỗi hoạt động của clip không phải là hình chữ nhật" + "Gỡ lỗi hoạt động của đoạn không phải hình chữ nhật" "Kết xuất HWUI cấu hình" "Bật lớp gỡ lỗi GPU" "Cho phép tải lớp gỡ lỗi GPU cho ứng dụng gỡ lỗi" From c3addc163ff9f638cfcd800bdfdc6095b1b2979d Mon Sep 17 00:00:00 2001 From: Bill Yi Date: Wed, 30 Nov 2022 04:43:00 -0800 Subject: [PATCH 12/38] Import translations. DO NOT MERGE ANYWHERE Auto-generated-cl: translation import Change-Id: I848d1c6b14c57492e2a28af0d4387520a9657ade --- core/res/res/values-es/strings.xml | 2 +- core/res/res/values-gl/strings.xml | 6 +++--- core/res/res/values-nl/strings.xml | 8 ++++---- core/res/res/values-or/strings.xml | 24 ++++++++++++------------ core/res/res/values-ru/strings.xml | 2 +- 5 files changed, 21 insertions(+), 21 deletions(-) diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml index fcbe2b8b62b31..d956e9ac2f9cd 100644 --- a/core/res/res/values-es/strings.xml +++ b/core/res/res/values-es/strings.xml @@ -91,7 +91,7 @@ "Alertas" "Desvío de llamadas" "Modo de devolución de llamada de emergencia" - "Estado de los datos móviles" + "Estado de datos móviles" "Mensajes SMS" "Mensajes de voz" "Llamada por Wi-Fi" diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml index 9b68186606622..57dcc90620995 100644 --- a/core/res/res/values-gl/strings.xml +++ b/core/res/res/values-gl/strings.xml @@ -1949,13 +1949,13 @@ "A configuración de Android TV non está dispoñible" "A configuración da tableta non está dispoñible" "A configuración do teléfono non está dispoñible" - "Nestes momentos, non podes acceder a este contido desde o teu dispositivo (%1$s). Proba a facelo desde o dispositivo con Android TV." + "Nestes momentos, non podes acceder a este contido desde o teu dispositivo (%1$s). Proba a facelo desde o dispositivo Android TV." "Nestes momentos, non podes acceder a este contido desde o teu dispositivo (%1$s). Proba a facelo desde a tableta." "Nestes momentos, non podes acceder a este contido desde o teu dispositivo (%1$s). Proba a facelo desde o teléfono." - "Esta aplicación solicita seguranza adicional. Proba a facelo desde o dispositivo con Android TV." + "Esta aplicación solicita seguranza adicional. Proba a facelo desde o dispositivo Android TV." "Esta aplicación solicita seguranza adicional. Proba a facelo desde a tableta." "Esta aplicación solicita seguranza adicional. Proba a facelo desde o teléfono." - "Non se puido acceder a este contido desde o teu dispositivo (%1$s). Proba a facelo desde o dispositivo con Android TV." + "Non se puido acceder a este contido desde o teu dispositivo (%1$s). Proba a facelo desde o dispositivo Android TV." "Non se puido acceder a este contido desde o teu dispositivo (%1$s). Proba a facelo desde a tableta." "Non se puido acceder a este contido desde o teu dispositivo (%1$s). Proba a facelo desde o teléfono." "Esta aplicación deseñouse para unha versión anterior de Android e quizais non funcione correctamente. Proba a buscar actualizacións ou contacta co programador." diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml index 251a53a857652..6b80aa3355a40 100644 --- a/core/res/res/values-nl/strings.xml +++ b/core/res/res/values-nl/strings.xml @@ -260,7 +260,7 @@ "Stille modus" "Geluid is UIT" "Geluid is AAN" - "Vliegtuigmodus" + "Vliegtuig­modus" "Vliegtuigmodus is AAN" "Vliegtuigmodus is UIT" "Instellingen" @@ -990,7 +990,7 @@ "Gebruikersselectie" "Status" "Camera" - "Mediabediening" + "Media­bediening" "Opnieuw indelen van widget gestart." "Opnieuw indelen van widget beëindigd." "Widget %1$s verwijderd." @@ -1482,7 +1482,7 @@ "U gebruikt deze app in je werkprofiel" "Invoermethode" "Synchroniseren" - "Toegankelijkheid" + "Toe­gankelijk­heid" "Achtergrond" "Achtergrond wijzigen" "Listener voor meldingen" @@ -1986,7 +1986,7 @@ "Nieuws en tijdschriften" "Maps en navigatie" "Productiviteit" - "Toegankelijkheid" + "Toe­gankelijk­heid" "Apparaatopslag" "USB-foutopsporing" "uur" diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml index 26bfeb4acec2a..dfb64e2c0621a 100644 --- a/core/res/res/values-or/strings.xml +++ b/core/res/res/values-or/strings.xml @@ -90,7 +90,7 @@ "ଆଲର୍ଟ" "କଲ୍‌ ଫରୱାର୍ଡିଂ" "ଜରୁରୀକାଳୀନ କଲବ୍ୟାକ୍‍ ମୋଡ୍‍" - "ମୋବାଇଲ୍‍ ଡାଟା ଷ୍ଟାଟସ୍‌" + "ମୋବାଇଲ ଡାଟା ଷ୍ଟାଟସ" "SMS ମେସେଜ୍‌" "ଭଏସମେଲ୍‍ ମେସେଜ୍‍" "ୱାଇ-ଫାଇ କଲିଙ୍ଗ" @@ -799,30 +799,30 @@ "ୱାର୍କ ଫ୍ୟାକ୍ସ" "ହୋମ ଫାକ୍ସ" "ପେଜର୍" - "ଅନ୍ୟାନ୍ୟ" + "ଅନ୍ୟ" "କଷ୍ଟମ୍‌" "ହୋମ" "ୱାର୍କ" - "ଅନ୍ୟାନ୍ୟ" + "ଅନ୍ୟ" "କଷ୍ଟମ୍‌" "ହୋମ" "ୱାର୍କ" - "ଅନ୍ୟାନ୍ୟ" + "ଅନ୍ୟ" "କଷ୍ଟମ୍‌" "ହୋମ" "ୱାର୍କ" - "ଅନ୍ୟାନ୍ୟ" + "ଅନ୍ୟ" "କଷ୍ଟମ୍‌" "ୱାର୍କ" - "ଅନ୍ୟାନ୍ୟ" + "ଅନ୍ୟ" "କଷ୍ଟମ୍‌" @@ -842,7 +842,7 @@ "ୱାର୍କ ଫାକ୍ସ" "ହୋମ ଫାକ୍ସ" "ପେଜର୍" - "ଅନ୍ୟାନ୍ୟ" + "ଅନ୍ୟ" "କଲବ୍ୟାକ୍" "କାର୍" "କମ୍ପାନୀର ମୁଖ୍ୟ" @@ -863,16 +863,16 @@ "କଷ୍ଟମ୍‌" "ହୋମ" "ୱାର୍କ" - "ଅନ୍ୟାନ୍ୟ" + "ଅନ୍ୟ" "ମୋବାଇଲ୍‍" "କଷ୍ଟମ୍‌" "ହୋମ" "ୱାର୍କ" - "ଅନ୍ୟାନ୍ୟ" + "ଅନ୍ୟ" "କଷ୍ଟମ୍‌" "ହୋମ" "ୱାର୍କ" - "ଅନ୍ୟାନ୍ୟ" + "ଅନ୍ୟ" "କଷ୍ଟମ୍‌" "AIM" "Windows Live" @@ -884,7 +884,7 @@ "Jabber" "NetMeeting" "ୱାର୍କ" - "ଅନ୍ୟାନ୍ୟ" + "ଅନ୍ୟ" "କଷ୍ଟମ୍‌" "କଷ୍ଟମ୍‌" "Assistant" @@ -904,7 +904,7 @@ "କଷ୍ଟମ୍‌" "ହୋମ" "ୱାର୍କ" - "ଅନ୍ୟାନ୍ୟ" + "ଅନ୍ୟ" "ଏହି କଣ୍ଟାକ୍ଟ ଦେଖିବାକୁ କୌଣସି ଆପ୍ଲିକେସନ ମିଳିଲା ନାହିଁ।" "PIN କୋଡ୍‍ ଟାଇପ୍‍ କରନ୍ତୁ" "PUK ଓ ନୂଆ PIN କୋଡ୍‍ ଟାଇପ୍‍ କରନ୍ତୁ" diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml index c2fe6ddd103a6..318971dced42d 100644 --- a/core/res/res/values-ru/strings.xml +++ b/core/res/res/values-ru/strings.xml @@ -92,7 +92,7 @@ "Оповещения" "Переадресация вызовов" "Режим экстренных обратных вызовов" - "Состояние мобильного Интернета" + "Состояние мобильного интернета" "SMS" "Голосовые сообщения" "Звонки по Wi-Fi" From 02cae22700e19097c1dbbbb1814cf30a59b65cf7 Mon Sep 17 00:00:00 2001 From: Bill Yi Date: Wed, 30 Nov 2022 05:21:15 -0800 Subject: [PATCH 13/38] Import translations. DO NOT MERGE ANYWHERE Auto-generated-cl: translation import Change-Id: I4313374d195b9da4215ebd5b9b243409acbd7534 --- libs/WindowManager/Shell/res/values-af/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-as/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-az/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-be/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-bg/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-bn/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-bs/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-ca/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-cs/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-da/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-de/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-el/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-en-rAU/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-en-rCA/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-en-rGB/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-en-rIN/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-en-rXC/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-es-rUS/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-es/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-et/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-fa/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-fi/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-fr-rCA/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-fr/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-gl/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-hr/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-hu/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-hy/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-in/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-is/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-it/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-iw/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-ja/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-ka/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-kk/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-km/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-kn/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-ko/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-ky/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-lo/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-lt/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-lv/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-mk/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-mn/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-mr/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-ms/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-nb/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-nl/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-or/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-pa/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-pl/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-pt-rPT/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-ro/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-ru/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-si/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-sk/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-sl/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-sq/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-sr/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-sv/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-te/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-th/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-tl/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-tr/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-ur/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-uz/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-vi/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-zh-rCN/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-zh-rHK/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-zh-rTW/strings.xml | 3 +-- libs/WindowManager/Shell/res/values-zu/strings.xml | 3 +-- 72 files changed, 72 insertions(+), 144 deletions(-) diff --git a/libs/WindowManager/Shell/res/values-af/strings.xml b/libs/WindowManager/Shell/res/values-af/strings.xml index dfce50174bda7..3d50d2262bb8d 100644 --- a/libs/WindowManager/Shell/res/values-af/strings.xml +++ b/libs/WindowManager/Shell/res/values-af/strings.xml @@ -33,8 +33,7 @@ "Laat los" "Program sal dalk nie met verdeelde skerm werk nie." "Program steun nie verdeelde skerm nie." - - + "Hierdie app kan net in 1 venster oopgemaak word." "Program sal dalk nie op \'n sekondêre skerm werk nie." "Program steun nie begin op sekondêre skerms nie." "Skermverdeler" diff --git a/libs/WindowManager/Shell/res/values-as/strings.xml b/libs/WindowManager/Shell/res/values-as/strings.xml index 655e53f64254d..a0213f42b1253 100644 --- a/libs/WindowManager/Shell/res/values-as/strings.xml +++ b/libs/WindowManager/Shell/res/values-as/strings.xml @@ -33,8 +33,7 @@ "দেখুৱাওক" "এপ্‌টোৱে বিভাজিত স্ক্ৰীনৰ সৈতে কাম নকৰিব পাৰে।" "এপ্‌টোৱে বিভাজিত স্ক্ৰীন সমৰ্থন নকৰে।" - - + "এই এপ্‌টো কেৱল ১ খন ৱিণ্ড’ত খুলিব পাৰি।" "গৌণ ডিছপ্লেত এপে সঠিকভাৱে কাম নকৰিব পাৰে।" "গৌণ ডিছপ্লেত এপ্ লঞ্চ কৰিব নোৱাৰি।" "স্প্লিট স্ক্ৰীনৰ বিভাজক" diff --git a/libs/WindowManager/Shell/res/values-az/strings.xml b/libs/WindowManager/Shell/res/values-az/strings.xml index d3d20587cb68b..f842bfe13efc8 100644 --- a/libs/WindowManager/Shell/res/values-az/strings.xml +++ b/libs/WindowManager/Shell/res/values-az/strings.xml @@ -33,8 +33,7 @@ "Güvənli məkandan çıxarın" "Tətbiq bölünmüş ekran ilə işləməyə bilər." "Tətbiq ekran bölünməsini dəstəkləmir." - - + "Bu tətbiq yalnız 1 pəncərədə açıla bilər." "Tətbiq ikinci ekranda işləməyə bilər." "Tətbiq ikinci ekranda başlamağı dəstəkləmir." "Bölünmüş ekran ayırıcısı" diff --git a/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml b/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml index 839ecb60e395e..540ae7ce69539 100644 --- a/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml +++ b/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml @@ -33,8 +33,7 @@ "Uklonite iz tajne memorije" "Aplikacija možda neće raditi sa podeljenim ekranom." "Aplikacija ne podržava podeljeni ekran." - - + "Ova aplikacija može da se otvori samo u jednom prozoru." "Aplikacija možda neće funkcionisati na sekundarnom ekranu." "Aplikacija ne podržava pokretanje na sekundarnim ekranima." "Razdelnik podeljenog ekrana" diff --git a/libs/WindowManager/Shell/res/values-be/strings.xml b/libs/WindowManager/Shell/res/values-be/strings.xml index b227cf12a1b08..bea753837b7b4 100644 --- a/libs/WindowManager/Shell/res/values-be/strings.xml +++ b/libs/WindowManager/Shell/res/values-be/strings.xml @@ -33,8 +33,7 @@ "Паказаць" "Праграма можа не працаваць у рэжыме падзеленага экрана." "Праграма не падтрымлівае функцыю дзялення экрана." - - + "Гэту праграму можна адкрыць толькі ў адным акне." "Праграма можа не працаваць на дадатковых экранах." "Праграма не падтрымлівае запуск на дадатковых экранах." "Раздзяляльнік падзеленага экрана" diff --git a/libs/WindowManager/Shell/res/values-bg/strings.xml b/libs/WindowManager/Shell/res/values-bg/strings.xml index 20f40387665e9..59915e6b2a6e8 100644 --- a/libs/WindowManager/Shell/res/values-bg/strings.xml +++ b/libs/WindowManager/Shell/res/values-bg/strings.xml @@ -33,8 +33,7 @@ "Отмяна на съхраняването" "Приложението може да не работи в режим на разделен екран." "Приложението не поддържа разделен екран." - - + "Това приложение може да се отвори само в 1 прозорец." "Възможно е приложението да не работи на алтернативни дисплеи." "Приложението не поддържа използването на алтернативни дисплеи." "Разделител в режима за разделен екран" diff --git a/libs/WindowManager/Shell/res/values-bn/strings.xml b/libs/WindowManager/Shell/res/values-bn/strings.xml index 4add02eec96de..63c9684070b6a 100644 --- a/libs/WindowManager/Shell/res/values-bn/strings.xml +++ b/libs/WindowManager/Shell/res/values-bn/strings.xml @@ -33,8 +33,7 @@ "আনস্ট্যাস করুন" "অ্যাপটি স্প্লিট স্ক্রিনে কাজ নাও করতে পারে।" "অ্যাপ্লিকেশান বিভক্ত-স্ক্রিন সমর্থন করে না৷" - - + "এই অ্যাপটি শুধু ১টি উইন্ডোয় খোলা যেতে পারে।" "সেকেন্ডারি ডিসপ্লেতে অ্যাপটি কাজ নাও করতে পারে।" "সেকেন্ডারি ডিসপ্লেতে অ্যাপ লঞ্চ করা যাবে না।" "বিভক্ত-স্ক্রিন বিভাজক" diff --git a/libs/WindowManager/Shell/res/values-bs/strings.xml b/libs/WindowManager/Shell/res/values-bs/strings.xml index 1444b89e2504e..b725efea6e48e 100644 --- a/libs/WindowManager/Shell/res/values-bs/strings.xml +++ b/libs/WindowManager/Shell/res/values-bs/strings.xml @@ -33,8 +33,7 @@ "Vađenje iz stasha" "Aplikacija možda neće raditi na podijeljenom ekranu." "Aplikacija ne podržava dijeljenje ekrana." - - + "Ova aplikacija se može otvoriti samo u 1 prozoru." "Aplikacija možda neće raditi na sekundarnom ekranu." "Aplikacija ne podržava pokretanje na sekundarnim ekranima." "Razdjelnik podijeljenog ekrana" diff --git a/libs/WindowManager/Shell/res/values-ca/strings.xml b/libs/WindowManager/Shell/res/values-ca/strings.xml index a0bec428499ef..4383916f65976 100644 --- a/libs/WindowManager/Shell/res/values-ca/strings.xml +++ b/libs/WindowManager/Shell/res/values-ca/strings.xml @@ -33,8 +33,7 @@ "Deixa d\'amagar" "És possible que l\'aplicació no funcioni amb la pantalla dividida." "L\'aplicació no admet la pantalla dividida." - - + "Aquesta aplicació només pot obrir-se en 1 finestra." "És possible que l\'aplicació no funcioni en una pantalla secundària." "L\'aplicació no es pot obrir en pantalles secundàries." "Divisor de pantalles" diff --git a/libs/WindowManager/Shell/res/values-cs/strings.xml b/libs/WindowManager/Shell/res/values-cs/strings.xml index 332e9568b6d80..e5cb26f3e3b43 100644 --- a/libs/WindowManager/Shell/res/values-cs/strings.xml +++ b/libs/WindowManager/Shell/res/values-cs/strings.xml @@ -33,8 +33,7 @@ "Zrušit uložení" "Aplikace v režimu rozdělené obrazovky nemusí fungovat." "Aplikace nepodporuje režim rozdělené obrazovky." - - + "Tuto aplikaci lze otevřít jen na jednom okně." "Aplikace na sekundárním displeji nemusí fungovat." "Aplikace nepodporuje spuštění na sekundárních displejích." "Čára rozdělující obrazovku" diff --git a/libs/WindowManager/Shell/res/values-da/strings.xml b/libs/WindowManager/Shell/res/values-da/strings.xml index a7fb175b69f9f..46f7c6985ec2c 100644 --- a/libs/WindowManager/Shell/res/values-da/strings.xml +++ b/libs/WindowManager/Shell/res/values-da/strings.xml @@ -33,8 +33,7 @@ "Vis" "Appen fungerer muligvis ikke i opdelt skærm." "Appen understøtter ikke opdelt skærm." - - + "Denne app kan kun åbnes i 1 vindue." "Appen fungerer muligvis ikke på sekundære skærme." "Appen kan ikke åbnes på sekundære skærme." "Adskiller til opdelt skærm" diff --git a/libs/WindowManager/Shell/res/values-de/strings.xml b/libs/WindowManager/Shell/res/values-de/strings.xml index 8d69eb4c9daf7..1269d362903d4 100644 --- a/libs/WindowManager/Shell/res/values-de/strings.xml +++ b/libs/WindowManager/Shell/res/values-de/strings.xml @@ -33,8 +33,7 @@ "Aus Stash entfernen" "Die App funktioniert unter Umständen im Modus für geteilten Bildschirm nicht." "Das Teilen des Bildschirms wird in dieser App nicht unterstützt." - - + "Diese App kann nur in einem einzigen Fenster geöffnet werden." "Die App funktioniert auf einem sekundären Display möglicherweise nicht." "Die App unterstützt den Start auf sekundären Displays nicht." "Bildschirmteiler" diff --git a/libs/WindowManager/Shell/res/values-el/strings.xml b/libs/WindowManager/Shell/res/values-el/strings.xml index 613e5b075e0ff..f8a69ef796b9b 100644 --- a/libs/WindowManager/Shell/res/values-el/strings.xml +++ b/libs/WindowManager/Shell/res/values-el/strings.xml @@ -33,8 +33,7 @@ "Κατάργηση απόκρυψης" "Η εφαρμογή ενδέχεται να μην λειτουργεί με διαχωρισμό οθόνης." "Η εφαρμογή δεν υποστηρίζει διαχωρισμό οθόνης." - - + "Αυτή η εφαρμογή μπορεί να ανοιχθεί μόνο σε 1 παράθυρο." "Η εφαρμογή ίσως να μην λειτουργήσει σε δευτερεύουσα οθόνη." "Η εφαρμογή δεν υποστηρίζει την εκκίνηση σε δευτερεύουσες οθόνες." "Διαχωριστικό οθόνης" diff --git a/libs/WindowManager/Shell/res/values-en-rAU/strings.xml b/libs/WindowManager/Shell/res/values-en-rAU/strings.xml index 5619617c9f769..8e46c3e0999e0 100644 --- a/libs/WindowManager/Shell/res/values-en-rAU/strings.xml +++ b/libs/WindowManager/Shell/res/values-en-rAU/strings.xml @@ -33,8 +33,7 @@ "Unstash" "App may not work with split-screen." "App does not support split-screen." - - + "This app can only be opened in one window." "App may not work on a secondary display." "App does not support launch on secondary displays." "Split screen divider" diff --git a/libs/WindowManager/Shell/res/values-en-rCA/strings.xml b/libs/WindowManager/Shell/res/values-en-rCA/strings.xml index 9f156697f5c77..7cbbf64991cdf 100644 --- a/libs/WindowManager/Shell/res/values-en-rCA/strings.xml +++ b/libs/WindowManager/Shell/res/values-en-rCA/strings.xml @@ -33,8 +33,7 @@ "Unstash" "App may not work with split-screen." "App does not support split-screen." - - + "This app can only be opened in 1 window." "App may not work on a secondary display." "App does not support launch on secondary displays." "Split-screen divider" diff --git a/libs/WindowManager/Shell/res/values-en-rGB/strings.xml b/libs/WindowManager/Shell/res/values-en-rGB/strings.xml index 5619617c9f769..8e46c3e0999e0 100644 --- a/libs/WindowManager/Shell/res/values-en-rGB/strings.xml +++ b/libs/WindowManager/Shell/res/values-en-rGB/strings.xml @@ -33,8 +33,7 @@ "Unstash" "App may not work with split-screen." "App does not support split-screen." - - + "This app can only be opened in one window." "App may not work on a secondary display." "App does not support launch on secondary displays." "Split screen divider" diff --git a/libs/WindowManager/Shell/res/values-en-rIN/strings.xml b/libs/WindowManager/Shell/res/values-en-rIN/strings.xml index 5619617c9f769..8e46c3e0999e0 100644 --- a/libs/WindowManager/Shell/res/values-en-rIN/strings.xml +++ b/libs/WindowManager/Shell/res/values-en-rIN/strings.xml @@ -33,8 +33,7 @@ "Unstash" "App may not work with split-screen." "App does not support split-screen." - - + "This app can only be opened in one window." "App may not work on a secondary display." "App does not support launch on secondary displays." "Split screen divider" diff --git a/libs/WindowManager/Shell/res/values-en-rXC/strings.xml b/libs/WindowManager/Shell/res/values-en-rXC/strings.xml index 2b474db99f601..b2720be3d8a03 100644 --- a/libs/WindowManager/Shell/res/values-en-rXC/strings.xml +++ b/libs/WindowManager/Shell/res/values-en-rXC/strings.xml @@ -33,8 +33,7 @@ "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‏‏‏‎‏‎‎‎‎‏‏‏‏‎‎‎‏‏‎‎‎‏‎‏‎‏‏‎‏‏‏‎‎‏‏‏‏‏‎‎‎‏‏‎‏‏‏‎‎‎‎‎‎‎‏‏‏‎‎Unstash‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‎‎‏‎‎‏‎‎‎‎‏‎‏‏‏‎‎‏‏‎‎‎‎‎‎‎‏‎‎‎‏‎‎‏‏‎‏‏‏‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‏‎‎‎App may not work with split-screen.‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‏‎‏‏‎‎‏‏‏‏‏‏‏‎‏‎‎‏‎‏‎‎‏‎‏‎‎‏‏‏‎‎‏‎‏‎‏‏‎‎‏‏‎‎‏‎‎‎‎‎‏‏‎‏‏‏‎‏‎App does not support split-screen.‎‏‎‎‏‎" - - + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‎‏‏‎‎‎‎‏‎‎‏‏‎‏‎‎‏‎‎‎‏‏‎‎‎‏‎‎‏‏‏‏‎‎‎‏‎‏‎‎‏‏‏‎‎‎‎‎‏‏‎‏‏‎‎‎‏‎This app can only be opened in 1 window.‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‎‏‎‎‎‏‎‎‏‎‏‎‏‏‏‎‏‎‏‎‏‎‎‏‎‏‎‏‏‏‏‎‏‏‏‎‏‏‎‏‏‎‎‎‏‎‎‏‎‎‏‎‎‏‏‏‏‎App may not work on a secondary display.‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‏‎‏‎‏‎‎‏‏‏‎‏‏‏‏‏‏‎‎‎‎‎‎‏‏‏‎‏‎‎‎‏‎‎‎‏‏‎‏‎‎‎‏‎‎‎‎‏‏‏‎‏‎‏‏‎‎‏‎App does not support launch on secondary displays.‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‎‏‏‏‎‎‎‏‎‎‎‏‏‎‏‏‏‏‏‎‎‎‎‏‎‏‏‎‏‎‏‎‎‏‎‎‏‎‎‏‎‏‏‎‏‎‏‏‏‏‏‎‎‏‎‏‏‏‎Split-screen divider‎‏‎‎‏‎" diff --git a/libs/WindowManager/Shell/res/values-es-rUS/strings.xml b/libs/WindowManager/Shell/res/values-es-rUS/strings.xml index 67386c4f31eae..47445a7a04881 100644 --- a/libs/WindowManager/Shell/res/values-es-rUS/strings.xml +++ b/libs/WindowManager/Shell/res/values-es-rUS/strings.xml @@ -33,8 +33,7 @@ "Dejar de almacenar de manera segura" "Es posible que la app no funcione en el modo de pantalla dividida." "La app no es compatible con la función de pantalla dividida." - - + "Esta app solo puede estar abierta en 1 ventana." "Es posible que la app no funcione en una pantalla secundaria." "La app no puede iniciarse en pantallas secundarias." "Divisor de pantalla dividida" diff --git a/libs/WindowManager/Shell/res/values-es/strings.xml b/libs/WindowManager/Shell/res/values-es/strings.xml index d4a6b6ce7347e..6c45231c32615 100644 --- a/libs/WindowManager/Shell/res/values-es/strings.xml +++ b/libs/WindowManager/Shell/res/values-es/strings.xml @@ -33,8 +33,7 @@ "No esconder" "Es posible que la aplicación no funcione con la pantalla dividida." "La aplicación no admite la pantalla dividida." - - + "Esta aplicación solo puede abrirse en una ventana." "Es posible que la aplicación no funcione en una pantalla secundaria." "La aplicación no se puede abrir en pantallas secundarias." "Dividir la pantalla" diff --git a/libs/WindowManager/Shell/res/values-et/strings.xml b/libs/WindowManager/Shell/res/values-et/strings.xml index df84e7c923de5..a8dc08cbbd270 100644 --- a/libs/WindowManager/Shell/res/values-et/strings.xml +++ b/libs/WindowManager/Shell/res/values-et/strings.xml @@ -33,8 +33,7 @@ "Eemalda hoidlast" "Rakendus ei pruugi poolitatud ekraaniga töötada." "Rakendus ei toeta jagatud ekraani." - - + "Selle rakenduse saab avada ainult ühes aknas." "Rakendus ei pruugi teisesel ekraanil töötada." "Rakendus ei toeta teisestel ekraanidel käivitamist." "Ekraanijagaja" diff --git a/libs/WindowManager/Shell/res/values-fa/strings.xml b/libs/WindowManager/Shell/res/values-fa/strings.xml index c062b928c2eca..e7cb5f41a3ace 100644 --- a/libs/WindowManager/Shell/res/values-fa/strings.xml +++ b/libs/WindowManager/Shell/res/values-fa/strings.xml @@ -33,8 +33,7 @@ "لغو مخفی‌سازی" "ممکن است برنامه با «صفحهٔ دونیمه» کار نکند." "برنامه از تقسیم صفحه پشتیبانی نمی‌کند." - - + "این برنامه فقط در ۱ پنجره می‌تواند باز شود." "ممکن است برنامه در نمایشگر ثانویه کار نکند." "برنامه از راه‌اندازی در نمایشگرهای ثانویه پشتیبانی نمی‌کند." "تقسیم‌کننده صفحه" diff --git a/libs/WindowManager/Shell/res/values-fi/strings.xml b/libs/WindowManager/Shell/res/values-fi/strings.xml index 6efb770d27277..86199f3cf0927 100644 --- a/libs/WindowManager/Shell/res/values-fi/strings.xml +++ b/libs/WindowManager/Shell/res/values-fi/strings.xml @@ -33,8 +33,7 @@ "Poista turvasäilytyksestä" "Sovellus ei ehkä toimi jaetulla näytöllä." "Sovellus ei tue jaetun näytön tilaa." - - + "Tämän sovelluksen voi avata vain yhdessä ikkunassa." "Sovellus ei ehkä toimi toissijaisella näytöllä." "Sovellus ei tue käynnistämistä toissijaisilla näytöillä." "Näytön jakaja" diff --git a/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml b/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml index 0c2e1b1298ca0..1f3ac9ecbcca3 100644 --- a/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml +++ b/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml @@ -33,8 +33,7 @@ "Retirer de la réserve" "Il est possible que l\'application ne fonctionne pas en mode Écran partagé." "L\'application n\'est pas compatible avec l\'écran partagé." - - + "Cette application ne peut être ouverte que dans une fenêtre." "Il est possible que l\'application ne fonctionne pas sur un écran secondaire." "L\'application ne peut pas être lancée sur des écrans secondaires." "Séparateur d\'écran partagé" diff --git a/libs/WindowManager/Shell/res/values-fr/strings.xml b/libs/WindowManager/Shell/res/values-fr/strings.xml index b7147180126f2..f1dbb35dc7a79 100644 --- a/libs/WindowManager/Shell/res/values-fr/strings.xml +++ b/libs/WindowManager/Shell/res/values-fr/strings.xml @@ -33,8 +33,7 @@ "Unstash" "Il est possible que l\'application ne fonctionne pas en mode Écran partagé." "Application incompatible avec l\'écran partagé." - - + "Cette appli ne peut être ouverte que dans 1 fenêtre." "Il est possible que l\'application ne fonctionne pas sur un écran secondaire." "L\'application ne peut pas être lancée sur des écrans secondaires." "Séparateur d\'écran partagé" diff --git a/libs/WindowManager/Shell/res/values-gl/strings.xml b/libs/WindowManager/Shell/res/values-gl/strings.xml index 952d5329bcd08..6e215a1f5b810 100644 --- a/libs/WindowManager/Shell/res/values-gl/strings.xml +++ b/libs/WindowManager/Shell/res/values-gl/strings.xml @@ -33,8 +33,7 @@ "Non esconder" "Pode que a aplicación non funcione coa pantalla dividida." "A aplicación non é compatible coa función de pantalla dividida." - - + "Esta aplicación só se pode abrir en 1 ventá." "É posible que a aplicación non funcione nunha pantalla secundaria." "A aplicación non se pode iniciar en pantallas secundarias." "Divisor de pantalla dividida" diff --git a/libs/WindowManager/Shell/res/values-hr/strings.xml b/libs/WindowManager/Shell/res/values-hr/strings.xml index 67488f9944687..1446e70ecdfad 100644 --- a/libs/WindowManager/Shell/res/values-hr/strings.xml +++ b/libs/WindowManager/Shell/res/values-hr/strings.xml @@ -33,8 +33,7 @@ "Poništite sakrivanje" "Aplikacija možda neće funkcionirati s podijeljenim zaslonom." "Aplikacija ne podržava podijeljeni zaslon." - - + "Ova se aplikacija može otvoriti samo u jednom prozoru." "Aplikacija možda neće funkcionirati na sekundarnom zaslonu." "Aplikacija ne podržava pokretanje na sekundarnim zaslonima." "Razdjelnik podijeljenog zaslona" diff --git a/libs/WindowManager/Shell/res/values-hu/strings.xml b/libs/WindowManager/Shell/res/values-hu/strings.xml index 41d2d3176994b..221c329020a02 100644 --- a/libs/WindowManager/Shell/res/values-hu/strings.xml +++ b/libs/WindowManager/Shell/res/values-hu/strings.xml @@ -33,8 +33,7 @@ "Félretevés megszüntetése" "Lehet, hogy az alkalmazás nem működik osztott képernyős nézetben." "Az alkalmazás nem támogatja az osztott képernyős nézetet." - - + "Ez az alkalmazás csak egy ablakban nyitható meg." "Előfordulhat, hogy az alkalmazás nem működik másodlagos kijelzőn." "Az alkalmazást nem lehet másodlagos kijelzőn elindítani." "Elválasztó az osztott nézetben" diff --git a/libs/WindowManager/Shell/res/values-hy/strings.xml b/libs/WindowManager/Shell/res/values-hy/strings.xml index 502bfb15c9320..7be9941d2a5e7 100644 --- a/libs/WindowManager/Shell/res/values-hy/strings.xml +++ b/libs/WindowManager/Shell/res/values-hy/strings.xml @@ -33,8 +33,7 @@ "Ցուցադրել" "Հավելվածը չի կարող աշխատել տրոհված էկրանի ռեժիմում։" "Հավելվածը չի աջակցում էկրանի տրոհումը:" - - + "Այս հավելվածը հնարավոր է բացել միայն մեկ պատուհանում։" "Հավելվածը կարող է չաշխատել լրացուցիչ էկրանի վրա" "Հավելվածը չի աջակցում գործարկումը լրացուցիչ էկրանների վրա" "Տրոհված էկրանի բաժանիչ" diff --git a/libs/WindowManager/Shell/res/values-in/strings.xml b/libs/WindowManager/Shell/res/values-in/strings.xml index 561df7269bcf0..4e760ef6450c3 100644 --- a/libs/WindowManager/Shell/res/values-in/strings.xml +++ b/libs/WindowManager/Shell/res/values-in/strings.xml @@ -33,8 +33,7 @@ "Batalkan stash" "Aplikasi mungkin tidak berfungsi dengan layar terpisah." "App tidak mendukung layar terpisah." - - + "Aplikasi ini hanya dapat dibuka di 1 jendela." "Aplikasi mungkin tidak berfungsi pada layar sekunder." "Aplikasi tidak mendukung peluncuran pada layar sekunder." "Pembagi layar terpisah" diff --git a/libs/WindowManager/Shell/res/values-is/strings.xml b/libs/WindowManager/Shell/res/values-is/strings.xml index 355968bfb6eb5..50d4ee7faed68 100644 --- a/libs/WindowManager/Shell/res/values-is/strings.xml +++ b/libs/WindowManager/Shell/res/values-is/strings.xml @@ -33,8 +33,7 @@ "Taka úr geymslu" "Hugsanlega virkar forritið ekki með skjáskiptingu." "Forritið styður ekki að skjánum sé skipt." - - + "Aðeins er hægt að opna þetta forrit í 1 glugga." "Hugsanlegt er að forritið virki ekki á öðrum skjá." "Forrit styður ekki opnun á öðrum skjá." "Skjáskipting" diff --git a/libs/WindowManager/Shell/res/values-it/strings.xml b/libs/WindowManager/Shell/res/values-it/strings.xml index 1417d00216581..d2595f7682d2b 100644 --- a/libs/WindowManager/Shell/res/values-it/strings.xml +++ b/libs/WindowManager/Shell/res/values-it/strings.xml @@ -33,8 +33,7 @@ "Annulla accantonamento" "L\'app potrebbe non funzionare con lo schermo diviso." "L\'app non supporta la modalità Schermo diviso." - - + "Questa app può essere aperta soltanto in 1 finestra." "L\'app potrebbe non funzionare su un display secondario." "L\'app non supporta l\'avvio su display secondari." "Strumento per schermo diviso" diff --git a/libs/WindowManager/Shell/res/values-iw/strings.xml b/libs/WindowManager/Shell/res/values-iw/strings.xml index b3c0b655ccb13..883596ebcd6fd 100644 --- a/libs/WindowManager/Shell/res/values-iw/strings.xml +++ b/libs/WindowManager/Shell/res/values-iw/strings.xml @@ -33,8 +33,7 @@ "ביטול ההסתרה הזמנית" "ייתכן שהאפליקציה לא תפעל במסך מפוצל." "האפליקציה אינה תומכת במסך מפוצל." - - + "ניתן לפתוח את האפליקציה הזו רק בחלון אחד." "ייתכן שהאפליקציה לא תפעל במסך משני." "האפליקציה אינה תומכת בהפעלה במסכים משניים." "מחלק מסך מפוצל" diff --git a/libs/WindowManager/Shell/res/values-ja/strings.xml b/libs/WindowManager/Shell/res/values-ja/strings.xml index a5b0f21882f7a..6bb22a29e79be 100644 --- a/libs/WindowManager/Shell/res/values-ja/strings.xml +++ b/libs/WindowManager/Shell/res/values-ja/strings.xml @@ -33,8 +33,7 @@ "表示" "アプリは分割画面では動作しないことがあります。" "アプリで分割画面がサポートされていません。" - - + "このアプリはウィンドウが 1 つの場合のみ開くことができます。" "アプリはセカンダリ ディスプレイでは動作しないことがあります。" "アプリはセカンダリ ディスプレイでの起動に対応していません。" "分割画面の分割線" diff --git a/libs/WindowManager/Shell/res/values-ka/strings.xml b/libs/WindowManager/Shell/res/values-ka/strings.xml index a85efb4333607..6cf7d7827ee93 100644 --- a/libs/WindowManager/Shell/res/values-ka/strings.xml +++ b/libs/WindowManager/Shell/res/values-ka/strings.xml @@ -33,8 +33,7 @@ "გადანახვის გაუქმება" "აპმა შეიძლება არ იმუშაოს გაყოფილი ეკრანის რეჟიმში." "ეკრანის გაყოფა არ არის მხარდაჭერილი აპის მიერ." - - + "ამ აპის გახსნა შესაძლებელია მხოლოდ 1 ფანჯარაში." "აპმა შეიძლება არ იმუშაოს მეორეულ ეკრანზე." "აპს არ გააჩნია მეორეული ეკრანის მხარდაჭერა." "გაყოფილი ეკრანის რეჟიმის გამყოფი" diff --git a/libs/WindowManager/Shell/res/values-kk/strings.xml b/libs/WindowManager/Shell/res/values-kk/strings.xml index 9c0c15cd66657..216619a232fc1 100644 --- a/libs/WindowManager/Shell/res/values-kk/strings.xml +++ b/libs/WindowManager/Shell/res/values-kk/strings.xml @@ -33,8 +33,7 @@ "Көрсету" "Қолданба экранды бөлу режимінде жұмыс істемеуі мүмкін." "Қодланба бөлінген экранды қолдамайды." - - + "Бұл қолданбаны тек 1 терезеден ашуға болады." "Қолданба қосымша дисплейде жұмыс істемеуі мүмкін." "Қолданба қосымша дисплейлерде іске қосуды қолдамайды." "Бөлінген экран бөлгіші" diff --git a/libs/WindowManager/Shell/res/values-km/strings.xml b/libs/WindowManager/Shell/res/values-km/strings.xml index d56d6a5c5a78e..79aca620f3486 100644 --- a/libs/WindowManager/Shell/res/values-km/strings.xml +++ b/libs/WindowManager/Shell/res/values-km/strings.xml @@ -33,8 +33,7 @@ "ឈប់លាក់ជាបណ្ដោះអាសន្ន" "កម្មវិធី​អាចនឹងមិន​ដំណើរការ​ជាមួយ​មុខងារបំបែកអេក្រង់​ទេ។" "កម្មវិធីមិនគាំទ្រអេក្រង់បំបែកជាពីរទេ" - - + "កម្មវិធីនេះអាចបើកនៅក្នុងវិនដូតែ 1 ប៉ុណ្ណោះ។" "កម្មវិធីនេះ​ប្រហែល​ជាមិនដំណើរការ​នៅលើ​អេក្រង់បន្ទាប់បន្សំទេ។" "កម្មវិធី​នេះមិន​អាច​ចាប់ផ្តើម​នៅលើ​អេក្រង់បន្ទាប់បន្សំបានទេ។" "កម្មវិធីចែកអេក្រង់បំបែក" diff --git a/libs/WindowManager/Shell/res/values-kn/strings.xml b/libs/WindowManager/Shell/res/values-kn/strings.xml index 1b31a6f883bbe..9e9333ea422c4 100644 --- a/libs/WindowManager/Shell/res/values-kn/strings.xml +++ b/libs/WindowManager/Shell/res/values-kn/strings.xml @@ -33,8 +33,7 @@ "ಅನ್‌ಸ್ಟ್ಯಾಶ್ ಮಾಡಿ" "ವಿಭಜಿಸಿದ ಸ್ಕ್ರೀನ್‌ನಲ್ಲಿ ಆ್ಯಪ್ ಕೆಲಸ ಮಾಡದೇ ಇರಬಹುದು." "ಅಪ್ಲಿಕೇಶನ್ ಸ್ಪ್ಲಿಟ್ ಸ್ಕ್ರೀನ್ ಅನ್ನು ಬೆಂಬಲಿಸುವುದಿಲ್ಲ." - - + "ಈ ಆ್ಯಪ್ ಅನ್ನು 1 ವಿಂಡೋದಲ್ಲಿ ಮಾತ್ರ ತೆರೆಯಬಹುದು." "ಸೆಕೆಂಡರಿ ಡಿಸ್‌ಪ್ಲೇಗಳಲ್ಲಿ ಅಪ್ಲಿಕೇಶನ್‌ ಕಾರ್ಯ ನಿರ್ವಹಿಸದೇ ಇರಬಹುದು." "ಸೆಕೆಂಡರಿ ಡಿಸ್‌ಪ್ಲೇಗಳಲ್ಲಿ ಪ್ರಾರಂಭಿಸುವಿಕೆಯನ್ನು ಅಪ್ಲಿಕೇಶನ್ ಬೆಂಬಲಿಸುವುದಿಲ್ಲ." "ಸ್ಪ್ಲಿಟ್-ಪರದೆ ಡಿವೈಡರ್" diff --git a/libs/WindowManager/Shell/res/values-ko/strings.xml b/libs/WindowManager/Shell/res/values-ko/strings.xml index 563db5b7e7c24..f9b495a38f4fd 100644 --- a/libs/WindowManager/Shell/res/values-ko/strings.xml +++ b/libs/WindowManager/Shell/res/values-ko/strings.xml @@ -33,8 +33,7 @@ "숨기기 취소" "앱이 분할 화면에서 작동하지 않을 수 있습니다." "앱이 화면 분할을 지원하지 않습니다." - - + "이 앱은 창 1개에서만 열 수 있습니다." "앱이 보조 디스플레이에서 작동하지 않을 수도 있습니다." "앱이 보조 디스플레이에서의 실행을 지원하지 않습니다." "화면 분할기" diff --git a/libs/WindowManager/Shell/res/values-ky/strings.xml b/libs/WindowManager/Shell/res/values-ky/strings.xml index 0497d15671edb..a57f9ae9689f0 100644 --- a/libs/WindowManager/Shell/res/values-ky/strings.xml +++ b/libs/WindowManager/Shell/res/values-ky/strings.xml @@ -33,8 +33,7 @@ "Сейфтен чыгаруу" "Колдонмодо экран бөлүнбөшү мүмкүн." "Колдонмодо экран бөлүнбөйт." - - + "Бул колдонмону 1 терезеде гана ачууга болот." "Колдонмо кошумча экранда иштебей коюшу мүмкүн." "Колдонмону кошумча экрандарда иштетүүгө болбойт." "Экранды бөлгүч" diff --git a/libs/WindowManager/Shell/res/values-lo/strings.xml b/libs/WindowManager/Shell/res/values-lo/strings.xml index 35aecaaada6c1..8e42aa346669b 100644 --- a/libs/WindowManager/Shell/res/values-lo/strings.xml +++ b/libs/WindowManager/Shell/res/values-lo/strings.xml @@ -33,8 +33,7 @@ "ເອົາອອກຈາກບ່ອນເກັບສ່ວນຕົວ" "ແອັບອາດໃຊ້ບໍ່ໄດ້ກັບການແບ່ງໜ້າຈໍ." "ແອັບບໍ່ຮອງຮັບໜ້າຈໍແບບແຍກກັນ." - - + "ແອັບນີ້ສາມາດເປີດໄດ້ໃນ 1 ໜ້າຈໍເທົ່ານັ້ນ." "ແອັບອາດບໍ່ສາມາດໃຊ້ໄດ້ໃນໜ້າຈໍທີສອງ." "ແອັບບໍ່ຮອງຮັບການເປີດໃນໜ້າຈໍທີສອງ." "ຕົວຂັ້ນການແບ່ງໜ້າຈໍ" diff --git a/libs/WindowManager/Shell/res/values-lt/strings.xml b/libs/WindowManager/Shell/res/values-lt/strings.xml index f4ed192f2fa8c..dc9969095cf53 100644 --- a/libs/WindowManager/Shell/res/values-lt/strings.xml +++ b/libs/WindowManager/Shell/res/values-lt/strings.xml @@ -33,8 +33,7 @@ "Nebeslėpti" "Programa gali neveikti naudojant išskaidyto ekrano režimą." "Programoje nepalaikomas skaidytas ekranas." - - + "Šią programą galima atidaryti tik viename lange." "Programa gali neveikti antriniame ekrane." "Programa nepalaiko paleisties antriniuose ekranuose." "Skaidyto ekrano daliklis" diff --git a/libs/WindowManager/Shell/res/values-lv/strings.xml b/libs/WindowManager/Shell/res/values-lv/strings.xml index ffb9ddb9f4b03..bd2eef42690b5 100644 --- a/libs/WindowManager/Shell/res/values-lv/strings.xml +++ b/libs/WindowManager/Shell/res/values-lv/strings.xml @@ -33,8 +33,7 @@ "Rādīt" "Iespējams, lietotne nedarbosies ekrāna sadalīšanas režīmā." "Lietotnē netiek atbalstīta ekrāna sadalīšana." - - + "Šo lietotni var atvērt tikai vienā logā." "Lietotne, iespējams, nedarbosies sekundārajā displejā." "Lietotnē netiek atbalstīta palaišana sekundārajos displejos." "Ekrāna sadalītājs" diff --git a/libs/WindowManager/Shell/res/values-mk/strings.xml b/libs/WindowManager/Shell/res/values-mk/strings.xml index cf6b9d5bf6276..d133654ba7778 100644 --- a/libs/WindowManager/Shell/res/values-mk/strings.xml +++ b/libs/WindowManager/Shell/res/values-mk/strings.xml @@ -33,8 +33,7 @@ "Прикажете" "Апликацијата може да не работи со поделен екран." "Апликацијата не поддржува поделен екран." - - + "Апликацијава може да се отвори само во еден прозорец." "Апликацијата може да не функционира на друг екран." "Апликацијата не поддржува стартување на други екрани." "Разделник на поделен екран" diff --git a/libs/WindowManager/Shell/res/values-mn/strings.xml b/libs/WindowManager/Shell/res/values-mn/strings.xml index 54513d1866ee7..264f9a0a4db9c 100644 --- a/libs/WindowManager/Shell/res/values-mn/strings.xml +++ b/libs/WindowManager/Shell/res/values-mn/strings.xml @@ -33,8 +33,7 @@ "Ил гаргах" "Апп хуваагдсан дэлгэц дээр ажиллахгүй байж болзошгүй." "Энэ апп нь дэлгэц хуваах тохиргоог дэмждэггүй." - - + "Энэ аппыг зөвхөн 1 цонхонд нээх боломжтой." "Апп хоёрдогч дэлгэцэд ажиллахгүй." "Аппыг хоёрдогч дэлгэцэд эхлүүлэх боломжгүй." "\"Дэлгэц хуваах\" хуваагч" diff --git a/libs/WindowManager/Shell/res/values-mr/strings.xml b/libs/WindowManager/Shell/res/values-mr/strings.xml index 2833480289796..7a475edcd964c 100644 --- a/libs/WindowManager/Shell/res/values-mr/strings.xml +++ b/libs/WindowManager/Shell/res/values-mr/strings.xml @@ -33,8 +33,7 @@ "अनस्टॅश करा" "अ‍ॅप कदाचित स्प्लिट स्क्रीनसह काम करू शकत नाही." "अ‍ॅप स्क्रीन-विभाजनास समर्थन देत नाही." - - + "हे अ‍ॅप फक्त एका विंडोमध्ये उघडले जाऊ शकते." "दुसऱ्या डिस्प्लेवर अ‍ॅप कदाचित चालणार नाही." "दुसऱ्या डिस्प्लेवर अ‍ॅप लाँच होणार नाही." "विभाजित-स्क्रीन विभाजक" diff --git a/libs/WindowManager/Shell/res/values-ms/strings.xml b/libs/WindowManager/Shell/res/values-ms/strings.xml index 20f8ff69ebc17..be1dc24ccfcb7 100644 --- a/libs/WindowManager/Shell/res/values-ms/strings.xml +++ b/libs/WindowManager/Shell/res/values-ms/strings.xml @@ -33,8 +33,7 @@ "Tunjukkan" "Apl mungkin tidak berfungsi dengan skrin pisah." "Apl tidak menyokong skrin pisah." - - + "Apl ini hanya boleh dibuka dalam 1 tetingkap." "Apl mungkin tidak berfungsi pada paparan kedua." "Apl tidak menyokong pelancaran pada paparan kedua." "Pembahagi skrin pisah" diff --git a/libs/WindowManager/Shell/res/values-nb/strings.xml b/libs/WindowManager/Shell/res/values-nb/strings.xml index dd2750b339a20..3e18b4968464c 100644 --- a/libs/WindowManager/Shell/res/values-nb/strings.xml +++ b/libs/WindowManager/Shell/res/values-nb/strings.xml @@ -33,8 +33,7 @@ "Avslutt oppbevaring" "Det kan hende at appen ikke fungerer med delt skjerm." "Appen støtter ikke delt skjerm." - - + "Denne appen kan bare åpnes i ett vindu." "Appen fungerer kanskje ikke på en sekundær skjerm." "Appen kan ikke kjøres på sekundære skjermer." "Skilleelement for delt skjerm" diff --git a/libs/WindowManager/Shell/res/values-nl/strings.xml b/libs/WindowManager/Shell/res/values-nl/strings.xml index 054f05f4bb8d9..b056483e3b2df 100644 --- a/libs/WindowManager/Shell/res/values-nl/strings.xml +++ b/libs/WindowManager/Shell/res/values-nl/strings.xml @@ -33,8 +33,7 @@ "Niet meer verbergen" "De app werkt mogelijk niet met gesplitst scherm." "App biedt geen ondersteuning voor gesplitst scherm." - - + "Deze app kan slechts in 1 venster worden geopend." "App werkt mogelijk niet op een secundair scherm." "App kan niet op secundaire displays worden gestart." "Scheiding voor gesplitst scherm" diff --git a/libs/WindowManager/Shell/res/values-or/strings.xml b/libs/WindowManager/Shell/res/values-or/strings.xml index d0971a35e622f..5fd81f44bf0de 100644 --- a/libs/WindowManager/Shell/res/values-or/strings.xml +++ b/libs/WindowManager/Shell/res/values-or/strings.xml @@ -33,8 +33,7 @@ "ଦେଖାନ୍ତୁ" "ସ୍ପ୍ଲିଟ୍-ସ୍କ୍ରିନରେ ଆପ୍ କାମ କରିନପାରେ।" "ଆପ୍‍ ସ୍ପ୍ଲିଟ୍‍-ସ୍କ୍ରୀନକୁ ସପୋର୍ଟ କରେ ନାହିଁ।" - - + "ଏହି ଆପକୁ କେବଳ 1ଟି ୱିଣ୍ଡୋରେ ଖୋଲାଯାଇପାରିବ।" "ସେକେଣ୍ଡାରୀ ଡିସପ୍ଲେରେ ଆପ୍‍ କାମ ନକରିପାରେ।" "ସେକେଣ୍ଡାରୀ ଡିସପ୍ଲେରେ ଆପ୍‍ ଲଞ୍ଚ ସପୋର୍ଟ କରେ ନାହିଁ।" "ସ୍ପ୍ଲିଟ୍‍-ସ୍କ୍ରୀନ ବିଭାଜକ" diff --git a/libs/WindowManager/Shell/res/values-pa/strings.xml b/libs/WindowManager/Shell/res/values-pa/strings.xml index 989f8fce4f505..ada79d195df2f 100644 --- a/libs/WindowManager/Shell/res/values-pa/strings.xml +++ b/libs/WindowManager/Shell/res/values-pa/strings.xml @@ -33,8 +33,7 @@ "ਅਣਸਟੈਸ਼" "ਹੋ ਸਕਦਾ ਹੈ ਕਿ ਐਪ ਸਪਲਿਟ-ਸਕ੍ਰੀਨ ਨਾਲ ਕੰਮ ਨਾ ਕਰੇ।" "ਐਪ ਸਪਲਿਟ-ਸਕ੍ਰੀਨ ਨੂੰ ਸਮਰਥਨ ਨਹੀਂ ਕਰਦੀ।" - - + "ਇਹ ਐਪ ਸਿਰਫ਼ 1 ਵਿੰਡੋ ਵਿੱਚ ਖੋਲ੍ਹੀ ਜਾ ਸਕਦੀ ਹੈ।" "ਹੋ ਸਕਦਾ ਹੈ ਕਿ ਐਪ ਸੈਕੰਡਰੀ ਡਿਸਪਲੇ \'ਤੇ ਕੰਮ ਨਾ ਕਰੇ।" "ਐਪ ਸੈਕੰਡਰੀ ਡਿਸਪਲੇਆਂ \'ਤੇ ਲਾਂਚ ਕਰਨ ਦਾ ਸਮਰਥਨ ਨਹੀਂ ਕਰਦੀ" "ਸਪਲਿਟ-ਸਕ੍ਰੀਨ ਡਿਵਾਈਡਰ" diff --git a/libs/WindowManager/Shell/res/values-pl/strings.xml b/libs/WindowManager/Shell/res/values-pl/strings.xml index 3458f261dfdd8..a97fd5c9ddb0c 100644 --- a/libs/WindowManager/Shell/res/values-pl/strings.xml +++ b/libs/WindowManager/Shell/res/values-pl/strings.xml @@ -33,8 +33,7 @@ "Zabierz ze schowka" "Aplikacja może nie działać przy podzielonym ekranie." "Aplikacja nie obsługuje dzielonego ekranu." - - + "Ta aplikacja może być otwarta tylko w 1 oknie." "Aplikacja może nie działać na dodatkowym ekranie." "Aplikacja nie obsługuje uruchamiania na dodatkowych ekranach." "Linia dzielenia ekranu" diff --git a/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml b/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml index aeb7f9a296b30..e0636d42d980a 100644 --- a/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml +++ b/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml @@ -33,8 +33,7 @@ "Remover do armazenamento" "A app pode não funcionar com o ecrã dividido." "A app não é compatível com o ecrã dividido." - - + "Esta app só pode ser aberta em 1 janela." "A app pode não funcionar num ecrã secundário." "A app não é compatível com o início em ecrãs secundários." "Divisor do ecrã dividido" diff --git a/libs/WindowManager/Shell/res/values-ro/strings.xml b/libs/WindowManager/Shell/res/values-ro/strings.xml index 23b2099404901..9227216ffc1fd 100644 --- a/libs/WindowManager/Shell/res/values-ro/strings.xml +++ b/libs/WindowManager/Shell/res/values-ro/strings.xml @@ -33,8 +33,7 @@ "Anulează stocarea" "Este posibil ca aplicația să nu funcționeze cu ecranul împărțit." "Aplicația nu acceptă ecranul împărțit." - - + "Aplicația poate fi deschisă într-o singură fereastră." "Este posibil ca aplicația să nu funcționeze pe un ecran secundar." "Aplicația nu acceptă lansare pe ecrane secundare." "Separator pentru ecranul împărțit" diff --git a/libs/WindowManager/Shell/res/values-ru/strings.xml b/libs/WindowManager/Shell/res/values-ru/strings.xml index c1dfb19162fe9..f5fa1a4758863 100644 --- a/libs/WindowManager/Shell/res/values-ru/strings.xml +++ b/libs/WindowManager/Shell/res/values-ru/strings.xml @@ -33,8 +33,7 @@ "Показать" "В режиме разделения экрана приложение может работать нестабильно." "Приложение не поддерживает разделение экрана." - - + "Это приложение можно открыть только в одном окне." "Приложение может не работать на дополнительном экране" "Приложение не поддерживает запуск на дополнительных экранах" "Разделитель экрана" diff --git a/libs/WindowManager/Shell/res/values-si/strings.xml b/libs/WindowManager/Shell/res/values-si/strings.xml index 5e51003e44296..53e52f28adcf0 100644 --- a/libs/WindowManager/Shell/res/values-si/strings.xml +++ b/libs/WindowManager/Shell/res/values-si/strings.xml @@ -33,8 +33,7 @@ "සඟවා තැබීම ඉවත් කරන්න" "යෙදුම බෙදුම් තිරය සමග ක්‍රියා නොකළ හැකිය" "යෙදුම බෙදුණු-තිරය සඳහා සහාය නොදක්වයි." - - + "මෙම යෙදුම විවෘත කළ හැක්කේ 1 කවුළුවක පමණයි." "යෙදුම ද්විතියික සංදර්ශකයක ක්‍රියා නොකළ හැකිය." "යෙදුම ද්විතීයික සංදර්ශක මත දියත් කිරීම සඳහා සහාය නොදක්වයි." "බෙදුම්-තිර වෙන්කරණය" diff --git a/libs/WindowManager/Shell/res/values-sk/strings.xml b/libs/WindowManager/Shell/res/values-sk/strings.xml index baf03241dcc6f..f004fd472adfc 100644 --- a/libs/WindowManager/Shell/res/values-sk/strings.xml +++ b/libs/WindowManager/Shell/res/values-sk/strings.xml @@ -33,8 +33,7 @@ "Zrušiť skrytie" "Aplikácia nemusí fungovať s rozdelenou obrazovkou." "Aplikácia nepodporuje rozdelenú obrazovku." - - + "Táto aplikácia môže byť otvorená iba v jednom okne." "Aplikácia nemusí fungovať na sekundárnej obrazovke." "Aplikácia nepodporuje spúšťanie na sekundárnych obrazovkách." "Rozdeľovač obrazovky" diff --git a/libs/WindowManager/Shell/res/values-sl/strings.xml b/libs/WindowManager/Shell/res/values-sl/strings.xml index 2a12a64b60762..c4808059a0c46 100644 --- a/libs/WindowManager/Shell/res/values-sl/strings.xml +++ b/libs/WindowManager/Shell/res/values-sl/strings.xml @@ -33,8 +33,7 @@ "Razkrij" "Aplikacija morda ne deluje v načinu razdeljenega zaslona." "Aplikacija ne podpira načina razdeljenega zaslona." - - + "To aplikacijo je mogoče odpreti samo v enem oknu." "Aplikacija morda ne bo delovala na sekundarnem zaslonu." "Aplikacija ne podpira zagona na sekundarnih zaslonih." "Razdelilnik zaslonov" diff --git a/libs/WindowManager/Shell/res/values-sq/strings.xml b/libs/WindowManager/Shell/res/values-sq/strings.xml index eb0199f55eed7..b59d4db6413e7 100644 --- a/libs/WindowManager/Shell/res/values-sq/strings.xml +++ b/libs/WindowManager/Shell/res/values-sq/strings.xml @@ -33,8 +33,7 @@ "Mos e fshih" "Aplikacioni mund të mos funksionojë me ekranin e ndarë." "Aplikacioni nuk mbështet ekranin e ndarë." - - + "Ky aplikacion mund të hapet vetëm në 1 dritare." "Aplikacioni mund të mos funksionojë në një ekran dytësor." "Aplikacioni nuk mbështet nisjen në ekrane dytësore." "Ndarësi i ekranit të ndarë" diff --git a/libs/WindowManager/Shell/res/values-sr/strings.xml b/libs/WindowManager/Shell/res/values-sr/strings.xml index 6e6019c160fe5..78d74d74ac3f2 100644 --- a/libs/WindowManager/Shell/res/values-sr/strings.xml +++ b/libs/WindowManager/Shell/res/values-sr/strings.xml @@ -33,8 +33,7 @@ "Уклоните из тајне меморије" "Апликација можда неће радити са подељеним екраном." "Апликација не подржава подељени екран." - - + "Ова апликација може да се отвори само у једном прозору." "Апликација можда неће функционисати на секундарном екрану." "Апликација не подржава покретање на секундарним екранима." "Разделник подељеног екрана" diff --git a/libs/WindowManager/Shell/res/values-sv/strings.xml b/libs/WindowManager/Shell/res/values-sv/strings.xml index 419c31d3fb836..cda3040dc0560 100644 --- a/libs/WindowManager/Shell/res/values-sv/strings.xml +++ b/libs/WindowManager/Shell/res/values-sv/strings.xml @@ -33,8 +33,7 @@ "Återställ stash" "Appen kanske inte fungerar med delad skärm." "Appen har inte stöd för delad skärm." - - + "Denna app kan bara vara öppen i ett fönster." "Appen kanske inte fungerar på en sekundär skärm." "Appen kan inte köras på en sekundär skärm." "Avdelare för delad skärm" diff --git a/libs/WindowManager/Shell/res/values-te/strings.xml b/libs/WindowManager/Shell/res/values-te/strings.xml index 0c9b96d5e36c8..f0c8be5c59574 100644 --- a/libs/WindowManager/Shell/res/values-te/strings.xml +++ b/libs/WindowManager/Shell/res/values-te/strings.xml @@ -33,8 +33,7 @@ "ఆన్‌స్టాచ్" "స్క్రీన్ విభజనతో యాప్‌ పని చేయకపోవచ్చు." "యాప్‌లో స్క్రీన్ విభజనకు మద్దతు లేదు." - - + "ఈ యాప్‌ను 1 విండోలో మాత్రమే తెరవవచ్చు." "ప్రత్యామ్నాయ డిస్‌ప్లేలో యాప్ పని చేయకపోవచ్చు." "ప్రత్యామ్నాయ డిస్‌ప్లేల్లో ప్రారంభానికి యాప్ మద్దతు లేదు." "విభజన స్క్రీన్ విభాగిని" diff --git a/libs/WindowManager/Shell/res/values-th/strings.xml b/libs/WindowManager/Shell/res/values-th/strings.xml index 94abe5b978454..2437e03777804 100644 --- a/libs/WindowManager/Shell/res/values-th/strings.xml +++ b/libs/WindowManager/Shell/res/values-th/strings.xml @@ -33,8 +33,7 @@ "เอาออกจากที่เก็บส่วนตัว" "แอปอาจใช้ไม่ได้กับโหมดแบ่งหน้าจอ" "แอปไม่สนับสนุนการแยกหน้าจอ" - - + "แอปนี้เปิดได้ใน 1 หน้าต่างเท่านั้น" "แอปอาจไม่ทำงานในจอแสดงผลรอง" "แอปไม่รองรับการเรียกใช้ในจอแสดงผลรอง" "เส้นแบ่งหน้าจอ" diff --git a/libs/WindowManager/Shell/res/values-tl/strings.xml b/libs/WindowManager/Shell/res/values-tl/strings.xml index 589bedd023c5a..86ef75718b774 100644 --- a/libs/WindowManager/Shell/res/values-tl/strings.xml +++ b/libs/WindowManager/Shell/res/values-tl/strings.xml @@ -33,8 +33,7 @@ "I-unstash" "Posibleng hindi gumana ang app sa split screen." "Hindi sinusuportahan ng app ang split-screen." - - + "Sa 1 window lang puwedeng buksan ang app na ito." "Maaaring hindi gumana ang app sa pangalawang display." "Hindi sinusuportahan ng app ang paglulunsad sa mga pangalawang display." "Divider ng split-screen" diff --git a/libs/WindowManager/Shell/res/values-tr/strings.xml b/libs/WindowManager/Shell/res/values-tr/strings.xml index 6b73f2f7ed7bd..c4060cc795abd 100644 --- a/libs/WindowManager/Shell/res/values-tr/strings.xml +++ b/libs/WindowManager/Shell/res/values-tr/strings.xml @@ -33,8 +33,7 @@ "Depolama" "Uygulama bölünmüş ekranda çalışmayabilir." "Uygulama bölünmüş ekranı desteklemiyor." - - + "Bu uygulama yalnızca 1 pencerede açılabilir." "Uygulama ikincil ekranda çalışmayabilir." "Uygulama ikincil ekranlarda başlatılmayı desteklemiyor." "Bölünmüş ekran ayırıcı" diff --git a/libs/WindowManager/Shell/res/values-ur/strings.xml b/libs/WindowManager/Shell/res/values-ur/strings.xml index 50908cc24fbd1..ca6a93714cdd0 100644 --- a/libs/WindowManager/Shell/res/values-ur/strings.xml +++ b/libs/WindowManager/Shell/res/values-ur/strings.xml @@ -33,8 +33,7 @@ "Unstash" "ممکن ہے کہ ایپ اسپلٹ اسکرین کے ساتھ کام نہ کرے۔" "ایپ سپلٹ اسکرین کو سپورٹ نہیں کرتی۔" - - + "یہ ایپ صرف 1 ونڈو میں کھولی جا سکتی ہے۔" "ممکن ہے ایپ ثانوی ڈسپلے پر کام نہ کرے۔" "ایپ ثانوی ڈسپلیز پر شروعات کا تعاون نہیں کرتی۔" "سپلٹ اسکرین تقسیم کار" diff --git a/libs/WindowManager/Shell/res/values-uz/strings.xml b/libs/WindowManager/Shell/res/values-uz/strings.xml index e0b802e6b0b9f..8f173d5d1e4bc 100644 --- a/libs/WindowManager/Shell/res/values-uz/strings.xml +++ b/libs/WindowManager/Shell/res/values-uz/strings.xml @@ -33,8 +33,7 @@ "Chiqarish" "Bu ilova ekranni ikkiga ajratish rejimini dastaklamaydi." "Bu ilova ekranni bo‘lish xususiyatini qo‘llab-quvvatlamaydi." - - + "Bu ilovani faqat 1 ta oynada ochish mumkin." "Bu ilova qo‘shimcha ekranda ishlamasligi mumkin." "Bu ilova qo‘shimcha ekranlarda ishga tushmaydi." "Ekranni ikkiga bo‘lish chizig‘i" diff --git a/libs/WindowManager/Shell/res/values-vi/strings.xml b/libs/WindowManager/Shell/res/values-vi/strings.xml index 71c3632714f16..1d5b9d63ee5a1 100644 --- a/libs/WindowManager/Shell/res/values-vi/strings.xml +++ b/libs/WindowManager/Shell/res/values-vi/strings.xml @@ -33,8 +33,7 @@ "Hiện" "Ứng dụng có thể không hoạt động với tính năng chia đôi màn hình." "Ứng dụng không hỗ trợ chia đôi màn hình." - - + "Ứng dụng này chỉ có thể mở 1 cửa sổ." "Ứng dụng có thể không hoạt động trên màn hình phụ." "Ứng dụng không hỗ trợ khởi chạy trên màn hình phụ." "Bộ chia chia đôi màn hình" diff --git a/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml b/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml index 35ff2f22be03c..87f2973aa6182 100644 --- a/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml +++ b/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml @@ -33,8 +33,7 @@ "取消隐藏" "应用可能无法在分屏模式下正常运行。" "应用不支持分屏。" - - + "此应用只能在 1 个窗口中打开。" "应用可能无法在辅显示屏上正常运行。" "应用不支持在辅显示屏上启动。" "分屏分隔线" diff --git a/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml b/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml index 9c17f64b881f5..f9b22d226c4f4 100644 --- a/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml +++ b/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml @@ -33,8 +33,7 @@ "取消保護" "應用程式可能無法在分割畫面中運作。" "應用程式不支援分割畫面。" - - + "此應用程式只可在 1 個視窗中開啟" "應用程式可能無法在次要顯示屏上運作。" "應用程式無法在次要顯示屏上啟動。" "分割畫面分隔線" diff --git a/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml b/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml index c4d9ca467a82b..1438e52ccb4a3 100644 --- a/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml +++ b/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml @@ -33,8 +33,7 @@ "取消暫時隱藏" "應用程式可能無法在分割畫面中運作。" "這個應用程式不支援分割畫面。" - - + "這個應用程式只能在 1 個視窗中開啟。" "應用程式可能無法在次要顯示器上運作。" "應用程式無法在次要顯示器上啟動。" "分割畫面分隔線" diff --git a/libs/WindowManager/Shell/res/values-zu/strings.xml b/libs/WindowManager/Shell/res/values-zu/strings.xml index 4d8f7e33d47e7..e9238dc0833a5 100644 --- a/libs/WindowManager/Shell/res/values-zu/strings.xml +++ b/libs/WindowManager/Shell/res/values-zu/strings.xml @@ -33,8 +33,7 @@ "Susa isiteshi" "Izinhlelo zokusebenza kungenzeka zingasebenzi ngesikrini esihlukanisiwe." "Uhlelo lokusebenza alusekeli isikrini esihlukanisiwe." - - + "Le-app ingavulwa kuphela ewindini eli-1." "Uhlelo lokusebenza kungenzeka lungasebenzi kusibonisi sesibili." "Uhlelo lokusebenza alusekeli ukuqalisa kuzibonisi zesibili." "Isihlukanisi sokuhlukanisa isikrini" From 66d7124d33ed4d283c71b094ed6dcef00b1885d2 Mon Sep 17 00:00:00 2001 From: Jerry Chang Date: Wed, 30 Nov 2022 14:49:05 +0000 Subject: [PATCH 14/38] Revert "Fix win mode issues for unresizable apps" This reverts commit 383b0006c5e024c3dc63bc0884a7aae23c039516. Reason for revert: b/260695808 Change-Id: Ic2f6b57534f393731e40c210f3b7b00b7c1fa6b8 --- .../server/wm/TaskLaunchParamsModifier.java | 43 +++++++++---------- .../wm/TaskLaunchParamsModifierTests.java | 42 +++--------------- 2 files changed, 26 insertions(+), 59 deletions(-) diff --git a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java index 39499523833e1..14a2d0383019e 100644 --- a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java +++ b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java @@ -277,31 +277,29 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier { // is set with the suggestedDisplayArea. If it is set, but the eventual TaskDisplayArea is // different, we should recalcuating the bounds. boolean hasInitialBoundsForSuggestedDisplayAreaInFreeformMode = false; - // shouldSetAsOverrideWindowingMode is set if the task needs to retain the launchMode - // regardless of the windowing mode of the parent. - boolean shouldSetAsOverrideWindowingMode = false; - if (launchMode == WINDOWING_MODE_PINNED) { - if (DEBUG) appendLog("picture-in-picture"); - } else if (!root.isResizeable()) { - if (shouldLaunchUnresizableAppInFreeformInFreeformMode(root, suggestedDisplayArea, - options)) { - launchMode = WINDOWING_MODE_UNDEFINED; - if (outParams.mBounds.isEmpty()) { - getTaskBounds(root, suggestedDisplayArea, layout, launchMode, hasInitialBounds, - outParams.mBounds); - hasInitialBoundsForSuggestedDisplayAreaInFreeformMode = true; + if (suggestedDisplayArea.inFreeformWindowingMode()) { + if (launchMode == WINDOWING_MODE_PINNED) { + if (DEBUG) appendLog("picture-in-picture"); + } else if (!root.isResizeable()) { + if (shouldLaunchUnresizableAppInFreeform(root, suggestedDisplayArea, options)) { + launchMode = WINDOWING_MODE_FREEFORM; + if (outParams.mBounds.isEmpty()) { + getTaskBounds(root, suggestedDisplayArea, layout, launchMode, + hasInitialBounds, outParams.mBounds); + hasInitialBoundsForSuggestedDisplayAreaInFreeformMode = true; + } + if (DEBUG) appendLog("unresizable-freeform"); + } else { + launchMode = WINDOWING_MODE_FULLSCREEN; + outParams.mBounds.setEmpty(); + if (DEBUG) appendLog("unresizable-forced-maximize"); } - if (DEBUG) appendLog("unresizable-freeform"); - } else { - launchMode = WINDOWING_MODE_FULLSCREEN; - outParams.mBounds.setEmpty(); - shouldSetAsOverrideWindowingMode = true; - if (DEBUG) appendLog("unresizable-forced-maximize"); } + } else { + if (DEBUG) appendLog("non-freeform-task-display-area"); } // If launch mode matches display windowing mode, let it inherit from display. outParams.mWindowingMode = launchMode == suggestedDisplayArea.getWindowingMode() - && !shouldSetAsOverrideWindowingMode ? WINDOWING_MODE_UNDEFINED : launchMode; if (phase == PHASE_WINDOWING_MODE) { @@ -652,7 +650,7 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier { inOutBounds.offset(xOffset, yOffset); } - private boolean shouldLaunchUnresizableAppInFreeformInFreeformMode(ActivityRecord activity, + private boolean shouldLaunchUnresizableAppInFreeform(ActivityRecord activity, TaskDisplayArea displayArea, @Nullable ActivityOptions options) { if (options != null && options.getLaunchWindowingMode() == WINDOWING_MODE_FULLSCREEN) { // Do not launch the activity in freeform if it explicitly requested fullscreen mode. @@ -665,7 +663,8 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier { final int displayOrientation = orientationFromBounds(displayArea.getBounds()); final int activityOrientation = resolveOrientation(activity, displayArea, displayArea.getBounds()); - if (displayOrientation != activityOrientation) { + if (displayArea.getWindowingMode() == WINDOWING_MODE_FREEFORM + && displayOrientation != activityOrientation) { return true; } diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java index 2a88eb0e7b617..1188f49ae60e9 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java @@ -825,11 +825,10 @@ public class TaskLaunchParamsModifierTests extends WindowTestsBase { } @Test - public void testLaunchesPortraitUnresizableOnFreeformLandscapeDisplay() { + public void testLaunchesPortraitUnresizableOnFreeformDisplayWithFreeformSizeCompat() { mAtm.mDevEnableNonResizableMultiWindow = true; final TestDisplayContent freeformDisplay = createNewDisplayContent( WINDOWING_MODE_FREEFORM); - assertTrue(freeformDisplay.getBounds().width() > freeformDisplay.getBounds().height()); final ActivityOptions options = ActivityOptions.makeBasic(); mCurrent.mPreferredTaskDisplayArea = freeformDisplay.getDefaultTaskDisplayArea(); mActivity.info.resizeMode = RESIZE_MODE_UNRESIZEABLE; @@ -837,42 +836,12 @@ public class TaskLaunchParamsModifierTests extends WindowTestsBase { assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setOptions(options).calculate()); - assertEquals(WINDOWING_MODE_UNDEFINED, mResult.mWindowingMode); - } - - @Test - public void testLaunchesLandscapeUnresizableOnFreeformLandscapeDisplay() { - mAtm.mDevEnableNonResizableMultiWindow = true; - final TestDisplayContent freeformDisplay = createNewDisplayContent( + assertEquivalentWindowingMode(WINDOWING_MODE_FREEFORM, mResult.mWindowingMode, WINDOWING_MODE_FREEFORM); - assertTrue(freeformDisplay.getBounds().width() > freeformDisplay.getBounds().height()); - final ActivityOptions options = ActivityOptions.makeBasic(); - mCurrent.mPreferredTaskDisplayArea = freeformDisplay.getDefaultTaskDisplayArea(); - mActivity.info.resizeMode = RESIZE_MODE_UNRESIZEABLE; - mActivity.info.screenOrientation = SCREEN_ORIENTATION_LANDSCAPE; - assertEquals(RESULT_CONTINUE, - new CalculateRequestBuilder().setOptions(options).calculate()); - - assertEquals(WINDOWING_MODE_FULLSCREEN, mResult.mWindowingMode); } @Test - public void testLaunchesUndefinedUnresizableOnFreeformLandscapeDisplay() { - mAtm.mDevEnableNonResizableMultiWindow = true; - final TestDisplayContent freeformDisplay = createNewDisplayContent( - WINDOWING_MODE_FREEFORM); - assertTrue(freeformDisplay.getBounds().width() > freeformDisplay.getBounds().height()); - final ActivityOptions options = ActivityOptions.makeBasic(); - mCurrent.mPreferredTaskDisplayArea = freeformDisplay.getDefaultTaskDisplayArea(); - mActivity.info.resizeMode = RESIZE_MODE_UNRESIZEABLE; - assertEquals(RESULT_CONTINUE, - new CalculateRequestBuilder().setOptions(options).calculate()); - - assertEquals(WINDOWING_MODE_FULLSCREEN, mResult.mWindowingMode); - } - - @Test - public void testForceMaximizingAppsOnNonFreeformDisplay() { + public void testSkipsForceMaximizingAppsOnNonFreeformDisplay() { final ActivityOptions options = ActivityOptions.makeBasic(); options.setLaunchWindowingMode(WINDOWING_MODE_FREEFORM); options.setLaunchBounds(new Rect(0, 0, 200, 100)); @@ -886,9 +855,8 @@ public class TaskLaunchParamsModifierTests extends WindowTestsBase { assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setOptions(options).calculate()); - // Non-resizable apps must be launched in fullscreen in a fullscreen display regardless of - // other properties. - assertEquals(WINDOWING_MODE_FULLSCREEN, mResult.mWindowingMode); + assertEquivalentWindowingMode(WINDOWING_MODE_FREEFORM, mResult.mWindowingMode, + WINDOWING_MODE_FULLSCREEN); } @Test From dd3aaa81dc7bcd50bfa8cc87657bdbe9e2b47fdf Mon Sep 17 00:00:00 2001 From: Justin Weir Date: Tue, 29 Nov 2022 15:26:35 -0500 Subject: [PATCH 15/38] Prevent touch event dispatch on the top edge when collapsed For some reason, touch events at y=0 can get dispatched all the way to Quick Settings, even though it is not visible. This change prevents that from happening in the most narrow way I could find. Fixes: 235889526 Test: atest and manual Change-Id: Iedbb3b55a94864d320b886ba7c29913ad4b8b145 --- .../NotificationPanelViewController.java | 26 +++++++++---------- .../NotificationPanelViewControllerTest.java | 13 +++++++++- 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java index 629d3d4d50ba8..13ce20cb5822a 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java @@ -4603,20 +4603,20 @@ public final class NotificationPanelViewController implements Dumpable { return false; } - // If the view that would receive the touch is disabled, just have status bar - // eat the gesture. - if (event.getAction() == MotionEvent.ACTION_DOWN && !mView.isEnabled()) { - Log.v(TAG, - String.format( - "onTouchForwardedFromStatusBar: " - + "panel view disabled, eating touch at (%d,%d)", - (int) event.getX(), - (int) event.getY() - ) - ); - return true; + if (event.getAction() == MotionEvent.ACTION_DOWN) { + // If the view that would receive the touch is disabled, just have status + // bar eat the gesture. + if (!mView.isEnabled()) { + mShadeLog.logMotionEvent(event, + "onTouchForwardedFromStatusBar: panel view disabled"); + return true; + } + if (isFullyCollapsed() && event.getY() < 1f) { + // b/235889526 Eat events on the top edge of the phone when collapsed + mShadeLog.logMotionEvent(event, "top edge touch ignored"); + return true; + } } - return mView.dispatchTouchEvent(event); } }; diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java index 69a45599668bd..f5b3bd081c72c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java @@ -831,13 +831,24 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { public void handleTouchEventFromStatusBar_panelAndViewEnabled_viewReceivesEvent() { when(mCommandQueue.panelsEnabled()).thenReturn(true); when(mView.isEnabled()).thenReturn(true); - MotionEvent event = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0); + MotionEvent event = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 2f, 0); mNotificationPanelViewController.getStatusBarTouchEventHandler().handleTouchEvent(event); verify(mView).dispatchTouchEvent(event); } + @Test + public void handleTouchEventFromStatusBar_topEdgeTouch_viewNeverReceivesEvent() { + when(mCommandQueue.panelsEnabled()).thenReturn(true); + when(mView.isEnabled()).thenReturn(true); + MotionEvent event = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0); + + mNotificationPanelViewController.getStatusBarTouchEventHandler().handleTouchEvent(event); + + verify(mView, never()).dispatchTouchEvent(event); + } + @Test public void testA11y_initializeNode() { AccessibilityNodeInfo nodeInfo = new AccessibilityNodeInfo(); From c5cd47b21691bfd05f60c92dd7c1180e76d49d75 Mon Sep 17 00:00:00 2001 From: Caitlin Shkuratov Date: Fri, 18 Nov 2022 16:11:02 +0000 Subject: [PATCH 16/38] [SB Refactor] Make some wifi pipeline classes into interfaces. This is needed for WifiScreenshotTest so that more of the pipeline can be faked out. Bug: 238425913 Test: manual: verified new wifi icon still works Test: atest WifiScreenshotTest Test: atest all tests in statusbar.pipeline Change-Id: I335451e62c5db01143226d7cdc3ee29b93301bf2 --- packages/SystemUI/ktfmt_includes.txt | 2 +- .../ui/viewmodel/AirplaneModeViewModel.kt | 12 +++-- .../dagger/StatusBarPipelineModule.kt | 10 ++++ .../wifi/domain/interactor/WifiInteractor.kt | 47 ++++++++++++------- ...st.kt => AirplaneModeViewModelImplTest.kt} | 6 +-- ...actorTest.kt => WifiInteractorImplTest.kt} | 5 +- .../ui/view/ModernStatusBarWifiViewTest.kt | 6 ++- .../WifiViewModelIconParameterizedTest.kt | 6 ++- .../wifi/ui/viewmodel/WifiViewModelTest.kt | 6 ++- 9 files changed, 68 insertions(+), 32 deletions(-) rename packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/{AirplaneModeViewModelTest.kt => AirplaneModeViewModelImplTest.kt} (96%) rename packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/{WifiInteractorTest.kt => WifiInteractorImplTest.kt} (97%) diff --git a/packages/SystemUI/ktfmt_includes.txt b/packages/SystemUI/ktfmt_includes.txt index 553b86bb833fd..0143ac783b956 100644 --- a/packages/SystemUI/ktfmt_includes.txt +++ b/packages/SystemUI/ktfmt_includes.txt @@ -753,7 +753,7 @@ -packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherControllerOldImplTest.kt -packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityPipelineLoggerTest.kt -packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepositoryImplTest.kt --packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorTest.kt +-packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorImplTest.kt -packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiViewTest.kt -packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelTest.kt -packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BatteryStateNotifierTest.kt diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModel.kt index fe30c0169021f..4a5342e0f765c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModel.kt @@ -36,16 +36,20 @@ import kotlinx.coroutines.flow.stateIn * [com.android.systemui.statusbar.pipeline.airplane.data.repository.AirplaneModeRepository] for * more details. */ +interface AirplaneModeViewModel { + /** True if the airplane mode icon is currently visible in the status bar. */ + val isAirplaneModeIconVisible: StateFlow +} + @SysUISingleton -class AirplaneModeViewModel +class AirplaneModeViewModelImpl @Inject constructor( interactor: AirplaneModeInteractor, logger: ConnectivityPipelineLogger, @Application private val scope: CoroutineScope, -) { - /** True if the airplane mode icon is currently visible in the status bar. */ - val isAirplaneModeIconVisible: StateFlow = +) : AirplaneModeViewModel { + override val isAirplaneModeIconVisible: StateFlow = combine(interactor.isAirplaneMode, interactor.isForceHidden) { isAirplaneMode, isAirplaneIconForceHidden -> diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt index fcd1b8abefe47..d8ae1c18343cd 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt @@ -18,6 +18,8 @@ package com.android.systemui.statusbar.pipeline.dagger import com.android.systemui.statusbar.pipeline.airplane.data.repository.AirplaneModeRepository import com.android.systemui.statusbar.pipeline.airplane.data.repository.AirplaneModeRepositoryImpl +import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModel +import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModelImpl import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionsRepository import com.android.systemui.statusbar.pipeline.mobile.data.repository.MobileConnectionsRepositoryImpl import com.android.systemui.statusbar.pipeline.mobile.data.repository.UserSetupRepository @@ -30,6 +32,8 @@ import com.android.systemui.statusbar.pipeline.shared.data.repository.Connectivi import com.android.systemui.statusbar.pipeline.shared.data.repository.ConnectivityRepositoryImpl import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepositoryImpl +import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractor +import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractorImpl import dagger.Binds import dagger.Module @@ -38,12 +42,18 @@ abstract class StatusBarPipelineModule { @Binds abstract fun airplaneModeRepository(impl: AirplaneModeRepositoryImpl): AirplaneModeRepository + @Binds + abstract fun airplaneModeViewModel(impl: AirplaneModeViewModelImpl): AirplaneModeViewModel + @Binds abstract fun connectivityRepository(impl: ConnectivityRepositoryImpl): ConnectivityRepository @Binds abstract fun wifiRepository(impl: WifiRepositoryImpl): WifiRepository + @Binds + abstract fun wifiInteractor(impl: WifiInteractorImpl): WifiInteractor + @Binds abstract fun mobileConnectionsRepository( impl: MobileConnectionsRepositoryImpl diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractor.kt index 3a3e611de96a9..ec935fe23d396 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractor.kt @@ -34,16 +34,36 @@ import kotlinx.coroutines.flow.map * This interactor processes information from our data layer into information that the UI layer can * use. */ -@SysUISingleton -class WifiInteractor @Inject constructor( - connectivityRepository: ConnectivityRepository, - wifiRepository: WifiRepository, -) { +interface WifiInteractor { /** * The SSID (service set identifier) of the wifi network. Null if we don't have a network, or * have a network but no valid SSID. */ - val ssid: Flow = wifiRepository.wifiNetwork.map { info -> + val ssid: Flow + + /** Our current enabled status. */ + val isEnabled: Flow + + /** Our current default status. */ + val isDefault: Flow + + /** Our current wifi network. See [WifiNetworkModel]. */ + val wifiNetwork: Flow + + /** Our current wifi activity. See [WifiActivityModel]. */ + val activity: StateFlow + + /** True if we're configured to force-hide the wifi icon and false otherwise. */ + val isForceHidden: Flow +} + +@SysUISingleton +class WifiInteractorImpl @Inject constructor( + connectivityRepository: ConnectivityRepository, + wifiRepository: WifiRepository, +) : WifiInteractor { + + override val ssid: Flow = wifiRepository.wifiNetwork.map { info -> when (info) { is WifiNetworkModel.Inactive -> null is WifiNetworkModel.CarrierMerged -> null @@ -56,20 +76,15 @@ class WifiInteractor @Inject constructor( } } - /** Our current enabled status. */ - val isEnabled: Flow = wifiRepository.isWifiEnabled + override val isEnabled: Flow = wifiRepository.isWifiEnabled - /** Our current default status. */ - val isDefault: Flow = wifiRepository.isWifiDefault + override val isDefault: Flow = wifiRepository.isWifiDefault - /** Our current wifi network. See [WifiNetworkModel]. */ - val wifiNetwork: Flow = wifiRepository.wifiNetwork + override val wifiNetwork: Flow = wifiRepository.wifiNetwork - /** Our current wifi activity. See [WifiActivityModel]. */ - val activity: StateFlow = wifiRepository.wifiActivity + override val activity: StateFlow = wifiRepository.wifiActivity - /** True if we're configured to force-hide the wifi icon and false otherwise. */ - val isForceHidden: Flow = connectivityRepository.forceHiddenSlots.map { + override val isForceHidden: Flow = connectivityRepository.forceHiddenSlots.map { it.contains(ConnectivitySlot.WIFI) } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModelImplTest.kt similarity index 96% rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModelTest.kt rename to packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModelImplTest.kt index 76016a121e686..5a6bb301743ae 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/airplane/ui/viewmodel/AirplaneModeViewModelImplTest.kt @@ -38,9 +38,9 @@ import org.mockito.MockitoAnnotations @SmallTest @OptIn(ExperimentalCoroutinesApi::class) @Suppress("EXPERIMENTAL_IS_NOT_ENABLED") -class AirplaneModeViewModelTest : SysuiTestCase() { +class AirplaneModeViewModelImplTest : SysuiTestCase() { - private lateinit var underTest: AirplaneModeViewModel + private lateinit var underTest: AirplaneModeViewModelImpl @Mock private lateinit var logger: ConnectivityPipelineLogger private lateinit var airplaneModeRepository: FakeAirplaneModeRepository @@ -57,7 +57,7 @@ class AirplaneModeViewModelTest : SysuiTestCase() { scope = CoroutineScope(IMMEDIATE) underTest = - AirplaneModeViewModel( + AirplaneModeViewModelImpl( interactor, logger, scope, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorImplTest.kt similarity index 97% rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorTest.kt rename to packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorImplTest.kt index 71b8bab87d197..b38497a7bbdd2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/domain/interactor/WifiInteractorImplTest.kt @@ -35,8 +35,9 @@ import org.junit.Before import org.junit.Test @OptIn(ExperimentalCoroutinesApi::class) +@Suppress("EXPERIMENTAL_IS_NOT_ENABLED") @SmallTest -class WifiInteractorTest : SysuiTestCase() { +class WifiInteractorImplTest : SysuiTestCase() { private lateinit var underTest: WifiInteractor @@ -47,7 +48,7 @@ class WifiInteractorTest : SysuiTestCase() { fun setUp() { connectivityRepository = FakeConnectivityRepository() wifiRepository = FakeWifiRepository() - underTest = WifiInteractor(connectivityRepository, wifiRepository) + underTest = WifiInteractorImpl(connectivityRepository, wifiRepository) } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiViewTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiViewTest.kt index 37457b3085970..5c16e1295b659 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiViewTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/view/ModernStatusBarWifiViewTest.kt @@ -32,12 +32,14 @@ import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModel +import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModelImpl import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractor +import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractorImpl import com.android.systemui.statusbar.pipeline.wifi.shared.WifiConstants import com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel.LocationBasedWifiViewModel import com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel.WifiViewModel @@ -86,9 +88,9 @@ class ModernStatusBarWifiViewTest : SysuiTestCase() { connectivityRepository = FakeConnectivityRepository() wifiRepository = FakeWifiRepository() wifiRepository.setIsWifiEnabled(true) - interactor = WifiInteractor(connectivityRepository, wifiRepository) + interactor = WifiInteractorImpl(connectivityRepository, wifiRepository) scope = CoroutineScope(Dispatchers.Unconfined) - airplaneModeViewModel = AirplaneModeViewModel( + airplaneModeViewModel = AirplaneModeViewModelImpl( AirplaneModeInteractor( airplaneModeRepository, connectivityRepository, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelIconParameterizedTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelIconParameterizedTest.kt index a1afcd71e3c3d..3001b81621852 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelIconParameterizedTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelIconParameterizedTest.kt @@ -30,6 +30,7 @@ import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModel +import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModelImpl import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlot @@ -37,6 +38,7 @@ import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnec import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractor +import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractorImpl import com.android.systemui.statusbar.pipeline.wifi.shared.WifiConstants import com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel.WifiViewModel.Companion.NO_INTERNET import com.google.common.truth.Truth.assertThat @@ -81,10 +83,10 @@ internal class WifiViewModelIconParameterizedTest(private val testCase: TestCase connectivityRepository = FakeConnectivityRepository() wifiRepository = FakeWifiRepository() wifiRepository.setIsWifiEnabled(true) - interactor = WifiInteractor(connectivityRepository, wifiRepository) + interactor = WifiInteractorImpl(connectivityRepository, wifiRepository) scope = CoroutineScope(IMMEDIATE) airplaneModeViewModel = - AirplaneModeViewModel( + AirplaneModeViewModelImpl( AirplaneModeInteractor( airplaneModeRepository, connectivityRepository, diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelTest.kt index 7d2c56098584f..6a6b2a801ab01 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModelTest.kt @@ -23,6 +23,7 @@ import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags import com.android.systemui.statusbar.pipeline.airplane.data.repository.FakeAirplaneModeRepository import com.android.systemui.statusbar.pipeline.airplane.domain.interactor.AirplaneModeInteractor import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModel +import com.android.systemui.statusbar.pipeline.airplane.ui.viewmodel.AirplaneModeViewModelImpl import com.android.systemui.statusbar.pipeline.shared.ConnectivityConstants import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlot @@ -30,6 +31,7 @@ import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnec import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractor +import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiInteractorImpl import com.android.systemui.statusbar.pipeline.wifi.shared.WifiConstants import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiActivityModel import com.google.common.truth.Truth.assertThat @@ -73,9 +75,9 @@ class WifiViewModelTest : SysuiTestCase() { connectivityRepository = FakeConnectivityRepository() wifiRepository = FakeWifiRepository() wifiRepository.setIsWifiEnabled(true) - interactor = WifiInteractor(connectivityRepository, wifiRepository) + interactor = WifiInteractorImpl(connectivityRepository, wifiRepository) scope = CoroutineScope(IMMEDIATE) - airplaneModeViewModel = AirplaneModeViewModel( + airplaneModeViewModel = AirplaneModeViewModelImpl( AirplaneModeInteractor( airplaneModeRepository, connectivityRepository, From 4714ab131716246a4e94c62c75e63df4e7f3eb90 Mon Sep 17 00:00:00 2001 From: Hawkwood Glazier Date: Wed, 30 Nov 2022 17:05:02 +0000 Subject: [PATCH 17/38] Fix clock being too low in AOD To fix the clock being too low, this undoes the relevant portions of I3feea196bf348630697385e010a13955cdb0a897. We'll want to revert this when we figure out why the clock is moving so low in AOD. The clock still moves vertically a significant distance when entering and leaving AOD, but not so much as to overlap with the UDFPS/lock icon. I'm continuing to investigate what's causing that. Test: Manual Bug: 259758161 Change-Id: Iaeddce2d99a2b8db5afb6ac8ca508eeab3ae223e --- .../systemui/shared/clocks/DefaultClockController.kt | 11 ++--------- .../res-keyguard/layout/keyguard_clock_switch.xml | 1 + 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt index 869884474ffe3..e1f21742bf93d 100644 --- a/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt +++ b/packages/SystemUI/customization/src/com/android/systemui/shared/clocks/DefaultClockController.kt @@ -20,7 +20,6 @@ import android.graphics.Rect import android.icu.text.NumberFormat import android.util.TypedValue import android.view.LayoutInflater -import android.view.View import android.widget.FrameLayout import androidx.annotation.VisibleForTesting import com.android.systemui.customization.R @@ -152,15 +151,9 @@ class DefaultClockController( view: AnimatableClockView, ) : DefaultClockFaceController(view) { override fun recomputePadding(targetRegion: Rect?) { - // We center the view within the targetRegion instead of within the parent - // view by computing the difference and adding that to the padding. - val parent = view.parent - val yDiff = - if (targetRegion != null && parent is View && parent.isLaidOut()) - targetRegion.centerY() - parent.height / 2f - else 0f + // Ignore Target Region until top padding fixed in aod val lp = view.getLayoutParams() as FrameLayout.LayoutParams - lp.topMargin = (-0.5f * view.bottom + yDiff).toInt() + lp.topMargin = (-0.5f * view.bottom).toInt() view.setLayoutParams(lp) } diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml index b49afeef09f3b..218c5cc9b7fec 100644 --- a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml +++ b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml @@ -35,6 +35,7 @@ android:visibility="invisible" /> Date: Wed, 30 Nov 2022 10:06:41 -0800 Subject: [PATCH 18/38] Enable SysUI Predictive Back in teamfood. Bug: 255854141 Test: manual, and passed presubmit Change-Id: I502967bd0c39206442cf98bea227f21363773798 --- packages/SystemUI/src/com/android/systemui/flags/Flags.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt index db19749d06dec..b1f74fc78e9f0 100644 --- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt +++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt @@ -377,7 +377,7 @@ object Flags { // TODO(b/255854141): Tracking Bug @JvmField val WM_ENABLE_PREDICTIVE_BACK_SYSUI = - unreleasedFlag(1204, "persist.wm.debug.predictive_back_sysui_enable", teamfood = false) + unreleasedFlag(1204, "persist.wm.debug.predictive_back_sysui_enable", teamfood = true) // 1300 - screenshots // TODO(b/254512719): Tracking Bug From 206f2e7894b5a911601bb768d0b6925ae0a138c5 Mon Sep 17 00:00:00 2001 From: Josh Tsuji Date: Wed, 30 Nov 2022 14:04:59 -0500 Subject: [PATCH 19/38] Migrate LightRevealScrim and all dependencies to flows. Bug: 195430376 Test: atest LightRevealScrimRepositoryTest Test: atest LightRevealScrimInteractorTest Change-Id: I5ddede5301b4f3cf92d678e9276785823ae29d25 --- .../systemui/biometrics/AuthController.java | 26 ++- .../biometrics/AuthRippleController.kt | 26 ++- .../src/com/android/systemui/flags/Flags.kt | 7 + .../data/repository/KeyguardRepository.kt | 198 +++++++++++++----- .../repository/KeyguardRepositoryModule.kt | 3 + .../repository/LightRevealScrimRepository.kt | 149 +++++++++++++ .../AodLockscreenTransitionInteractor.kt | 1 - .../DreamingToAodTransitionInteractor.kt | 2 +- .../interactor/GoneAodTransitionInteractor.kt | 7 +- .../domain/interactor/KeyguardInteractor.kt | 12 +- .../KeyguardTransitionAuditLogger.kt | 2 +- .../interactor/LightRevealScrimInteractor.kt | 95 +++++++++ .../LockscreenBouncerTransitionInteractor.kt | 45 ++-- .../shared/model/BiometricUnlockSource.kt | 39 ++++ .../keyguard/shared/model/WakeSleepReason.kt | 44 ++++ .../keyguard/shared/model/WakefulnessModel.kt | 34 +-- .../keyguard/shared/model/WakefulnessState.kt | 44 ++++ .../ui/binder/LightRevealScrimViewBinder.kt | 43 ++++ .../ui/viewmodel/LightRevealScrimViewModel.kt | 31 +++ .../phone/BiometricUnlockController.java | 2 +- .../statusbar/phone/CentralSurfacesImpl.java | 29 ++- .../biometrics/AuthRippleControllerTest.kt | 3 + .../repository/KeyguardRepositoryImplTest.kt | 160 ++++++++++++-- .../LightRevealScrimRepositoryTest.kt | 167 +++++++++++++++ .../LightRevealScrimInteractorTest.kt | 154 ++++++++++++++ .../phone/CentralSurfacesImplTest.java | 5 +- .../data/repository/FakeKeyguardRepository.kt | 43 +++- .../FakeLightRevealScrimRepository.kt | 33 +++ 28 files changed, 1273 insertions(+), 131 deletions(-) create mode 100644 packages/SystemUI/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepository.kt create mode 100644 packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractor.kt create mode 100644 packages/SystemUI/src/com/android/systemui/keyguard/shared/model/BiometricUnlockSource.kt create mode 100644 packages/SystemUI/src/com/android/systemui/keyguard/shared/model/WakeSleepReason.kt create mode 100644 packages/SystemUI/src/com/android/systemui/keyguard/shared/model/WakefulnessState.kt create mode 100644 packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/LightRevealScrimViewBinder.kt create mode 100644 packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LightRevealScrimViewModel.kt create mode 100644 packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepositoryTest.kt create mode 100644 packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractorTest.kt create mode 100644 packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeLightRevealScrimRepository.kt diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java index eb974dd909be3..092339a74e3f3 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java @@ -598,6 +598,10 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks, getFingerprintSensorLocationInNaturalOrientation(), mCachedDisplayInfo); } + + for (final Callback cb : mCallbacks) { + cb.onFingerprintLocationChanged(); + } } /** @@ -619,6 +623,10 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks, mCachedDisplayInfo ); } + + for (final Callback cb : mCallbacks) { + cb.onFaceSensorLocationChanged(); + } } /** @@ -1265,8 +1273,24 @@ public class AuthController implements CoreStartable, CommandQueue.Callbacks, default void onBiometricPromptDismissed() {} /** - * The location in pixels can change due to resolution changes. + * Called when the location of the fingerprint sensor changes. The location in pixels can + * change due to resolution changes. + */ + default void onFingerprintLocationChanged() {} + + /** + * Called when the location of the under display fingerprint sensor changes. The location in + * pixels can change due to resolution changes. + * + * On devices with UDFPS, this is always called alongside + * {@link #onFingerprintLocationChanged}. */ default void onUdfpsLocationChanged() {} + + /** + * Called when the location of the face unlock sensor (typically the front facing camera) + * changes. The location in pixels can change due to resolution changes. + */ + default void onFaceSensorLocationChanged() {} } } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt index 0c1cb9233c892..d68fcd0a59226 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleController.kt @@ -29,6 +29,8 @@ import com.android.keyguard.KeyguardUpdateMonitorCallback import com.android.settingslib.Utils import com.android.systemui.R import com.android.systemui.animation.Interpolators +import com.android.systemui.flags.FeatureFlags +import com.android.systemui.flags.Flags import com.android.systemui.keyguard.WakefulnessLifecycle import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.statusbar.CircleReveal @@ -71,7 +73,8 @@ class AuthRippleController @Inject constructor( private val biometricUnlockController: BiometricUnlockController, private val udfpsControllerProvider: Provider, private val statusBarStateController: StatusBarStateController, - rippleView: AuthRippleView? + private val featureFlags: FeatureFlags, + rippleView: AuthRippleView? ) : ViewController(rippleView), KeyguardStateController.Callback, WakefulnessLifecycle.Observer { @@ -159,12 +162,17 @@ class AuthRippleController @Inject constructor( private fun showUnlockedRipple() { notificationShadeWindowController.setForcePluginOpen(true, this) - val lightRevealScrim = centralSurfaces.lightRevealScrim - if (statusBarStateController.isDozing || biometricUnlockController.isWakeAndUnlock) { - circleReveal?.let { - lightRevealScrim?.revealAmount = 0f - lightRevealScrim?.revealEffect = it - startLightRevealScrimOnKeyguardFadingAway = true + + // This code path is not used if the KeyguardTransitionRepository is managing the light + // reveal scrim. + if (!featureFlags.isEnabled(Flags.LIGHT_REVEAL_MIGRATION)) { + val lightRevealScrim = centralSurfaces.lightRevealScrim + if (statusBarStateController.isDozing || biometricUnlockController.isWakeAndUnlock) { + circleReveal?.let { + lightRevealScrim?.revealAmount = 0f + lightRevealScrim?.revealEffect = it + startLightRevealScrimOnKeyguardFadingAway = true + } } } @@ -177,6 +185,10 @@ class AuthRippleController @Inject constructor( } override fun onKeyguardFadingAwayChanged() { + if (featureFlags.isEnabled(Flags.LIGHT_REVEAL_MIGRATION)) { + return + } + if (keyguardStateController.isKeyguardFadingAway) { val lightRevealScrim = centralSurfaces.lightRevealScrim if (startLightRevealScrimOnKeyguardFadingAway && lightRevealScrim != null) { diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt index db19749d06dec..a118b78fc50a5 100644 --- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt +++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt @@ -164,6 +164,13 @@ object Flags { // TODO(b/256513609): Tracking Bug @JvmField val ACTIVE_UNLOCK_CHIPBAR = releasedFlag(217, "active_unlock_chipbar") + /** + * Migrates control of the LightRevealScrim's reveal effect and amount from legacy code to the + * new KeyguardTransitionRepository. + */ + @JvmField + val LIGHT_REVEAL_MIGRATION = unreleasedFlag(218, "light_reveal_migration", teamfood = true) + // 300 - power menu // TODO(b/254512600): Tracking Bug @JvmField val POWER_MENU_LITE = releasedFlag(300, "power_menu_lite") diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt index 796f2b44effc6..148792ba779b3 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt @@ -16,8 +16,11 @@ package com.android.systemui.keyguard.data.repository +import android.graphics.Point +import android.hardware.biometrics.BiometricSourceType import com.android.keyguard.KeyguardUpdateMonitor import com.android.keyguard.KeyguardUpdateMonitorCallback +import com.android.systemui.biometrics.AuthController import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow import com.android.systemui.common.shared.model.Position @@ -27,8 +30,8 @@ import com.android.systemui.doze.DozeMachine import com.android.systemui.doze.DozeTransitionCallback import com.android.systemui.doze.DozeTransitionListener import com.android.systemui.keyguard.WakefulnessLifecycle -import com.android.systemui.keyguard.WakefulnessLifecycle.Wakefulness import com.android.systemui.keyguard.shared.model.BiometricUnlockModel +import com.android.systemui.keyguard.shared.model.BiometricUnlockSource import com.android.systemui.keyguard.shared.model.DozeStateModel import com.android.systemui.keyguard.shared.model.DozeTransitionModel import com.android.systemui.keyguard.shared.model.StatusBarState @@ -88,8 +91,8 @@ interface KeyguardRepository { * enter to conserve battery when the device is locked and inactive. * * Note that it is possible for the system to be transitioning into doze while this flow still - * returns `false`. In order to account for that, observers should also use the [dozeAmount] - * flow to check if it's greater than `0` + * returns `false`. In order to account for that, observers should also use the + * [linearDozeAmount] flow to check if it's greater than `0` */ val isDozing: Flow @@ -111,7 +114,7 @@ interface KeyguardRepository { * happens during an animation/transition into doze mode. An observer would be wise to account * for both flows if needed. */ - val dozeAmount: Flow + val linearDozeAmount: Flow /** Doze state information, as it transitions */ val dozeTransitionModel: Flow @@ -120,11 +123,20 @@ interface KeyguardRepository { val statusBarState: Flow /** Observable for device wake/sleep state */ - val wakefulnessState: Flow + val wakefulness: Flow /** Observable for biometric unlock modes */ val biometricUnlockState: Flow + /** Approximate location on the screen of the fingerprint sensor. */ + val fingerprintSensorLocation: Flow + + /** Approximate location on the screen of the face unlock sensor/front facing camera. */ + val faceSensorLocation: Flow + + /** Source of the most recent biometric unlock, such as fingerprint or face. */ + val biometricUnlockSource: Flow + /** * Returns `true` if the keyguard is showing; `false` otherwise. * @@ -163,6 +175,7 @@ constructor( private val keyguardStateController: KeyguardStateController, private val keyguardUpdateMonitor: KeyguardUpdateMonitor, private val dozeTransitionListener: DozeTransitionListener, + private val authController: AuthController, ) : KeyguardRepository { private val _animateBottomAreaDozingTransitions = MutableStateFlow(false) override val animateBottomAreaDozingTransitions = @@ -281,11 +294,11 @@ constructor( } .distinctUntilChanged() - override val dozeAmount: Flow = conflatedCallbackFlow { + override val linearDozeAmount: Flow = conflatedCallbackFlow { val callback = object : StatusBarStateController.StateListener { override fun onDozeAmountChanged(linear: Float, eased: Float) { - trySendWithFailureLogging(eased, TAG, "updated dozeAmount") + trySendWithFailureLogging(linear, TAG, "updated dozeAmount") } } @@ -348,58 +361,139 @@ constructor( awaitClose { statusBarStateController.removeCallback(callback) } } - override val wakefulnessState: Flow = conflatedCallbackFlow { - val callback = - object : WakefulnessLifecycle.Observer { - override fun onStartedWakingUp() { - trySendWithFailureLogging( - WakefulnessModel.STARTING_TO_WAKE, - TAG, - "Wakefulness: starting to wake" - ) - } - override fun onFinishedWakingUp() { - trySendWithFailureLogging(WakefulnessModel.AWAKE, TAG, "Wakefulness: awake") - } - override fun onStartedGoingToSleep() { - trySendWithFailureLogging( - WakefulnessModel.STARTING_TO_SLEEP, - TAG, - "Wakefulness: starting to sleep" - ) - } - override fun onFinishedGoingToSleep() { - trySendWithFailureLogging(WakefulnessModel.ASLEEP, TAG, "Wakefulness: asleep") - } - } - wakefulnessLifecycle.addObserver(callback) - trySendWithFailureLogging( - wakefulnessIntToObject(wakefulnessLifecycle.getWakefulness()), - TAG, - "initial wakefulness state" - ) - - awaitClose { wakefulnessLifecycle.removeObserver(callback) } - } - override val biometricUnlockState: Flow = conflatedCallbackFlow { + fun dispatchUpdate() { + trySendWithFailureLogging( + biometricModeIntToObject(biometricUnlockController.mode), + TAG, + "biometric mode" + ) + } + val callback = object : BiometricUnlockController.BiometricModeListener { override fun onModeChanged(@WakeAndUnlockMode mode: Int) { - trySendWithFailureLogging(biometricModeIntToObject(mode), TAG, "biometric mode") + dispatchUpdate() + } + + override fun onResetMode() { + dispatchUpdate() } } biometricUnlockController.addBiometricModeListener(callback) - trySendWithFailureLogging( - biometricModeIntToObject(biometricUnlockController.getMode()), - TAG, - "initial biometric mode" - ) + dispatchUpdate() awaitClose { biometricUnlockController.removeBiometricModeListener(callback) } } + override val wakefulness: Flow = conflatedCallbackFlow { + val observer = + object : WakefulnessLifecycle.Observer { + override fun onStartedWakingUp() { + dispatchNewState() + } + + override fun onFinishedWakingUp() { + dispatchNewState() + } + + override fun onPostFinishedWakingUp() { + dispatchNewState() + } + + override fun onStartedGoingToSleep() { + dispatchNewState() + } + + override fun onFinishedGoingToSleep() { + dispatchNewState() + } + + private fun dispatchNewState() { + trySendWithFailureLogging( + WakefulnessModel.fromWakefulnessLifecycle(wakefulnessLifecycle), + TAG, + "updated wakefulness state" + ) + } + } + + wakefulnessLifecycle.addObserver(observer) + trySendWithFailureLogging( + WakefulnessModel.fromWakefulnessLifecycle(wakefulnessLifecycle), + TAG, + "initial wakefulness state" + ) + + awaitClose { wakefulnessLifecycle.removeObserver(observer) } + } + + override val fingerprintSensorLocation: Flow = conflatedCallbackFlow { + fun sendFpLocation() { + trySendWithFailureLogging( + authController.fingerprintSensorLocation, + TAG, + "AuthController.Callback#onFingerprintLocationChanged" + ) + } + + val callback = + object : AuthController.Callback { + override fun onFingerprintLocationChanged() { + sendFpLocation() + } + } + + authController.addCallback(callback) + sendFpLocation() + + awaitClose { authController.removeCallback(callback) } + } + + override val faceSensorLocation: Flow = conflatedCallbackFlow { + fun sendSensorLocation() { + trySendWithFailureLogging( + authController.faceSensorLocation, + TAG, + "AuthController.Callback#onFingerprintLocationChanged" + ) + } + + val callback = + object : AuthController.Callback { + override fun onFaceSensorLocationChanged() { + sendSensorLocation() + } + } + + authController.addCallback(callback) + sendSensorLocation() + + awaitClose { authController.removeCallback(callback) } + } + + override val biometricUnlockSource: Flow = conflatedCallbackFlow { + val callback = + object : KeyguardUpdateMonitorCallback() { + override fun onBiometricAuthenticated( + userId: Int, + biometricSourceType: BiometricSourceType?, + isStrongBiometric: Boolean + ) { + trySendWithFailureLogging( + BiometricUnlockSource.fromBiometricSourceType(biometricSourceType), + TAG, + "onBiometricAuthenticated" + ) + } + } + + keyguardUpdateMonitor.registerCallback(callback) + trySendWithFailureLogging(null, TAG, "initial value") + awaitClose { keyguardUpdateMonitor.removeCallback(callback) } + } + override fun setAnimateDozingTransitions(animate: Boolean) { _animateBottomAreaDozingTransitions.value = animate } @@ -423,16 +517,6 @@ constructor( } } - private fun wakefulnessIntToObject(@Wakefulness value: Int): WakefulnessModel { - return when (value) { - 0 -> WakefulnessModel.ASLEEP - 1 -> WakefulnessModel.STARTING_TO_WAKE - 2 -> WakefulnessModel.AWAKE - 3 -> WakefulnessModel.STARTING_TO_SLEEP - else -> throw IllegalArgumentException("Invalid Wakefulness value: $value") - } - } - private fun biometricModeIntToObject(@WakeAndUnlockMode value: Int): BiometricUnlockModel { return when (value) { 0 -> BiometricUnlockModel.NONE diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryModule.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryModule.kt index 0c725208e22dc..26f853f3ad1c8 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryModule.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryModule.kt @@ -27,4 +27,7 @@ interface KeyguardRepositoryModule { fun keyguardTransitionRepository( impl: KeyguardTransitionRepositoryImpl ): KeyguardTransitionRepository + + @Binds + fun lightRevealScrimRepository(impl: LightRevealScrimRepositoryImpl): LightRevealScrimRepository } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepository.kt new file mode 100644 index 0000000000000..a17481a9978b7 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepository.kt @@ -0,0 +1,149 @@ +/* + * 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. + */ + +@file:OptIn(ExperimentalCoroutinesApi::class) + +package com.android.systemui.keyguard.data.repository + +import android.content.Context +import android.graphics.Point +import com.android.systemui.R +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.keyguard.shared.model.BiometricUnlockModel +import com.android.systemui.keyguard.shared.model.BiometricUnlockSource +import com.android.systemui.keyguard.shared.model.WakeSleepReason +import com.android.systemui.statusbar.CircleReveal +import com.android.systemui.statusbar.LiftReveal +import com.android.systemui.statusbar.LightRevealEffect +import com.android.systemui.statusbar.PowerButtonReveal +import javax.inject.Inject +import kotlin.math.max +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.flatMapLatest +import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.flow.map + +val DEFAULT_REVEAL_EFFECT = LiftReveal + +/** + * Encapsulates state relevant to the light reveal scrim, the view used to reveal/hide screen + * contents during transitions between AOD and lockscreen/unlocked. + */ +interface LightRevealScrimRepository { + + /** + * The reveal effect that should be used for the next lock/unlock. We switch between either the + * biometric unlock effect (if wake and unlocking) or the non-biometric effect, and position it + * at the current screen position of the appropriate sensor. + */ + val revealEffect: Flow +} + +@SysUISingleton +class LightRevealScrimRepositoryImpl +@Inject +constructor( + keyguardRepository: KeyguardRepository, + val context: Context, +) : LightRevealScrimRepository { + + /** The reveal effect used if the device was locked/unlocked via the power button. */ + private val powerButtonReveal = + PowerButtonReveal( + context.resources + .getDimensionPixelSize(R.dimen.physical_power_button_center_screen_location_y) + .toFloat() + ) + + /** + * Reveal effect to use for a fingerprint unlock. This is reconstructed if the fingerprint + * sensor location on the screen (in pixels) changes due to configuration changes. + */ + private val fingerprintRevealEffect: Flow = + keyguardRepository.fingerprintSensorLocation.map { + it?.let { constructCircleRevealFromPoint(it) } + } + + /** + * Reveal effect to use for a face unlock. This is reconstructed if the face sensor/front camera + * location on the screen (in pixels) changes due to configuration changes. + */ + private val faceRevealEffect: Flow = + keyguardRepository.faceSensorLocation.map { it?.let { constructCircleRevealFromPoint(it) } } + + /** + * The reveal effect we'll use for the next biometric unlock animation. We switch between the + * fingerprint/face unlock effect flows depending on the biometric unlock source. + */ + private val biometricRevealEffect: Flow = + keyguardRepository.biometricUnlockSource.flatMapLatest { source -> + when (source) { + BiometricUnlockSource.FINGERPRINT_SENSOR -> fingerprintRevealEffect + BiometricUnlockSource.FACE_SENSOR -> faceRevealEffect + else -> flowOf(null) + } + } + + /** The reveal effect we'll use for the next non-biometric unlock (tap, power button, etc). */ + private val nonBiometricRevealEffect: Flow = + keyguardRepository.wakefulness.map { wakefulnessModel -> + val wakingUpFromPowerButton = + wakefulnessModel.isWakingUpOrAwake && + wakefulnessModel.lastWakeReason == WakeSleepReason.POWER_BUTTON + val sleepingFromPowerButton = + !wakefulnessModel.isWakingUpOrAwake && + wakefulnessModel.lastSleepReason == WakeSleepReason.POWER_BUTTON + + if (wakingUpFromPowerButton || sleepingFromPowerButton) { + powerButtonReveal + } else { + LiftReveal + } + } + + override val revealEffect = + combine( + keyguardRepository.biometricUnlockState, + biometricRevealEffect, + nonBiometricRevealEffect + ) { biometricUnlockState, biometricReveal, nonBiometricReveal -> + + // Use the biometric reveal for any flavor of wake and unlocking. + when (biometricUnlockState) { + BiometricUnlockModel.WAKE_AND_UNLOCK, + BiometricUnlockModel.WAKE_AND_UNLOCK_PULSING, + BiometricUnlockModel.WAKE_AND_UNLOCK_FROM_DREAM -> biometricReveal + else -> nonBiometricReveal + } + ?: DEFAULT_REVEAL_EFFECT + } + .distinctUntilChanged() + + private fun constructCircleRevealFromPoint(point: Point): LightRevealEffect { + return with(point) { + CircleReveal( + x, + y, + startRadius = 0, + endRadius = + max(max(x, context.display.width - x), max(y, context.display.height - y)), + ) + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AodLockscreenTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AodLockscreenTransitionInteractor.kt index 2dbacd5d3c693..9b193533805ef 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AodLockscreenTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/AodLockscreenTransitionInteractor.kt @@ -27,7 +27,6 @@ import com.android.systemui.keyguard.shared.model.TransitionInfo import com.android.systemui.util.kotlin.sample import javax.inject.Inject import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.flow.collect import kotlinx.coroutines.launch @SysUISingleton diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/DreamingToAodTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/DreamingToAodTransitionInteractor.kt index 9e2b7241ade22..e34981eabcac0 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/DreamingToAodTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/DreamingToAodTransitionInteractor.kt @@ -42,7 +42,7 @@ constructor( override fun start() { scope.launch { - keyguardInteractor.wakefulnessState + keyguardInteractor.wakefulnessModel .sample(keyguardTransitionInteractor.finishedKeyguardState, { a, b -> Pair(a, b) }) .collect { pair -> val (wakefulnessState, keyguardState) = pair diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/GoneAodTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/GoneAodTransitionInteractor.kt index 0e2a54c57bdb4..483041a1b2365 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/GoneAodTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/GoneAodTransitionInteractor.kt @@ -23,11 +23,10 @@ import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.shared.model.TransitionInfo -import com.android.systemui.keyguard.shared.model.WakefulnessModel +import com.android.systemui.keyguard.shared.model.WakefulnessState import com.android.systemui.util.kotlin.sample import javax.inject.Inject import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.flow.collect import kotlinx.coroutines.launch @SysUISingleton @@ -42,13 +41,13 @@ constructor( override fun start() { scope.launch { - keyguardInteractor.wakefulnessState + keyguardInteractor.wakefulnessModel .sample(keyguardTransitionInteractor.finishedKeyguardState, { a, b -> Pair(a, b) }) .collect { pair -> val (wakefulnessState, keyguardState) = pair if ( keyguardState == KeyguardState.GONE && - wakefulnessState == WakefulnessModel.STARTING_TO_SLEEP + wakefulnessState.state == WakefulnessState.STARTING_TO_SLEEP ) { keyguardTransitionRepository.startTransition( TransitionInfo( diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt index 7cfd117d8eb43..6912e1d3558e1 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt @@ -17,6 +17,7 @@ package com.android.systemui.keyguard.domain.interactor +import android.graphics.Point import com.android.systemui.dagger.SysUISingleton import com.android.systemui.keyguard.data.repository.KeyguardRepository import com.android.systemui.keyguard.shared.model.BiometricUnlockModel @@ -41,7 +42,7 @@ constructor( * The amount of doze the system is in, where `1.0` is fully dozing and `0.0` is not dozing at * all. */ - val dozeAmount: Flow = repository.dozeAmount + val dozeAmount: Flow = repository.linearDozeAmount /** Whether the system is in doze mode. */ val isDozing: Flow = repository.isDozing /** Doze transition information. */ @@ -58,7 +59,7 @@ constructor( /** Whether the bouncer is showing or not. */ val isBouncerShowing: Flow = repository.isBouncerShowing /** The device wake/sleep state */ - val wakefulnessState: Flow = repository.wakefulnessState + val wakefulnessModel: Flow = repository.wakefulness /** Observable for the [StatusBarState] */ val statusBarState: Flow = repository.statusBarState /** @@ -67,10 +68,15 @@ constructor( */ val biometricUnlockState: Flow = repository.biometricUnlockState + /** The approximate location on the screen of the fingerprint sensor, if one is available. */ + val fingerprintSensorLocation: Flow = repository.fingerprintSensorLocation + + /** The approximate location on the screen of the face unlock sensor, if one is available. */ + val faceSensorLocation: Flow = repository.faceSensorLocation + fun dozeTransitionTo(state: DozeStateModel): Flow { return dozeTransitionModel.filter { it.to == state } } - fun isKeyguardShowing(): Boolean { return repository.isKeyguardShowing() } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionAuditLogger.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionAuditLogger.kt index 58a8093d49d23..e30e7f6ece110 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionAuditLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionAuditLogger.kt @@ -37,7 +37,7 @@ constructor( fun start() { scope.launch { - keyguardInteractor.wakefulnessState.collect { logger.v("WakefulnessState", it) } + keyguardInteractor.wakefulnessModel.collect { logger.v("WakefulnessModel", it) } } scope.launch { diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractor.kt new file mode 100644 index 0000000000000..6e25200bc2f64 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractor.kt @@ -0,0 +1,95 @@ +/* + * 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.keyguard.domain.interactor + +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository +import com.android.systemui.keyguard.data.repository.LightRevealScrimRepository +import com.android.systemui.keyguard.shared.model.KeyguardState +import com.android.systemui.keyguard.shared.model.TransitionStep +import com.android.systemui.statusbar.LightRevealEffect +import com.android.systemui.util.kotlin.sample +import javax.inject.Inject +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.filter +import kotlinx.coroutines.flow.map + +@ExperimentalCoroutinesApi +@SysUISingleton +class LightRevealScrimInteractor +@Inject +constructor( + transitionRepository: KeyguardTransitionRepository, + transitionInteractor: KeyguardTransitionInteractor, + lightRevealScrimRepository: LightRevealScrimRepository, +) { + + /** + * Whenever a keyguard transition starts, sample the latest reveal effect from the repository + * and use that for the starting transition. + * + * We can't simply use the nextRevealEffect since the effect may change midway through a + * transition, but we don't want to change effects part way through. For example, if we're using + * a CircleReveal to animate a biometric unlock, but the biometric unlock mode changes to NONE + * from WAKE_AND_UNLOCK before the unlock animation ends, we don't want to end up switching to a + * LiftReveal. + */ + val lightRevealEffect: Flow = + transitionInteractor.startedKeyguardTransitionStep.sample( + lightRevealScrimRepository.revealEffect + ) + + /** + * The reveal amount to use for the light reveal scrim, which is derived from the keyguard + * transition steps. + */ + val revealAmount: Flow = + transitionRepository.transitions + // Only listen to transitions that change the reveal amount. + .filter { willTransitionAffectRevealAmount(it) } + // Use the transition amount as the reveal amount, inverting it if we're transitioning + // to a non-revealed (hidden) state. + .map { step -> if (willBeRevealedInState(step.to)) step.value else 1f - step.value } + + companion object { + + /** + * Whether the transition requires a change in the reveal amount of the light reveal scrim. + * If not, we don't care about the transition and don't need to listen to it. + */ + fun willTransitionAffectRevealAmount(transition: TransitionStep): Boolean { + return willBeRevealedInState(transition.from) != willBeRevealedInState(transition.to) + } + + /** + * Whether the light reveal scrim will be fully revealed (revealAmount = 1.0f) in the given + * state after the transition is complete. If false, scrim will be fully hidden. + */ + fun willBeRevealedInState(state: KeyguardState): Boolean { + return when (state) { + KeyguardState.OFF -> false + KeyguardState.DOZING -> false + KeyguardState.AOD -> false + KeyguardState.DREAMING -> true + KeyguardState.BOUNCER -> true + KeyguardState.LOCKSCREEN -> true + KeyguardState.GONE -> true + } + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LockscreenBouncerTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LockscreenBouncerTransitionInteractor.kt index 3bb8241257cc0..3218f9699f350 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LockscreenBouncerTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/LockscreenBouncerTransitionInteractor.kt @@ -25,7 +25,7 @@ import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.shared.model.StatusBarState.SHADE_LOCKED import com.android.systemui.keyguard.shared.model.TransitionInfo import com.android.systemui.keyguard.shared.model.TransitionState -import com.android.systemui.keyguard.shared.model.WakefulnessModel +import com.android.systemui.keyguard.shared.model.WakefulnessState import com.android.systemui.shade.data.repository.ShadeRepository import com.android.systemui.util.kotlin.sample import java.util.UUID @@ -58,22 +58,26 @@ constructor( keyguardInteractor.isBouncerShowing .sample( combine( - keyguardInteractor.wakefulnessState, + keyguardInteractor.wakefulnessModel, keyguardTransitionInteractor.startedKeyguardTransitionStep, - ) { a, b -> - Pair(a, b) - }, - { a, bc -> Triple(a, bc.first, bc.second) } - ) - .collect { triple -> - val (isBouncerShowing, wakefulnessState, lastStartedTransitionStep) = triple + ) { wakefulnessModel, transitionStep -> + Pair(wakefulnessModel, transitionStep) + } + ) { bouncerShowing, wakefulnessAndTransition -> + Triple( + bouncerShowing, + wakefulnessAndTransition.first, + wakefulnessAndTransition.second + ) + } + .collect { (isBouncerShowing, wakefulnessState, lastStartedTransitionStep) -> if ( !isBouncerShowing && lastStartedTransitionStep.to == KeyguardState.BOUNCER ) { val to = if ( - wakefulnessState == WakefulnessModel.STARTING_TO_SLEEP || - wakefulnessState == WakefulnessModel.ASLEEP + wakefulnessState.state == WakefulnessState.STARTING_TO_SLEEP || + wakefulnessState.state == WakefulnessState.ASLEEP ) { KeyguardState.AOD } else { @@ -100,14 +104,17 @@ constructor( combine( keyguardTransitionInteractor.finishedKeyguardState, keyguardInteractor.statusBarState, - ) { a, b -> - Pair(a, b) - }, - { a, bc -> Triple(a, bc.first, bc.second) } - ) - .collect { triple -> - val (shadeModel, keyguardState, statusBarState) = triple - + ) { finishedKeyguardState, statusBarState -> + Pair(finishedKeyguardState, statusBarState) + } + ) { shadeModel, keyguardStateAndStatusBarState -> + Triple( + shadeModel, + keyguardStateAndStatusBarState.first, + keyguardStateAndStatusBarState.second + ) + } + .collect { (shadeModel, keyguardState, statusBarState) -> val id = transitionId if (id != null) { // An existing `id` means a transition is started, and calls to diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/BiometricUnlockSource.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/BiometricUnlockSource.kt new file mode 100644 index 0000000000000..b403416c572c4 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/BiometricUnlockSource.kt @@ -0,0 +1,39 @@ +/* + * 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.keyguard.shared.model + +import android.hardware.biometrics.BiometricSourceType + +/** Biometric unlock sensor sources, which we use to play sensor-specific animations. */ +enum class BiometricUnlockSource { + /** The unlock was initiated by a fingerprint sensor authentication. */ + FINGERPRINT_SENSOR, + + /** The unlock was initiated by the front-facing camera or a nearby sensor. */ + FACE_SENSOR; + + companion object { + fun fromBiometricSourceType(type: BiometricSourceType?): BiometricUnlockSource? { + return when (type) { + BiometricSourceType.FINGERPRINT -> FINGERPRINT_SENSOR + BiometricSourceType.FACE -> FACE_SENSOR + BiometricSourceType.IRIS -> FACE_SENSOR + else -> null + } + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/WakeSleepReason.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/WakeSleepReason.kt new file mode 100644 index 0000000000000..b32597d5cff0b --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/WakeSleepReason.kt @@ -0,0 +1,44 @@ +/* + * 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.keyguard.shared.model + +import android.os.PowerManager + +/** The reason we're waking up or going to sleep, such as pressing the power button. */ +enum class WakeSleepReason { + /** The physical power button was pressed to wake up or sleep the device. */ + POWER_BUTTON, + + /** Something else happened to wake up or sleep the device. */ + OTHER; + + companion object { + fun fromPowerManagerWakeReason(reason: Int): WakeSleepReason { + return when (reason) { + PowerManager.WAKE_REASON_POWER_BUTTON -> POWER_BUTTON + else -> OTHER + } + } + + fun fromPowerManagerSleepReason(reason: Int): WakeSleepReason { + return when (reason) { + PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON -> POWER_BUTTON + else -> OTHER + } + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/WakefulnessModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/WakefulnessModel.kt index 92040f4f03481..03dee0045c108 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/WakefulnessModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/WakefulnessModel.kt @@ -15,24 +15,34 @@ */ package com.android.systemui.keyguard.shared.model -/** Model device wakefulness states. */ -enum class WakefulnessModel { - /** The device is asleep and not interactive. */ - ASLEEP, - /** Received a signal that the device is beginning to wake up. */ - STARTING_TO_WAKE, - /** Device is now fully awake and interactive. */ - AWAKE, - /** Signal that the device is now going to sleep. */ - STARTING_TO_SLEEP; +import com.android.systemui.keyguard.WakefulnessLifecycle +/** Model device wakefulness states. */ +data class WakefulnessModel( + val state: WakefulnessState, + val isWakingUpOrAwake: Boolean, + val lastWakeReason: WakeSleepReason, + val lastSleepReason: WakeSleepReason, +) { companion object { fun isSleepingOrStartingToSleep(model: WakefulnessModel): Boolean { - return model == ASLEEP || model == STARTING_TO_SLEEP + return model.state == WakefulnessState.ASLEEP || + model.state == WakefulnessState.STARTING_TO_SLEEP } fun isWakingOrStartingToWake(model: WakefulnessModel): Boolean { - return model == AWAKE || model == STARTING_TO_WAKE + return model.state == WakefulnessState.AWAKE || + model.state == WakefulnessState.STARTING_TO_WAKE + } + + fun fromWakefulnessLifecycle(wakefulnessLifecycle: WakefulnessLifecycle): WakefulnessModel { + return WakefulnessModel( + WakefulnessState.fromWakefulnessLifecycleInt(wakefulnessLifecycle.wakefulness), + wakefulnessLifecycle.wakefulness == WakefulnessLifecycle.WAKEFULNESS_WAKING || + wakefulnessLifecycle.wakefulness == WakefulnessLifecycle.WAKEFULNESS_AWAKE, + WakeSleepReason.fromPowerManagerWakeReason(wakefulnessLifecycle.lastWakeReason), + WakeSleepReason.fromPowerManagerSleepReason(wakefulnessLifecycle.lastSleepReason), + ) } } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/WakefulnessState.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/WakefulnessState.kt new file mode 100644 index 0000000000000..6791d88f16d13 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/WakefulnessState.kt @@ -0,0 +1,44 @@ +/* + * 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.keyguard.shared.model + +import com.android.systemui.keyguard.WakefulnessLifecycle + +enum class WakefulnessState { + /** The device is asleep and not interactive. */ + ASLEEP, + /** Received a signal that the device is beginning to wake up. */ + STARTING_TO_WAKE, + /** Device is now fully awake and interactive. */ + AWAKE, + /** Signal that the device is now going to sleep. */ + STARTING_TO_SLEEP; + + companion object { + fun fromWakefulnessLifecycleInt( + @WakefulnessLifecycle.Wakefulness value: Int + ): WakefulnessState { + return when (value) { + WakefulnessLifecycle.WAKEFULNESS_ASLEEP -> ASLEEP + WakefulnessLifecycle.WAKEFULNESS_WAKING -> STARTING_TO_WAKE + WakefulnessLifecycle.WAKEFULNESS_AWAKE -> AWAKE + WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP -> STARTING_TO_SLEEP + else -> throw IllegalArgumentException("Invalid Wakefulness value: $value") + } + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/LightRevealScrimViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/LightRevealScrimViewBinder.kt new file mode 100644 index 0000000000000..f1da8826a22ce --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/LightRevealScrimViewBinder.kt @@ -0,0 +1,43 @@ +/* + * 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.keyguard.ui.binder + +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.repeatOnLifecycle +import com.android.systemui.keyguard.ui.viewmodel.LightRevealScrimViewModel +import com.android.systemui.lifecycle.repeatWhenAttached +import com.android.systemui.statusbar.LightRevealScrim +import kotlinx.coroutines.launch + +object LightRevealScrimViewBinder { + @JvmStatic + fun bind(revealScrim: LightRevealScrim, viewModel: LightRevealScrimViewModel) { + revealScrim.repeatWhenAttached { + repeatOnLifecycle(Lifecycle.State.CREATED) { + launch { + viewModel.revealAmount.collect { amount -> revealScrim.revealAmount = amount } + } + + launch { + viewModel.lightRevealEffect.collect { effect -> + revealScrim.revealEffect = effect + } + } + } + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LightRevealScrimViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LightRevealScrimViewModel.kt new file mode 100644 index 0000000000000..a46d441613acc --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LightRevealScrimViewModel.kt @@ -0,0 +1,31 @@ +/* + * 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.keyguard.ui.viewmodel + +import com.android.systemui.keyguard.domain.interactor.LightRevealScrimInteractor +import com.android.systemui.statusbar.LightRevealEffect +import javax.inject.Inject +import kotlinx.coroutines.flow.Flow + +/** + * Models UI state for the light reveal scrim, which is used during screen on and off animations to + * draw a gradient that reveals/hides the contents of the screen. + */ +class LightRevealScrimViewModel @Inject constructor(interactor: LightRevealScrimInteractor) { + val lightRevealEffect: Flow = interactor.lightRevealEffect + val revealAmount: Flow = interactor.revealAmount +} 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 679bcea00f745..556431114ff15 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java @@ -514,7 +514,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp && mPendingAuthenticated.userId == KeyguardUpdateMonitor.getCurrentUser(); } - public int getMode() { + public @WakeAndUnlockMode int getMode() { return mMode; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java index 00a9916f5ac15..2d48ffcf98103 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java @@ -160,6 +160,8 @@ import com.android.systemui.keyguard.KeyguardUnlockAnimationController; import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.keyguard.ScreenLifecycle; import com.android.systemui.keyguard.WakefulnessLifecycle; +import com.android.systemui.keyguard.ui.binder.LightRevealScrimViewBinder; +import com.android.systemui.keyguard.ui.viewmodel.LightRevealScrimViewModel; import com.android.systemui.navigationbar.NavigationBarController; import com.android.systemui.navigationbar.NavigationBarView; import com.android.systemui.plugins.DarkIconDispatcher; @@ -491,6 +493,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces { private final OngoingCallController mOngoingCallController; private final StatusBarSignalPolicy mStatusBarSignalPolicy; private final StatusBarHideIconsForBouncerManager mStatusBarHideIconsForBouncerManager; + private final Lazy mLightRevealScrimViewModelLazy; /** Controller for the Shade. */ @VisibleForTesting @@ -757,7 +760,8 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces { DeviceStateManager deviceStateManager, WiredChargingRippleController wiredChargingRippleController, IDreamManager dreamManager, - Lazy cameraLauncherLazy) { + Lazy cameraLauncherLazy, + Lazy lightRevealScrimViewModelLazy) { mContext = context; mNotificationsController = notificationsController; mFragmentService = fragmentService; @@ -871,6 +875,8 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces { deviceStateManager.registerCallback(mMainExecutor, new FoldStateListener(mContext, this::onFoldedStateChanged)); wiredChargingRippleController.registerCallbacks(); + + mLightRevealScrimViewModelLazy = lightRevealScrimViewModelLazy; } @Override @@ -1000,6 +1006,12 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces { @Override public void onKeyguardGoingAwayChanged() { + if (mFeatureFlags.isEnabled(Flags.LIGHT_REVEAL_MIGRATION)) { + // This code path is not used if the KeyguardTransitionRepository is managing + // the lightreveal scrim. + return; + } + // The light reveal scrim should always be fully revealed by the time the keyguard // is done going away. Double check that this is true. if (!mKeyguardStateController.isKeyguardGoingAway()) { @@ -1236,6 +1248,12 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces { mScrimController.attachViews(scrimBehind, notificationsScrim, scrimInFront); mLightRevealScrim = mNotificationShadeWindowView.findViewById(R.id.light_reveal_scrim); + + if (mFeatureFlags.isEnabled(Flags.LIGHT_REVEAL_MIGRATION)) { + LightRevealScrimViewBinder.bind( + mLightRevealScrim, mLightRevealScrimViewModelLazy.get()); + } + mLightRevealScrim.setScrimOpaqueChangedListener((opaque) -> { Runnable updateOpaqueness = () -> { mNotificationShadeWindowController.setLightRevealScrimOpaque( @@ -3308,6 +3326,10 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces { return; } + if (mFeatureFlags.isEnabled(Flags.LIGHT_REVEAL_MIGRATION)) { + return; + } + final boolean wakingUpFromPowerButton = wakingUp && !(mLightRevealScrim.getRevealEffect() instanceof CircleReveal) && mWakefulnessLifecycle.getLastWakeReason() @@ -4072,7 +4094,9 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces { return; } - mLightRevealScrim.setAlpha(mScrimController.getState().getMaxLightRevealScrimAlpha()); + if (!mFeatureFlags.isEnabled(Flags.LIGHT_REVEAL_MIGRATION)) { + mLightRevealScrim.setAlpha(mScrimController.getState().getMaxLightRevealScrimAlpha()); + } } @Override @@ -4253,6 +4277,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces { @Override public void onDozeAmountChanged(float linear, float eased) { if (mFeatureFlags.isEnabled(Flags.LOCKSCREEN_ANIMATIONS) + && !mFeatureFlags.isEnabled(Flags.LIGHT_REVEAL_MIGRATION) && !(mLightRevealScrim.getRevealEffect() instanceof CircleReveal)) { mLightRevealScrim.setRevealAmount(1f - linear); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt index eb8c823ffe1c2..b765ab3c5eac6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthRippleControllerTest.kt @@ -26,6 +26,7 @@ import com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession import com.android.keyguard.KeyguardUpdateMonitor import com.android.keyguard.KeyguardUpdateMonitorCallback import com.android.systemui.SysuiTestCase +import com.android.systemui.flags.FeatureFlags import com.android.systemui.keyguard.WakefulnessLifecycle import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.statusbar.LightRevealScrim @@ -77,6 +78,7 @@ class AuthRippleControllerTest : SysuiTestCase() { @Mock private lateinit var udfpsControllerProvider: Provider @Mock private lateinit var udfpsController: UdfpsController @Mock private lateinit var statusBarStateController: StatusBarStateController + @Mock private lateinit var featureFlags: FeatureFlags @Mock private lateinit var lightRevealScrim: LightRevealScrim @Mock private lateinit var fpSensorProp: FingerprintSensorPropertiesInternal @@ -106,6 +108,7 @@ class AuthRippleControllerTest : SysuiTestCase() { biometricUnlockController, udfpsControllerProvider, statusBarStateController, + featureFlags, rippleView ) controller.init() diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt index 13fc9fcf834bf..5deac1924ab78 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt @@ -16,10 +16,13 @@ package com.android.systemui.keyguard.data.repository +import android.graphics.Point +import android.hardware.biometrics.BiometricSourceType import androidx.test.filters.SmallTest import com.android.keyguard.KeyguardUpdateMonitor import com.android.keyguard.KeyguardUpdateMonitorCallback import com.android.systemui.SysuiTestCase +import com.android.systemui.biometrics.AuthController import com.android.systemui.common.shared.model.Position import com.android.systemui.doze.DozeHost import com.android.systemui.doze.DozeMachine @@ -27,9 +30,11 @@ import com.android.systemui.doze.DozeTransitionCallback import com.android.systemui.doze.DozeTransitionListener import com.android.systemui.keyguard.WakefulnessLifecycle import com.android.systemui.keyguard.shared.model.BiometricUnlockModel +import com.android.systemui.keyguard.shared.model.BiometricUnlockSource import com.android.systemui.keyguard.shared.model.DozeStateModel import com.android.systemui.keyguard.shared.model.DozeTransitionModel import com.android.systemui.keyguard.shared.model.WakefulnessModel +import com.android.systemui.keyguard.shared.model.WakefulnessState import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.statusbar.phone.BiometricUnlockController import com.android.systemui.statusbar.policy.KeyguardStateController @@ -57,9 +62,10 @@ class KeyguardRepositoryImplTest : SysuiTestCase() { @Mock private lateinit var dozeHost: DozeHost @Mock private lateinit var keyguardStateController: KeyguardStateController @Mock private lateinit var wakefulnessLifecycle: WakefulnessLifecycle - @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor @Mock private lateinit var biometricUnlockController: BiometricUnlockController @Mock private lateinit var dozeTransitionListener: DozeTransitionListener + @Mock private lateinit var authController: AuthController + @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor private lateinit var underTest: KeyguardRepositoryImpl @@ -76,6 +82,7 @@ class KeyguardRepositoryImplTest : SysuiTestCase() { keyguardStateController, keyguardUpdateMonitor, dozeTransitionListener, + authController, ) } @@ -198,7 +205,7 @@ class KeyguardRepositoryImplTest : SysuiTestCase() { fun dozeAmount() = runTest(UnconfinedTestDispatcher()) { val values = mutableListOf() - val job = underTest.dozeAmount.onEach(values::add).launchIn(this) + val job = underTest.linearDozeAmount.onEach(values::add).launchIn(this) val captor = argumentCaptor() verify(statusBarStateController).addCallback(captor.capture()) @@ -207,7 +214,7 @@ class KeyguardRepositoryImplTest : SysuiTestCase() { captor.value.onDozeAmountChanged(0.498f, 0.5f) captor.value.onDozeAmountChanged(0.661f, 0.65f) - assertThat(values).isEqualTo(listOf(0f, 0.4f, 0.5f, 0.65f)) + assertThat(values).isEqualTo(listOf(0f, 0.433f, 0.498f, 0.661f)) job.cancel() verify(statusBarStateController).removeCallback(captor.value) @@ -217,25 +224,36 @@ class KeyguardRepositoryImplTest : SysuiTestCase() { fun wakefulness() = runTest(UnconfinedTestDispatcher()) { val values = mutableListOf() - val job = underTest.wakefulnessState.onEach(values::add).launchIn(this) + val job = underTest.wakefulness.onEach(values::add).launchIn(this) val captor = argumentCaptor() verify(wakefulnessLifecycle).addObserver(captor.capture()) + whenever(wakefulnessLifecycle.wakefulness) + .thenReturn(WakefulnessLifecycle.WAKEFULNESS_WAKING) captor.value.onStartedWakingUp() + + whenever(wakefulnessLifecycle.wakefulness) + .thenReturn(WakefulnessLifecycle.WAKEFULNESS_AWAKE) captor.value.onFinishedWakingUp() + + whenever(wakefulnessLifecycle.wakefulness) + .thenReturn(WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP) captor.value.onStartedGoingToSleep() + + whenever(wakefulnessLifecycle.wakefulness) + .thenReturn(WakefulnessLifecycle.WAKEFULNESS_ASLEEP) captor.value.onFinishedGoingToSleep() - assertThat(values) + assertThat(values.map { it.state }) .isEqualTo( listOf( // Initial value will be ASLEEP - WakefulnessModel.ASLEEP, - WakefulnessModel.STARTING_TO_WAKE, - WakefulnessModel.AWAKE, - WakefulnessModel.STARTING_TO_SLEEP, - WakefulnessModel.ASLEEP, + WakefulnessState.ASLEEP, + WakefulnessState.STARTING_TO_WAKE, + WakefulnessState.AWAKE, + WakefulnessState.STARTING_TO_SLEEP, + WakefulnessState.ASLEEP, ) ) @@ -329,14 +347,20 @@ class KeyguardRepositoryImplTest : SysuiTestCase() { val captor = argumentCaptor() verify(biometricUnlockController).addBiometricModeListener(captor.capture()) - captor.value.onModeChanged(BiometricUnlockController.MODE_NONE) - captor.value.onModeChanged(BiometricUnlockController.MODE_WAKE_AND_UNLOCK) - captor.value.onModeChanged(BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING) - captor.value.onModeChanged(BiometricUnlockController.MODE_SHOW_BOUNCER) - captor.value.onModeChanged(BiometricUnlockController.MODE_ONLY_WAKE) - captor.value.onModeChanged(BiometricUnlockController.MODE_UNLOCK_COLLAPSING) - captor.value.onModeChanged(BiometricUnlockController.MODE_DISMISS_BOUNCER) - captor.value.onModeChanged(BiometricUnlockController.MODE_WAKE_AND_UNLOCK_FROM_DREAM) + listOf( + BiometricUnlockController.MODE_NONE, + BiometricUnlockController.MODE_WAKE_AND_UNLOCK, + BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING, + BiometricUnlockController.MODE_SHOW_BOUNCER, + BiometricUnlockController.MODE_ONLY_WAKE, + BiometricUnlockController.MODE_UNLOCK_COLLAPSING, + BiometricUnlockController.MODE_DISMISS_BOUNCER, + BiometricUnlockController.MODE_WAKE_AND_UNLOCK_FROM_DREAM, + ) + .forEach { + whenever(biometricUnlockController.mode).thenReturn(it) + captor.value.onModeChanged(it) + } assertThat(values) .isEqualTo( @@ -420,4 +444,104 @@ class KeyguardRepositoryImplTest : SysuiTestCase() { job.cancel() verify(dozeTransitionListener).removeCallback(listener) } + + @Test + fun fingerprintSensorLocation() = + runTest(UnconfinedTestDispatcher()) { + val values = mutableListOf() + val job = underTest.fingerprintSensorLocation.onEach(values::add).launchIn(this) + + val captor = argumentCaptor() + verify(authController).addCallback(captor.capture()) + + // An initial, null value should be initially emitted so that flows combined with this + // one + // emit values immediately. The sensor location is expected to be nullable, so anyone + // consuming it should handle that properly. + assertThat(values).isEqualTo(listOf(null)) + + listOf(Point(500, 500), Point(0, 0), null, Point(250, 250)) + .onEach { + whenever(authController.fingerprintSensorLocation).thenReturn(it) + captor.value.onFingerprintLocationChanged() + } + .also { dispatchedSensorLocations -> + assertThat(values).isEqualTo(listOf(null) + dispatchedSensorLocations) + } + + job.cancel() + } + + @Test + fun faceSensorLocation() = + runTest(UnconfinedTestDispatcher()) { + val values = mutableListOf() + val job = underTest.faceSensorLocation.onEach(values::add).launchIn(this) + + val captor = argumentCaptor() + verify(authController).addCallback(captor.capture()) + + // An initial, null value should be initially emitted so that flows combined with this + // one + // emit values immediately. The sensor location is expected to be nullable, so anyone + // consuming it should handle that properly. + assertThat(values).isEqualTo(listOf(null)) + + listOf( + Point(500, 500), + Point(0, 0), + null, + Point(250, 250), + ) + .onEach { + whenever(authController.faceSensorLocation).thenReturn(it) + captor.value.onFaceSensorLocationChanged() + } + .also { dispatchedSensorLocations -> + assertThat(values).isEqualTo(listOf(null) + dispatchedSensorLocations) + } + + job.cancel() + } + + @Test + fun biometricUnlockSource() = + runTest(UnconfinedTestDispatcher()) { + val values = mutableListOf() + val job = underTest.biometricUnlockSource.onEach(values::add).launchIn(this) + + val captor = argumentCaptor() + verify(keyguardUpdateMonitor).registerCallback(captor.capture()) + + // An initial, null value should be initially emitted so that flows combined with this + // one + // emit values immediately. The biometric unlock source is expected to be nullable, so + // anyone consuming it should handle that properly. + assertThat(values).isEqualTo(listOf(null)) + + listOf( + BiometricSourceType.FINGERPRINT, + BiometricSourceType.IRIS, + null, + BiometricSourceType.FACE, + BiometricSourceType.FINGERPRINT, + ) + .onEach { biometricSourceType -> + captor.value.onBiometricAuthenticated(0, biometricSourceType, false) + } + + assertThat(values) + .isEqualTo( + listOf( + null, + BiometricUnlockSource.FINGERPRINT_SENSOR, + BiometricUnlockSource.FACE_SENSOR, + null, + BiometricUnlockSource.FACE_SENSOR, + BiometricUnlockSource.FINGERPRINT_SENSOR, + ) + ) + + job.cancel() + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepositoryTest.kt new file mode 100644 index 0000000000000..d2db910ad4431 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/LightRevealScrimRepositoryTest.kt @@ -0,0 +1,167 @@ +/* + * 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.keyguard.data.repository + +import android.graphics.Point +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.keyguard.shared.model.BiometricUnlockModel +import com.android.systemui.keyguard.shared.model.BiometricUnlockSource +import com.android.systemui.statusbar.CircleReveal +import com.android.systemui.statusbar.LightRevealEffect +import junit.framework.Assert.assertEquals +import junit.framework.Assert.assertFalse +import kotlinx.coroutines.launch +import kotlinx.coroutines.test.runCurrent +import kotlinx.coroutines.test.runTest +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 +import org.mockito.MockitoAnnotations + +@SmallTest +@RunWith(JUnit4::class) +class LightRevealScrimRepositoryTest : SysuiTestCase() { + private lateinit var fakeKeyguardRepository: FakeKeyguardRepository + private lateinit var underTest: LightRevealScrimRepositoryImpl + + @Before + fun setUp() { + MockitoAnnotations.initMocks(this) + fakeKeyguardRepository = FakeKeyguardRepository() + underTest = LightRevealScrimRepositoryImpl(fakeKeyguardRepository, context) + } + + @Test + fun `nextRevealEffect - effect switches between default and biometric with no dupes`() = + runTest { + val values = mutableListOf() + val job = launch { underTest.revealEffect.collect { values.add(it) } } + + // We should initially emit the default reveal effect. + runCurrent() + values.assertEffectsMatchPredicates({ it == DEFAULT_REVEAL_EFFECT }) + + // The source and sensor locations are still null, so we should still be using the + // default reveal despite a biometric unlock. + fakeKeyguardRepository.setBiometricUnlockState(BiometricUnlockModel.WAKE_AND_UNLOCK) + + runCurrent() + values.assertEffectsMatchPredicates({ it == DEFAULT_REVEAL_EFFECT },) + + // We got a source but still have no sensor locations, so should be sticking with + // the default effect. + fakeKeyguardRepository.setBiometricUnlockSource( + BiometricUnlockSource.FINGERPRINT_SENSOR + ) + + runCurrent() + values.assertEffectsMatchPredicates({ it == DEFAULT_REVEAL_EFFECT },) + + // We got a location for the face sensor, but we unlocked with fingerprint. + val faceLocation = Point(250, 0) + fakeKeyguardRepository.setFaceSensorLocation(faceLocation) + + runCurrent() + values.assertEffectsMatchPredicates({ it == DEFAULT_REVEAL_EFFECT },) + + // Now we have fingerprint sensor locations, and wake and unlock via fingerprint. + val fingerprintLocation = Point(500, 500) + fakeKeyguardRepository.setFingerprintSensorLocation(fingerprintLocation) + fakeKeyguardRepository.setBiometricUnlockSource( + BiometricUnlockSource.FINGERPRINT_SENSOR + ) + fakeKeyguardRepository.setBiometricUnlockState( + BiometricUnlockModel.WAKE_AND_UNLOCK_PULSING + ) + + // We should now have switched to the circle reveal, at the fingerprint location. + runCurrent() + values.assertEffectsMatchPredicates( + { it == DEFAULT_REVEAL_EFFECT }, + { + it is CircleReveal && + it.centerX == fingerprintLocation.x && + it.centerY == fingerprintLocation.y + }, + ) + + // Subsequent wake and unlocks should not emit duplicate, identical CircleReveals. + val valuesPrevSize = values.size + fakeKeyguardRepository.setBiometricUnlockState( + BiometricUnlockModel.WAKE_AND_UNLOCK_PULSING + ) + fakeKeyguardRepository.setBiometricUnlockState( + BiometricUnlockModel.WAKE_AND_UNLOCK_FROM_DREAM + ) + assertEquals(valuesPrevSize, values.size) + + // Non-biometric unlock, we should return to the default reveal. + fakeKeyguardRepository.setBiometricUnlockState(BiometricUnlockModel.NONE) + + runCurrent() + values.assertEffectsMatchPredicates( + { it == DEFAULT_REVEAL_EFFECT }, + { + it is CircleReveal && + it.centerX == fingerprintLocation.x && + it.centerY == fingerprintLocation.y + }, + { it == DEFAULT_REVEAL_EFFECT }, + ) + + // We already have a face location, so switching to face source should update the + // CircleReveal. + fakeKeyguardRepository.setBiometricUnlockSource(BiometricUnlockSource.FACE_SENSOR) + runCurrent() + fakeKeyguardRepository.setBiometricUnlockState(BiometricUnlockModel.WAKE_AND_UNLOCK) + runCurrent() + + values.assertEffectsMatchPredicates( + { it == DEFAULT_REVEAL_EFFECT }, + { + it is CircleReveal && + it.centerX == fingerprintLocation.x && + it.centerY == fingerprintLocation.y + }, + { it == DEFAULT_REVEAL_EFFECT }, + { + it is CircleReveal && + it.centerX == faceLocation.x && + it.centerY == faceLocation.y + }, + ) + + job.cancel() + } + + /** + * Asserts that the list of LightRevealEffects satisfies the list of predicates, in order, with + * no leftover elements. + */ + private fun List.assertEffectsMatchPredicates( + vararg predicates: (LightRevealEffect) -> Boolean + ) { + println(this) + assertEquals(predicates.size, this.size) + + assertFalse( + zip(predicates) { effect, predicate -> predicate(effect) }.any { matched -> !matched } + ) + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractorTest.kt new file mode 100644 index 0000000000000..31662145dfbe4 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/LightRevealScrimInteractorTest.kt @@ -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.systemui.keyguard.domain.interactor + +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository +import com.android.systemui.keyguard.data.repository.FakeLightRevealScrimRepository +import com.android.systemui.keyguard.shared.model.KeyguardState +import com.android.systemui.keyguard.shared.model.TransitionState +import com.android.systemui.keyguard.shared.model.TransitionStep +import com.android.systemui.statusbar.LightRevealEffect +import com.android.systemui.statusbar.LightRevealScrim +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.test.UnconfinedTestDispatcher +import kotlinx.coroutines.test.runTest +import org.junit.Assert.assertEquals +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 +import org.mockito.MockitoAnnotations + +@SmallTest +@RunWith(JUnit4::class) +class LightRevealScrimInteractorTest : SysuiTestCase() { + private val fakeKeyguardTransitionRepository = FakeKeyguardTransitionRepository() + private val fakeLightRevealScrimRepository = FakeLightRevealScrimRepository() + + private val keyguardTransitionInteractor = + KeyguardTransitionInteractor(fakeKeyguardTransitionRepository) + + private lateinit var underTest: LightRevealScrimInteractor + + private val reveal1 = + object : LightRevealEffect { + override fun setRevealAmountOnScrim(amount: Float, scrim: LightRevealScrim) {} + } + + private val reveal2 = + object : LightRevealEffect { + override fun setRevealAmountOnScrim(amount: Float, scrim: LightRevealScrim) {} + } + + @Before + fun setUp() { + MockitoAnnotations.initMocks(this) + underTest = + LightRevealScrimInteractor( + fakeKeyguardTransitionRepository, + keyguardTransitionInteractor, + fakeLightRevealScrimRepository + ) + } + + @Test + fun `lightRevealEffect - does not change during keyguard transition`() = + runTest(UnconfinedTestDispatcher()) { + val values = mutableListOf() + val job = underTest.lightRevealEffect.onEach(values::add).launchIn(this) + + fakeLightRevealScrimRepository.setRevealEffect(reveal1) + + // The reveal effect shouldn't emit anything until a keyguard transition starts. + assertEquals(values.size, 0) + + // Once it starts, it should emit reveal1. + fakeKeyguardTransitionRepository.sendTransitionStep( + TransitionStep(transitionState = TransitionState.STARTED) + ) + assertEquals(values, listOf(reveal1)) + + // Until the next transition starts, reveal2 should not be emitted. + fakeLightRevealScrimRepository.setRevealEffect(reveal2) + fakeKeyguardTransitionRepository.sendTransitionStep( + TransitionStep(transitionState = TransitionState.RUNNING) + ) + fakeKeyguardTransitionRepository.sendTransitionStep( + TransitionStep(transitionState = TransitionState.FINISHED) + ) + assertEquals(values, listOf(reveal1)) + fakeKeyguardTransitionRepository.sendTransitionStep( + TransitionStep(transitionState = TransitionState.STARTED) + ) + assertEquals(values, listOf(reveal1, reveal2)) + + job.cancel() + } + + @Test + fun `revealAmount - inverted when appropriate`() = + runTest(UnconfinedTestDispatcher()) { + val values = mutableListOf() + val job = underTest.revealAmount.onEach(values::add).launchIn(this) + + fakeKeyguardTransitionRepository.sendTransitionStep( + TransitionStep( + from = KeyguardState.AOD, + to = KeyguardState.LOCKSCREEN, + value = 0.3f + ) + ) + + assertEquals(values, listOf(0.3f)) + + fakeKeyguardTransitionRepository.sendTransitionStep( + TransitionStep( + from = KeyguardState.LOCKSCREEN, + to = KeyguardState.AOD, + value = 0.3f + ) + ) + + assertEquals(values, listOf(0.3f, 0.7f)) + + job.cancel() + } + + @Test + fun `revealAmount - ignores transitions that do not affect reveal amount`() = + runTest(UnconfinedTestDispatcher()) { + val values = mutableListOf() + val job = underTest.revealAmount.onEach(values::add).launchIn(this) + + fakeKeyguardTransitionRepository.sendTransitionStep( + TransitionStep(from = KeyguardState.DOZING, to = KeyguardState.AOD, value = 0.3f) + ) + + assertEquals(values, emptyList()) + + fakeKeyguardTransitionRepository.sendTransitionStep( + TransitionStep(from = KeyguardState.AOD, to = KeyguardState.DOZING, value = 0.3f) + ) + + assertEquals(values, emptyList()) + + job.cancel() + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java index ed84e4268c903..521e518468340 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java @@ -106,6 +106,7 @@ import com.android.systemui.keyguard.KeyguardUnlockAnimationController; import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.keyguard.ScreenLifecycle; import com.android.systemui.keyguard.WakefulnessLifecycle; +import com.android.systemui.keyguard.ui.viewmodel.LightRevealScrimViewModel; import com.android.systemui.navigationbar.NavigationBarController; import com.android.systemui.plugins.ActivityStarter.OnDismissAction; import com.android.systemui.plugins.PluginDependencyProvider; @@ -212,6 +213,7 @@ public class CentralSurfacesImplTest extends SysuiTestCase { @Mock private NotificationPanelView mNotificationPanelView; @Mock private IStatusBarService mBarService; @Mock private IDreamManager mDreamManager; + @Mock private LightRevealScrimViewModel mLightRevealScrimViewModel; @Mock private ScrimController mScrimController; @Mock private DozeScrimController mDozeScrimController; @Mock private Lazy mBiometricUnlockControllerLazy; @@ -497,7 +499,8 @@ public class CentralSurfacesImplTest extends SysuiTestCase { mDeviceStateManager, mWiredChargingRippleController, mDreamManager, - mCameraLauncherLazy) { + mCameraLauncherLazy, + () -> mLightRevealScrimViewModel) { @Override protected ViewRootImpl getViewRootImpl() { return mViewRootImpl; diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt index 36016678fb918..5c2a915e81b6a 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt @@ -17,11 +17,15 @@ package com.android.systemui.keyguard.data.repository +import android.graphics.Point import com.android.systemui.common.shared.model.Position import com.android.systemui.keyguard.shared.model.BiometricUnlockModel +import com.android.systemui.keyguard.shared.model.BiometricUnlockSource import com.android.systemui.keyguard.shared.model.DozeTransitionModel import com.android.systemui.keyguard.shared.model.StatusBarState +import com.android.systemui.keyguard.shared.model.WakeSleepReason import com.android.systemui.keyguard.shared.model.WakefulnessModel +import com.android.systemui.keyguard.shared.model.WakefulnessState import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow @@ -49,7 +53,7 @@ class FakeKeyguardRepository : KeyguardRepository { override val isDreaming: Flow = _isDreaming private val _dozeAmount = MutableStateFlow(0f) - override val dozeAmount: Flow = _dozeAmount + override val linearDozeAmount: Flow = _dozeAmount private val _statusBarState = MutableStateFlow(StatusBarState.SHADE) override val statusBarState: Flow = _statusBarState @@ -57,8 +61,16 @@ class FakeKeyguardRepository : KeyguardRepository { private val _dozeTransitionModel = MutableStateFlow(DozeTransitionModel()) override val dozeTransitionModel: Flow = _dozeTransitionModel - private val _wakefulnessState = MutableStateFlow(WakefulnessModel.ASLEEP) - override val wakefulnessState: Flow = _wakefulnessState + private val _wakefulnessModel = + MutableStateFlow( + WakefulnessModel( + WakefulnessState.ASLEEP, + false, + WakeSleepReason.OTHER, + WakeSleepReason.OTHER + ) + ) + override val wakefulness: Flow = _wakefulnessModel private val _isUdfpsSupported = MutableStateFlow(false) @@ -71,6 +83,15 @@ class FakeKeyguardRepository : KeyguardRepository { private val _biometricUnlockState = MutableStateFlow(BiometricUnlockModel.NONE) override val biometricUnlockState: Flow = _biometricUnlockState + private val _fingerprintSensorLocation = MutableStateFlow(null) + override val fingerprintSensorLocation: Flow = _fingerprintSensorLocation + + private val _faceSensorLocation = MutableStateFlow(null) + override val faceSensorLocation: Flow = _faceSensorLocation + + private val _biometricUnlockSource = MutableStateFlow(null) + override val biometricUnlockSource: Flow = _biometricUnlockSource + override fun isKeyguardShowing(): Boolean { return _isKeyguardShowing.value } @@ -99,6 +120,22 @@ class FakeKeyguardRepository : KeyguardRepository { _dozeAmount.value = dozeAmount } + fun setBiometricUnlockState(state: BiometricUnlockModel) { + _biometricUnlockState.tryEmit(state) + } + + fun setBiometricUnlockSource(source: BiometricUnlockSource?) { + _biometricUnlockSource.tryEmit(source) + } + + fun setFaceSensorLocation(location: Point?) { + _faceSensorLocation.tryEmit(location) + } + + fun setFingerprintSensorLocation(location: Point?) { + _fingerprintSensorLocation.tryEmit(location) + } + override fun isUdfpsSupported(): Boolean { return _isUdfpsSupported.value } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeLightRevealScrimRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeLightRevealScrimRepository.kt new file mode 100644 index 0000000000000..7c22604dc5465 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeLightRevealScrimRepository.kt @@ -0,0 +1,33 @@ +/* + * 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.keyguard.data.repository + +import com.android.systemui.statusbar.LightRevealEffect +import kotlinx.coroutines.flow.MutableStateFlow + +/** Fake implementation of [LightRevealScrimRepository] */ +class FakeLightRevealScrimRepository : LightRevealScrimRepository { + + private val _revealEffect: MutableStateFlow = + MutableStateFlow(DEFAULT_REVEAL_EFFECT) + override val revealEffect = _revealEffect + + fun setRevealEffect(effect: LightRevealEffect) { + _revealEffect.tryEmit(effect) + } +} From 548aa374fbd950c16a3d8af6e7b6e22a3bf91edc Mon Sep 17 00:00:00 2001 From: Jared Duke Date: Wed, 30 Nov 2022 13:38:17 -0800 Subject: [PATCH 20/38] Refine SystemUI plugin and animation deps The PluginCoreLib dependency is not needed by SystemUIAnimationLib, and can conflict with downstream plugins that might want to use the animation lib statically. Remove the dependency, and also remove the animation Proguard rules that were intended to make the animation lib another shared library for plugins. Test: m Bug: 215530220 Change-Id: Ib96e8b0e6f1d4a432c16e699da79ac2de44c9789 --- packages/SystemUI/animation/Android.bp | 5 +---- packages/SystemUI/proguard.flags | 5 +---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/packages/SystemUI/animation/Android.bp b/packages/SystemUI/animation/Android.bp index 5df79e1bee942..e6ac48ff5af8d 100644 --- a/packages/SystemUI/animation/Android.bp +++ b/packages/SystemUI/animation/Android.bp @@ -34,10 +34,7 @@ android_library { "res", ], - static_libs: [ - "PluginCoreLib", - "androidx.core_core-animation-nodeps", - ], + static_libs: ["androidx.core_core-animation-nodeps"], manifest: "AndroidManifest.xml", kotlincflags: ["-Xjvm-default=all"], diff --git a/packages/SystemUI/proguard.flags b/packages/SystemUI/proguard.flags index 1282d771579e3..f96644fbd6673 100644 --- a/packages/SystemUI/proguard.flags +++ b/packages/SystemUI/proguard.flags @@ -23,14 +23,11 @@ -keep class ** extends androidx.preference.PreferenceFragment -keep class com.android.systemui.tuner.* -# The plugins and animation subpackages both act as shared libraries that might be referenced in +# The plugins subpackage acts as a shared library that might be referenced in # dynamically-loaded plugin APKs. -keep class com.android.systemui.plugins.** { *; } --keep class !com.android.systemui.animation.R$**,com.android.systemui.animation.** { - *; -} -keep class com.android.systemui.fragments.FragmentService$FragmentCreator { *; } From 62b6e99f99804107153cca08a96a2fb778481055 Mon Sep 17 00:00:00 2001 From: Sarah Chin Date: Wed, 23 Nov 2022 14:47:25 -0800 Subject: [PATCH 21/38] Add carrier config to include LTE bands when calculating NR advaanced threshold Test: atest NetworkTypeControllerTest Bug: 260052715 Merged-In: I71f989d5dcff9d5f7d3fd11c87fbce68b1484b50 Change-Id: Ie48a045a148bf6a41eb23f4f67030efde01e8c39 --- .../java/android/telephony/CarrierConfigManager.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index 7f8e4ba405d33..741721d14ac1e 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -1999,6 +1999,17 @@ public class CarrierConfigManager { public static final String KEY_NR_ADVANCED_THRESHOLD_BANDWIDTH_KHZ_INT = "nr_advanced_threshold_bandwidth_khz_int"; + /** + * Indicating whether to include LTE cell bandwidths when determining whether the aggregated + * cell bandwidth meets the required threshold for NR advanced. + * + * @see TelephonyDisplayInfo#OVERRIDE_NETWORK_TYPE_NR_ADVANCED + * + * @hide + */ + public static final String KEY_INCLUDE_LTE_FOR_NR_ADVANCED_THRESHOLD_BANDWIDTH_BOOL = + "include_lte_for_nr_advanced_threshold_bandwidth_bool"; + /** * Boolean indicating if operator name should be shown in the status bar * @hide @@ -9001,6 +9012,7 @@ public class CarrierConfigManager { sDefaults.putBoolean(KEY_HIDE_LTE_PLUS_DATA_ICON_BOOL, true); sDefaults.putInt(KEY_LTE_PLUS_THRESHOLD_BANDWIDTH_KHZ_INT, 20000); sDefaults.putInt(KEY_NR_ADVANCED_THRESHOLD_BANDWIDTH_KHZ_INT, 0); + sDefaults.putBoolean(KEY_INCLUDE_LTE_FOR_NR_ADVANCED_THRESHOLD_BANDWIDTH_BOOL, false); sDefaults.putIntArray(KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY, new int[]{CARRIER_NR_AVAILABILITY_NSA, CARRIER_NR_AVAILABILITY_SA}); sDefaults.putBoolean(KEY_LTE_ENABLED_BOOL, true); From 8e91950d5594a527adee82ffb6d64d63825341ad Mon Sep 17 00:00:00 2001 From: Caitlin Shkuratov Date: Tue, 29 Nov 2022 15:27:11 +0000 Subject: [PATCH 22/38] [SB Refactor] Add table logging to the rest of the wifi repository. Bug: 238425913 Test: `adb shell dumpsys activity service com.android.systemui/.SystemUIService WifiTableLog` -> has logs for enabled, default, activity Test: atest WifiRepositoryImplTest Change-Id: I1496b81509dc7abbce458c49102b7e83ae9b5479 --- .../wifi/data/repository/WifiRepository.kt | 20 ++++++++++++++-- .../wifi/shared/model/WifiActivityModel.kt | 24 ++++++++++++++++++- 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepository.kt index a6635361cb3c7..0c9c1cc51ca4e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepository.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/repository/WifiRepository.kt @@ -43,6 +43,7 @@ import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger.Companion.SB_LOGGING_TAG import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger.Companion.logInputChange import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel +import com.android.systemui.statusbar.pipeline.wifi.shared.model.ACTIVITY_PREFIX import com.android.systemui.statusbar.pipeline.wifi.shared.model.WifiActivityModel import java.util.concurrent.Executor import javax.inject.Inject @@ -109,7 +110,12 @@ class WifiRepositoryImpl @Inject constructor( merge(wifiNetworkChangeEvents, wifiStateChangeEvents) .mapLatest { wifiManager.isWifiEnabled } .distinctUntilChanged() - .logInputChange(logger, "enabled") + .logDiffsForTable( + wifiTableLogBuffer, + columnPrefix = "", + columnName = "isWifiEnabled", + initialValue = wifiManager.isWifiEnabled, + ) .stateIn( scope = scope, started = SharingStarted.WhileSubscribed(), @@ -143,7 +149,12 @@ class WifiRepositoryImpl @Inject constructor( awaitClose { connectivityManager.unregisterNetworkCallback(callback) } } .distinctUntilChanged() - .logInputChange(logger, "isWifiDefault") + .logDiffsForTable( + wifiTableLogBuffer, + columnPrefix = "", + columnName = "isWifiDefault", + initialValue = false, + ) .stateIn( scope, started = SharingStarted.WhileSubscribed(), @@ -233,6 +244,11 @@ class WifiRepositoryImpl @Inject constructor( awaitClose { wifiManager.unregisterTrafficStateCallback(callback) } } } + .logDiffsForTable( + wifiTableLogBuffer, + columnPrefix = ACTIVITY_PREFIX, + initialValue = ACTIVITY_DEFAULT, + ) .stateIn( scope, started = SharingStarted.WhileSubscribed(), diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/model/WifiActivityModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/model/WifiActivityModel.kt index 574610605b4e2..a4ca41c22ad10 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/model/WifiActivityModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/shared/model/WifiActivityModel.kt @@ -16,10 +16,32 @@ package com.android.systemui.statusbar.pipeline.wifi.shared.model +import com.android.systemui.log.table.Diffable +import com.android.systemui.log.table.TableRowLogger + /** Provides information on the current wifi activity. */ data class WifiActivityModel( /** True if the wifi has activity in (download). */ val hasActivityIn: Boolean, /** True if the wifi has activity out (upload). */ val hasActivityOut: Boolean, -) +) : Diffable { + + override fun logDiffs(prevVal: WifiActivityModel, row: TableRowLogger) { + if (prevVal.hasActivityIn != hasActivityIn) { + row.logChange(COL_ACTIVITY_IN, hasActivityIn) + } + if (prevVal.hasActivityOut != hasActivityOut) { + row.logChange(COL_ACTIVITY_OUT, hasActivityOut) + } + } + + override fun logFull(row: TableRowLogger) { + row.logChange(COL_ACTIVITY_IN, hasActivityIn) + row.logChange(COL_ACTIVITY_OUT, hasActivityOut) + } +} + +const val ACTIVITY_PREFIX = "wifiActivity" +private const val COL_ACTIVITY_IN = "in" +private const val COL_ACTIVITY_OUT = "out" From e96ef6d3c70f2bbc8aadd958916b1ee27e74712f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A1s=20Kurucz?= Date: Wed, 30 Nov 2022 13:32:11 +0000 Subject: [PATCH 23/38] Fix rendering issue after cancelling Notifications inside a group If we return true from `offerToKeepInParentForAnimation`, the ShadeViewDiffer won't detach this row and the view system is responsible for ensuring the row is in eventually removed from the parent. The view system can only guarantee this if the removal was triggered by a dismissal from the user. The bug was a regression from ag/20291263. Fixes: 260079710 Test: 1) post a group of notifications 2) cancel a child 3) post the same child again (a notif with the same tag) 4) expand notif group Test: dismiss a group of Notifications and observe the animations Test: atest ExpandableNotificationRowControllerTest Change-Id: Iea4032ece37e36a3f08cd6626e998717cda511c7 --- .../row/ExpandableNotificationRow.java | 6 + .../ExpandableNotificationRowController.java | 7 +- ...ExpandableNotificationRowControllerTest.kt | 173 ++++++++++++++++++ 3 files changed, 185 insertions(+), 1 deletion(-) create mode 100644 packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowControllerTest.kt diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java index 1eccc9879a873..d7d5ac9612492 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java @@ -19,6 +19,7 @@ package com.android.systemui.statusbar.notification.row; import static android.app.Notification.Action.SEMANTIC_ACTION_MARK_CONVERSATION_AS_PRIORITY; import static android.service.notification.NotificationListenerService.REASON_CANCEL; +import static com.android.systemui.statusbar.notification.collection.NotificationEntry.DismissState.PARENT_DISMISSED; import static com.android.systemui.statusbar.notification.row.NotificationContentView.VISIBLE_TYPE_HEADSUP; import android.animation.Animator; @@ -1404,6 +1405,11 @@ public class ExpandableNotificationRow extends ActivatableNotificationView mKeepInParentForDismissAnimation = keepInParent; } + /** @return true if the User has dismissed this notif's parent */ + public boolean isParentDismissed() { + return getEntry().getDismissState() == PARENT_DISMISSED; + } + @Override public boolean isRemoved() { return mRemoved; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java index f9e9a2d381380..8a400d5fef99a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowController.java @@ -359,10 +359,15 @@ public class ExpandableNotificationRowController implements NotifViewController @Override public boolean offerToKeepInParentForAnimation() { - if (mFeatureFlags.isEnabled(Flags.NOTIFICATION_GROUP_DISMISSAL_ANIMATION)) { + //If the User dismissed the notification's parent, we want to keep it attached until the + //dismiss animation is ongoing. Therefore we don't want to remove it in the ShadeViewDiffer. + if (mFeatureFlags.isEnabled(Flags.NOTIFICATION_GROUP_DISMISSAL_ANIMATION) + && mView.isParentDismissed()) { mView.setKeepInParentForDismissAnimation(true); return true; } + + //Otherwise the view system doesn't do the removal, so we rely on the ShadeViewDiffer return false; } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowControllerTest.kt new file mode 100644 index 0000000000000..2d23f3c4aea8d --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowControllerTest.kt @@ -0,0 +1,173 @@ +/* + * 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.statusbar.notification.row + +import android.testing.AndroidTestingRunner +import android.testing.TestableLooper +import androidx.test.filters.SmallTest +import com.android.internal.logging.MetricsLogger +import com.android.systemui.SysuiTestCase +import com.android.systemui.classifier.FalsingCollector +import com.android.systemui.flags.FeatureFlags +import com.android.systemui.flags.Flags +import com.android.systemui.plugins.FalsingManager +import com.android.systemui.plugins.PluginManager +import com.android.systemui.plugins.statusbar.StatusBarStateController +import com.android.systemui.statusbar.NotificationMediaManager +import com.android.systemui.statusbar.SmartReplyController +import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager +import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager +import com.android.systemui.statusbar.notification.logging.NotificationLogger +import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier +import com.android.systemui.statusbar.notification.stack.NotificationListContainer +import com.android.systemui.statusbar.phone.KeyguardBypassController +import com.android.systemui.statusbar.policy.HeadsUpManager +import com.android.systemui.statusbar.policy.SmartReplyConstants +import com.android.systemui.statusbar.policy.dagger.RemoteInputViewSubcomponent +import com.android.systemui.util.mockito.mock +import com.android.systemui.util.time.SystemClock +import com.android.systemui.wmshell.BubblesManager +import java.util.Optional +import junit.framework.Assert +import org.junit.After +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mockito +import org.mockito.Mockito.anyBoolean +import org.mockito.Mockito.never +import org.mockito.Mockito.`when` as whenever + +@SmallTest +@RunWith(AndroidTestingRunner::class) +@TestableLooper.RunWithLooper +class ExpandableNotificationRowControllerTest : SysuiTestCase() { + + private val appName = "MyApp" + private val notifKey = "MyNotifKey" + + private val view: ExpandableNotificationRow = mock() + private val activableNotificationViewController: ActivatableNotificationViewController = mock() + private val rivSubComponentFactory: RemoteInputViewSubcomponent.Factory = mock() + private val metricsLogger: MetricsLogger = mock() + private val logBufferLogger: NotificationRowLogger = mock() + private val listContainer: NotificationListContainer = mock() + private val mediaManager: NotificationMediaManager = mock() + private val smartReplyConstants: SmartReplyConstants = mock() + private val smartReplyController: SmartReplyController = mock() + private val pluginManager: PluginManager = mock() + private val systemClock: SystemClock = mock() + private val keyguardBypassController: KeyguardBypassController = mock() + private val groupMembershipManager: GroupMembershipManager = mock() + private val groupExpansionManager: GroupExpansionManager = mock() + private val rowContentBindStage: RowContentBindStage = mock() + private val notifLogger: NotificationLogger = mock() + private val headsUpManager: HeadsUpManager = mock() + private val onExpandClickListener: ExpandableNotificationRow.OnExpandClickListener = mock() + private val statusBarStateController: StatusBarStateController = mock() + private val gutsManager: NotificationGutsManager = mock() + private val onUserInteractionCallback: OnUserInteractionCallback = mock() + private val falsingManager: FalsingManager = mock() + private val falsingCollector: FalsingCollector = mock() + private val featureFlags: FeatureFlags = mock() + private val peopleNotificationIdentifier: PeopleNotificationIdentifier = mock() + private val bubblesManager: BubblesManager = mock() + private val dragController: ExpandableNotificationRowDragController = mock() + private lateinit var controller: ExpandableNotificationRowController + + @Before + fun setUp() { + allowTestableLooperAsMainThread() + controller = + ExpandableNotificationRowController( + view, + activableNotificationViewController, + rivSubComponentFactory, + metricsLogger, + logBufferLogger, + listContainer, + mediaManager, + smartReplyConstants, + smartReplyController, + pluginManager, + systemClock, + appName, + notifKey, + keyguardBypassController, + groupMembershipManager, + groupExpansionManager, + rowContentBindStage, + notifLogger, + headsUpManager, + onExpandClickListener, + statusBarStateController, + gutsManager, + /*allowLongPress=*/ false, + onUserInteractionCallback, + falsingManager, + falsingCollector, + featureFlags, + peopleNotificationIdentifier, + Optional.of(bubblesManager), + dragController + ) + } + + @After + fun tearDown() { + disallowTestableLooperAsMainThread() + } + + @Test + fun offerKeepInParent_parentDismissed() { + whenever(featureFlags.isEnabled(Flags.NOTIFICATION_GROUP_DISMISSAL_ANIMATION)) + .thenReturn(true) + whenever(view.isParentDismissed).thenReturn(true) + + Assert.assertTrue(controller.offerToKeepInParentForAnimation()) + Mockito.verify(view).setKeepInParentForDismissAnimation(true) + } + + @Test + fun offerKeepInParent_parentNotDismissed() { + whenever(featureFlags.isEnabled(Flags.NOTIFICATION_GROUP_DISMISSAL_ANIMATION)) + .thenReturn(true) + + Assert.assertFalse(controller.offerToKeepInParentForAnimation()) + Mockito.verify(view, never()).setKeepInParentForDismissAnimation(anyBoolean()) + } + + @Test + fun removeFromParent_keptForAnimation() { + val parentView: ExpandableNotificationRow = mock() + whenever(view.notificationParent).thenReturn(parentView) + whenever(view.keepInParentForDismissAnimation()).thenReturn(true) + + Assert.assertTrue(controller.removeFromParentIfKeptForAnimation()) + Mockito.verify(parentView).removeChildNotification(view) + } + + @Test + fun removeFromParent_notKeptForAnimation() { + val parentView: ExpandableNotificationRow = mock() + whenever(view.notificationParent).thenReturn(parentView) + + Assert.assertFalse(controller.removeFromParentIfKeptForAnimation()) + Mockito.verifyNoMoreInteractions(parentView) + } +} From 31da217d0651d1d28ee362ef25cd6af128d94a56 Mon Sep 17 00:00:00 2001 From: Jordan Demeulenaere Date: Thu, 1 Dec 2022 18:02:14 +0100 Subject: [PATCH 24/38] Fix NPE in DialogLaunchAnimator This CL fixes a NPE happening in DialogLaunchAnimator if it tried to synchronize the 2 view roots at the start/end of the animation and that the view that triggered the animation was detached from the hierarchy. This regression was caused by the refactoring in http://ag/20139844. Bug: 256194999 Test: Manual Change-Id: Id264ddfa6365bfdc952d512c2c182b6cbf4906e4 --- .../systemui/animation/DialogLaunchAnimator.kt | 12 +++++++----- .../animation/ViewDialogLaunchAnimatorController.kt | 2 +- .../compose/animation/ExpandableController.kt | 2 +- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt index fdfad2bc2fa17..54aa3516d867f 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt +++ b/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt @@ -75,7 +75,7 @@ constructor( */ interface Controller { /** The [ViewRootImpl] of this controller. */ - val viewRoot: ViewRootImpl + val viewRoot: ViewRootImpl? /** * The identity object of the source animated by this controller. This animator will ensure @@ -807,15 +807,17 @@ private class AnimatedDialog( * inversely, removed from the overlay when the source is moved back to its original position). */ private fun synchronizeNextDraw(then: () -> Unit) { - if (forceDisableSynchronization) { - // Don't synchronize when inside an automated test. + val controllerRootView = controller.viewRoot?.view + if (forceDisableSynchronization || controllerRootView == null) { + // Don't synchronize when inside an automated test or if the controller root view is + // detached. then() return } - ViewRootSync.synchronizeNextDraw(controller.viewRoot.view, decorView, then) + ViewRootSync.synchronizeNextDraw(controllerRootView, decorView, then) decorView.invalidate() - controller.viewRoot.view.invalidate() + controllerRootView.invalidate() } private fun findFirstViewGroupWithBackground(view: View): ViewGroup? { diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/ViewDialogLaunchAnimatorController.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/ViewDialogLaunchAnimatorController.kt index ecee598afe4e4..964ef8c880982 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/animation/ViewDialogLaunchAnimatorController.kt +++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ViewDialogLaunchAnimatorController.kt @@ -28,7 +28,7 @@ internal constructor( private val source: View, override val cuj: DialogCuj?, ) : DialogLaunchAnimator.Controller { - override val viewRoot: ViewRootImpl + override val viewRoot: ViewRootImpl? get() = source.viewRootImpl override val sourceIdentity: Any = source diff --git a/packages/SystemUI/compose/core/src/com/android/systemui/compose/animation/ExpandableController.kt b/packages/SystemUI/compose/core/src/com/android/systemui/compose/animation/ExpandableController.kt index 50c3d7e1e76b2..d6db574a34ae7 100644 --- a/packages/SystemUI/compose/core/src/com/android/systemui/compose/animation/ExpandableController.kt +++ b/packages/SystemUI/compose/core/src/com/android/systemui/compose/animation/ExpandableController.kt @@ -262,7 +262,7 @@ internal class ExpandableControllerImpl( private fun dialogController(cuj: DialogCuj?): DialogLaunchAnimator.Controller { return object : DialogLaunchAnimator.Controller { - override val viewRoot: ViewRootImpl = composeViewRoot.viewRootImpl + override val viewRoot: ViewRootImpl? = composeViewRoot.viewRootImpl override val sourceIdentity: Any = this@ExpandableControllerImpl override val cuj: DialogCuj? = cuj From bb3fe749a9e39363be6ca520acc26ac66b23cb9b Mon Sep 17 00:00:00 2001 From: Brad Hinegardner Date: Tue, 29 Nov 2022 16:55:59 -0500 Subject: [PATCH 25/38] When in guest mode, see "Exit guest" in user switcher Bug: 260404638 Test: UserSwitcherViewModel.kt added tests, manual verification Change-Id: Iaaf1480a8bffde610063c29b32a2b7ae7187b184 --- .../ui/viewmodel/UserSwitcherViewModel.kt | 9 +- .../ui/viewmodel/UserSwitcherViewModelTest.kt | 139 +++++++++++++----- 2 files changed, 114 insertions(+), 34 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModel.kt b/packages/SystemUI/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModel.kt index 0910ea36b7fff..37115ad53880c 100644 --- a/packages/SystemUI/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModel.kt @@ -19,6 +19,8 @@ package com.android.systemui.user.ui.viewmodel import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider +import com.android.systemui.R +import com.android.systemui.common.shared.model.Text import com.android.systemui.common.ui.drawable.CircularDrawable import com.android.systemui.power.domain.interactor.PowerInteractor import com.android.systemui.user.domain.interactor.GuestUserInteractor @@ -144,7 +146,12 @@ private constructor( ): UserViewModel { return UserViewModel( viewKey = model.id, - name = model.name, + name = + if (model.isGuest && model.isSelected) { + Text.Resource(R.string.guest_exit_quick_settings_button) + } else { + model.name + }, image = CircularDrawable(model.image), isSelectionMarkerVisible = model.isSelected, alpha = diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt index 4b6bdac46a3d9..784a26bb371bf 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt @@ -47,18 +47,14 @@ import com.android.systemui.user.shared.model.UserActionModel import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat -import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.Job -import kotlinx.coroutines.SupervisorJob -import kotlinx.coroutines.cancelAndJoin import kotlinx.coroutines.flow.toList import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking import kotlinx.coroutines.test.TestDispatcher -import kotlinx.coroutines.test.TestResult import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.UnconfinedTestDispatcher +import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Before import org.junit.Test @@ -89,7 +85,6 @@ class UserSwitcherViewModelTest : SysuiTestCase() { private lateinit var testDispatcher: TestDispatcher private lateinit var testScope: TestScope - private lateinit var injectedScope: CoroutineScope @Before fun setUp() { @@ -104,7 +99,6 @@ class UserSwitcherViewModelTest : SysuiTestCase() { testDispatcher = UnconfinedTestDispatcher() testScope = TestScope(testDispatcher) - injectedScope = CoroutineScope(testScope.coroutineContext + SupervisorJob()) userRepository = FakeUserRepository() runBlocking { userRepository.setSettings( @@ -118,14 +112,14 @@ class UserSwitcherViewModelTest : SysuiTestCase() { powerRepository = FakePowerRepository() val refreshUsersScheduler = RefreshUsersScheduler( - applicationScope = injectedScope, + applicationScope = testScope.backgroundScope, mainDispatcher = testDispatcher, repository = userRepository, ) val guestUserInteractor = GuestUserInteractor( applicationContext = context, - applicationScope = injectedScope, + applicationScope = testScope.backgroundScope, mainDispatcher = testDispatcher, backgroundDispatcher = testDispatcher, manager = manager, @@ -154,7 +148,7 @@ class UserSwitcherViewModelTest : SysuiTestCase() { set(Flags.FULL_SCREEN_USER_SWITCHER, false) }, manager = manager, - applicationScope = injectedScope, + applicationScope = testScope.backgroundScope, telephonyInteractor = TelephonyInteractor( repository = FakeTelephonyRepository(), @@ -175,7 +169,7 @@ class UserSwitcherViewModelTest : SysuiTestCase() { } @Test - fun users() = selfCancelingTest { + fun users() = testScope.runTest { val userInfos = listOf( UserInfo( @@ -210,26 +204,26 @@ class UserSwitcherViewModelTest : SysuiTestCase() { assertUserViewModel( viewModel = userViewModels.last()[0], viewKey = 0, - name = "zero", + name = Text.Loaded("zero"), isSelectionMarkerVisible = true, ) assertUserViewModel( viewModel = userViewModels.last()[1], viewKey = 1, - name = "one", + name = Text.Loaded("one"), isSelectionMarkerVisible = false, ) assertUserViewModel( viewModel = userViewModels.last()[2], viewKey = 2, - name = "two", + name = Text.Loaded("two"), isSelectionMarkerVisible = false, ) job.cancel() } @Test - fun `maximumUserColumns - few users`() = selfCancelingTest { + fun `maximumUserColumns - few users`() = testScope.runTest { setUsers(count = 2) val values = mutableListOf() val job = launch(testDispatcher) { underTest.maximumUserColumns.toList(values) } @@ -240,7 +234,7 @@ class UserSwitcherViewModelTest : SysuiTestCase() { } @Test - fun `maximumUserColumns - many users`() = selfCancelingTest { + fun `maximumUserColumns - many users`() = testScope.runTest { setUsers(count = 5) val values = mutableListOf() val job = launch(testDispatcher) { underTest.maximumUserColumns.toList(values) } @@ -250,7 +244,7 @@ class UserSwitcherViewModelTest : SysuiTestCase() { } @Test - fun `isOpenMenuButtonVisible - has actions - true`() = selfCancelingTest { + fun `isOpenMenuButtonVisible - has actions - true`() = testScope.runTest { setUsers(2) val isVisible = mutableListOf() @@ -261,7 +255,7 @@ class UserSwitcherViewModelTest : SysuiTestCase() { } @Test - fun `isOpenMenuButtonVisible - no actions - false`() = selfCancelingTest { + fun `isOpenMenuButtonVisible - no actions - false`() = testScope.runTest { val userInfos = setUsers(2) userRepository.setSelectedUserInfo(userInfos[1]) keyguardRepository.setKeyguardShowing(true) @@ -275,7 +269,7 @@ class UserSwitcherViewModelTest : SysuiTestCase() { } @Test - fun menu() = selfCancelingTest { + fun menu() = testScope.runTest { val isMenuVisible = mutableListOf() val job = launch(testDispatcher) { underTest.isMenuVisible.toList(isMenuVisible) } assertThat(isMenuVisible.last()).isFalse() @@ -290,7 +284,7 @@ class UserSwitcherViewModelTest : SysuiTestCase() { } @Test - fun `menu actions`() = selfCancelingTest { + fun `menu actions`() = testScope.runTest { setUsers(2) val actions = mutableListOf>() val job = launch(testDispatcher) { underTest.menu.toList(actions) } @@ -309,7 +303,7 @@ class UserSwitcherViewModelTest : SysuiTestCase() { } @Test - fun `isFinishRequested - finishes when user is switched`() = selfCancelingTest { + fun `isFinishRequested - finishes when user is switched`() = testScope.runTest { val userInfos = setUsers(count = 2) val isFinishRequested = mutableListOf() val job = launch(testDispatcher) { underTest.isFinishRequested.toList(isFinishRequested) } @@ -323,7 +317,7 @@ class UserSwitcherViewModelTest : SysuiTestCase() { } @Test - fun `isFinishRequested - finishes when the screen turns off`() = selfCancelingTest { + fun `isFinishRequested - finishes when the screen turns off`() = testScope.runTest { setUsers(count = 2) powerRepository.setInteractive(true) val isFinishRequested = mutableListOf() @@ -338,7 +332,7 @@ class UserSwitcherViewModelTest : SysuiTestCase() { } @Test - fun `isFinishRequested - finishes when cancel button is clicked`() = selfCancelingTest { + fun `isFinishRequested - finishes when cancel button is clicked`() = testScope.runTest { setUsers(count = 2) powerRepository.setInteractive(true) val isFinishRequested = mutableListOf() @@ -356,6 +350,93 @@ class UserSwitcherViewModelTest : SysuiTestCase() { job.cancel() } + @Test + fun `guest selected -- name is exit guest`() = testScope.runTest { + val userInfos = + listOf( + UserInfo( + /* id= */ 0, + /* name= */ "zero", + /* iconPath= */ "", + /* flags= */ UserInfo.FLAG_PRIMARY or UserInfo.FLAG_ADMIN or UserInfo.FLAG_FULL, + UserManager.USER_TYPE_FULL_SYSTEM, + ), + UserInfo( + /* id= */ 1, + /* name= */ "one", + /* iconPath= */ "", + /* flags= */ UserInfo.FLAG_FULL, + UserManager.USER_TYPE_FULL_GUEST, + ), + ) + + userRepository.setUserInfos(userInfos) + userRepository.setSelectedUserInfo(userInfos[1]) + + val userViewModels = mutableListOf>() + val job = launch(testDispatcher) { underTest.users.toList(userViewModels) } + + assertThat(userViewModels.last()).hasSize(2) + assertUserViewModel( + viewModel = userViewModels.last()[0], + viewKey = 0, + name = Text.Loaded("zero"), + isSelectionMarkerVisible = false, + ) + assertUserViewModel( + viewModel = userViewModels.last()[1], + viewKey = 1, + name = Text.Resource( + com.android.settingslib.R.string.guest_exit_quick_settings_button + ), + isSelectionMarkerVisible = true, + ) + job.cancel() + } + + @Test + fun `guest not selected -- name is guest`() = testScope.runTest { + val userInfos = + listOf( + UserInfo( + /* id= */ 0, + /* name= */ "zero", + /* iconPath= */ "", + /* flags= */ UserInfo.FLAG_PRIMARY or UserInfo.FLAG_ADMIN or UserInfo.FLAG_FULL, + UserManager.USER_TYPE_FULL_SYSTEM, + ), + UserInfo( + /* id= */ 1, + /* name= */ "one", + /* iconPath= */ "", + /* flags= */ UserInfo.FLAG_FULL, + UserManager.USER_TYPE_FULL_GUEST, + ), + ) + + userRepository.setUserInfos(userInfos) + userRepository.setSelectedUserInfo(userInfos[0]) + runCurrent() + + val userViewModels = mutableListOf>() + val job = launch(testDispatcher) { underTest.users.toList(userViewModels) } + + assertThat(userViewModels.last()).hasSize(2) + assertUserViewModel( + viewModel = userViewModels.last()[0], + viewKey = 0, + name = Text.Loaded("zero"), + isSelectionMarkerVisible = true, + ) + assertUserViewModel( + viewModel = userViewModels.last()[1], + viewKey = 1, + name = Text.Loaded("one"), + isSelectionMarkerVisible = false, + ) + job.cancel() + } + private suspend fun setUsers(count: Int): List { val userInfos = (0 until count).map { index -> @@ -384,26 +465,18 @@ class UserSwitcherViewModelTest : SysuiTestCase() { private fun assertUserViewModel( viewModel: UserViewModel?, viewKey: Int, - name: String, + name: Text, isSelectionMarkerVisible: Boolean, ) { checkNotNull(viewModel) assertThat(viewModel.viewKey).isEqualTo(viewKey) - assertThat(viewModel.name).isEqualTo(Text.Loaded(name)) + assertThat(viewModel.name).isEqualTo(name) assertThat(viewModel.isSelectionMarkerVisible).isEqualTo(isSelectionMarkerVisible) assertThat(viewModel.alpha) .isEqualTo(LegacyUserUiHelper.USER_SWITCHER_USER_VIEW_SELECTABLE_ALPHA) assertThat(viewModel.onClicked).isNotNull() } - private fun selfCancelingTest( - block: suspend TestScope.() -> Unit, - ): TestResult = - testScope.runTest { - block() - injectedScope.coroutineContext[Job.Key]?.cancelAndJoin() - } - companion object { private const val SUPERVISED_USER_CREATION_PACKAGE = "com.some.package" } From 669b633e9d1907d4efe2410220d6fc36019b39e8 Mon Sep 17 00:00:00 2001 From: David Saff Date: Thu, 1 Dec 2022 12:57:45 -0500 Subject: [PATCH 26/38] Clear TestableLoopers in SysuiTestCase Bug: 261039202 Test: presubmit to verify this doesn't break existing tests Test: See b/259992416 for analysis of how this improves memory pressure. Change-Id: Ifa1b489b8dff354a29727fb61342ac9b82ec65e7 --- .../tests/utils/src/com/android/systemui/SysuiTestCase.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java b/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java index fa3cc9905c3f4..bf2235aa98a9b 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/SysuiTestCase.java @@ -136,6 +136,8 @@ public abstract class SysuiTestCase { InstrumentationRegistry.getArguments()); if (TestableLooper.get(this) != null) { TestableLooper.get(this).processAllMessages(); + // Must remove static reference to this test object to prevent leak (b/261039202) + TestableLooper.remove(this); } disallowTestableLooperAsMainThread(); mContext.cleanUpReceivers(this.getClass().getSimpleName()); From 9e3c21bae54a894bd6305e7c728e67d800782e23 Mon Sep 17 00:00:00 2001 From: Joshua McCloskey Date: Thu, 1 Dec 2022 17:34:21 +0000 Subject: [PATCH 27/38] Fixed contrast with sfps overlay. Tested various different themes 1. Choose a color in settings > wallpapers > basic colors 2. Go through enrollment 3. Verify that light/dark theme have appropriate contrast. Test: Manually verified the contrast works for light/dark themes and various different basic color styles. Fixes: 243008680 Change-Id: I63900a8df21a3fe0f02e5da0db6e3b75520fce12 --- packages/SystemUI/res/values/colors.xml | 3 +++ .../src/com/android/systemui/biometrics/SideFpsController.kt | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml index 4ce0852901ff1..4133056dcc57f 100644 --- a/packages/SystemUI/res/values/colors.xml +++ b/packages/SystemUI/res/values/colors.xml @@ -133,6 +133,9 @@ @color/material_dynamic_primary40 #ffd93025 + + @color/material_dynamic_primary90 + #699FF3 #C2D7F7 diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt index 1c3dd451a1d32..e09e65e1b4799 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/SideFpsController.kt @@ -370,11 +370,15 @@ private fun WindowInsets.hasBigNavigationBar(): Boolean = private fun LottieAnimationView.addOverlayDynamicColor(context: Context) { fun update() { val c = context.getColor(R.color.biometric_dialog_accent) + val chevronFill = context.getColor(R.color.sfps_chevron_fill) for (key in listOf(".blue600", ".blue400")) { addValueCallback(KeyPath(key, "**"), LottieProperty.COLOR_FILTER) { PorterDuffColorFilter(c, PorterDuff.Mode.SRC_ATOP) } } + addValueCallback(KeyPath(".black", "**"), LottieProperty.COLOR_FILTER) { + PorterDuffColorFilter(chevronFill, PorterDuff.Mode.SRC_ATOP) + } } if (composition != null) { From f1ae7fbbcfdfd68f91d90538357bf615e79c4642 Mon Sep 17 00:00:00 2001 From: Bill Yi Date: Wed, 30 Nov 2022 06:33:32 -0800 Subject: [PATCH 28/38] Import translations. DO NOT MERGE ANYWHERE Auto-generated-cl: translation import Change-Id: I5e3dbbaa8de129cd52a64ae440272605ac814718 --- packages/SystemUI/res/values-af/strings.xml | 38 +++++++++++----- packages/SystemUI/res/values-am/strings.xml | 44 ++++++++++++++----- packages/SystemUI/res/values-ar/strings.xml | 44 ++++++++++++++----- packages/SystemUI/res/values-as/strings.xml | 38 +++++++++++----- packages/SystemUI/res/values-az/strings.xml | 38 +++++++++++----- .../SystemUI/res/values-b+sr+Latn/strings.xml | 38 +++++++++++----- packages/SystemUI/res/values-be/strings.xml | 38 +++++++++++----- packages/SystemUI/res/values-bg/strings.xml | 38 +++++++++++----- packages/SystemUI/res/values-bn/strings.xml | 38 +++++++++++----- packages/SystemUI/res/values-bs/strings.xml | 37 +++++++++++----- packages/SystemUI/res/values-ca/strings.xml | 40 +++++++++++------ packages/SystemUI/res/values-cs/strings.xml | 38 +++++++++++----- packages/SystemUI/res/values-da/strings.xml | 38 +++++++++++----- packages/SystemUI/res/values-de/strings.xml | 38 +++++++++++----- packages/SystemUI/res/values-el/strings.xml | 35 ++++++++++----- .../SystemUI/res/values-en-rAU/strings.xml | 26 +++++++---- .../SystemUI/res/values-en-rCA/strings.xml | 28 ++++++++---- .../SystemUI/res/values-en-rGB/strings.xml | 26 +++++++---- .../SystemUI/res/values-en-rIN/strings.xml | 26 +++++++---- .../SystemUI/res/values-en-rXC/strings.xml | 26 +++++++---- .../SystemUI/res/values-es-rUS/strings.xml | 38 +++++++++++----- packages/SystemUI/res/values-es/strings.xml | 38 +++++++++++----- packages/SystemUI/res/values-et/strings.xml | 38 +++++++++++----- packages/SystemUI/res/values-eu/strings.xml | 38 +++++++++++----- packages/SystemUI/res/values-fa/strings.xml | 38 +++++++++++----- packages/SystemUI/res/values-fi/strings.xml | 38 +++++++++++----- .../SystemUI/res/values-fr-rCA/strings.xml | 37 +++++++++++----- packages/SystemUI/res/values-fr/strings.xml | 38 +++++++++++----- packages/SystemUI/res/values-gl/strings.xml | 40 +++++++++++------ packages/SystemUI/res/values-gu/strings.xml | 38 +++++++++++----- packages/SystemUI/res/values-hi/strings.xml | 44 ++++++++++++++----- packages/SystemUI/res/values-hr/strings.xml | 35 ++++++++++----- packages/SystemUI/res/values-hu/strings.xml | 38 +++++++++++----- packages/SystemUI/res/values-hy/strings.xml | 38 +++++++++++----- packages/SystemUI/res/values-in/strings.xml | 38 +++++++++++----- packages/SystemUI/res/values-is/strings.xml | 38 +++++++++++----- packages/SystemUI/res/values-it/strings.xml | 32 +++++++++----- packages/SystemUI/res/values-iw/strings.xml | 29 +++++++----- packages/SystemUI/res/values-ja/strings.xml | 26 +++++++---- packages/SystemUI/res/values-ka/strings.xml | 35 ++++++++++----- packages/SystemUI/res/values-kk/strings.xml | 38 +++++++++++----- packages/SystemUI/res/values-km/strings.xml | 38 +++++++++++----- packages/SystemUI/res/values-kn/strings.xml | 32 +++++++++----- packages/SystemUI/res/values-ko/strings.xml | 38 +++++++++++----- packages/SystemUI/res/values-ky/strings.xml | 38 +++++++++++----- packages/SystemUI/res/values-lo/strings.xml | 38 +++++++++++----- packages/SystemUI/res/values-lt/strings.xml | 32 +++++++++----- packages/SystemUI/res/values-lv/strings.xml | 38 +++++++++++----- packages/SystemUI/res/values-mk/strings.xml | 29 +++++++----- packages/SystemUI/res/values-ml/strings.xml | 44 ++++++++++++++----- packages/SystemUI/res/values-mn/strings.xml | 35 ++++++++++----- packages/SystemUI/res/values-mr/strings.xml | 38 +++++++++++----- packages/SystemUI/res/values-ms/strings.xml | 35 ++++++++++----- packages/SystemUI/res/values-my/strings.xml | 44 ++++++++++++++----- packages/SystemUI/res/values-nb/strings.xml | 38 +++++++++++----- packages/SystemUI/res/values-ne/strings.xml | 44 ++++++++++++++----- packages/SystemUI/res/values-nl/strings.xml | 44 ++++++++++++------- packages/SystemUI/res/values-or/strings.xml | 39 +++++++++++----- packages/SystemUI/res/values-pa/strings.xml | 38 +++++++++++----- packages/SystemUI/res/values-pl/strings.xml | 38 +++++++++++----- .../SystemUI/res/values-pt-rBR/strings.xml | 44 ++++++++++++++----- .../SystemUI/res/values-pt-rPT/strings.xml | 26 +++++++---- packages/SystemUI/res/values-pt/strings.xml | 44 ++++++++++++++----- packages/SystemUI/res/values-ro/strings.xml | 35 ++++++++++----- packages/SystemUI/res/values-ru/strings.xml | 38 +++++++++++----- packages/SystemUI/res/values-si/strings.xml | 38 +++++++++++----- packages/SystemUI/res/values-sk/strings.xml | 40 +++++++++++------ packages/SystemUI/res/values-sl/strings.xml | 38 +++++++++++----- packages/SystemUI/res/values-sq/strings.xml | 38 +++++++++++----- packages/SystemUI/res/values-sr/strings.xml | 38 +++++++++++----- packages/SystemUI/res/values-sv/strings.xml | 38 +++++++++++----- packages/SystemUI/res/values-sw/strings.xml | 44 ++++++++++++++----- packages/SystemUI/res/values-ta/strings.xml | 44 ++++++++++++++----- packages/SystemUI/res/values-te/strings.xml | 32 +++++++++----- packages/SystemUI/res/values-th/strings.xml | 26 +++++++---- packages/SystemUI/res/values-tl/strings.xml | 35 ++++++++++----- packages/SystemUI/res/values-tr/strings.xml | 38 +++++++++++----- packages/SystemUI/res/values-uk/strings.xml | 44 ++++++++++++++----- packages/SystemUI/res/values-ur/strings.xml | 38 +++++++++++----- packages/SystemUI/res/values-uz/strings.xml | 35 ++++++++++----- packages/SystemUI/res/values-vi/strings.xml | 38 +++++++++++----- .../SystemUI/res/values-zh-rCN/strings.xml | 40 +++++++++++------ .../SystemUI/res/values-zh-rHK/strings.xml | 32 +++++++++----- .../SystemUI/res/values-zh-rTW/strings.xml | 38 +++++++++++----- packages/SystemUI/res/values-zu/strings.xml | 38 +++++++++++----- 85 files changed, 2182 insertions(+), 961 deletions(-) diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml index 15423af9f02cc..11483d43abd16 100644 --- a/packages/SystemUI/res/values-af/strings.xml +++ b/packages/SystemUI/res/values-af/strings.xml @@ -125,8 +125,7 @@ "Stembystand" "Wallet" "QR-kodeskandeerder" - - + "Ontsluit" "Toestel is gesluit" "Skandeer tans gesig" "Stuur" @@ -169,8 +168,7 @@ "Kan nie gesig herken nie" "Gebruik eerder vingerafdruk" - - + "Gesigslot is onbeskikbaar" "Bluetooth gekoppel." "Batterypersentasie is onbekend." "Gekoppel aan %s." @@ -181,13 +179,10 @@ "Vliegtuigmodus." "VPN aan." "Battery %d persent." - - + "Battery is op %1$d persent; %2$s" "Battery laai tans, %d%%." - - - - + "Battery is op %d persent; laaiproses is onderbreek om die battery te beskerm." + "Battery is op %1$d persent; %2$s, laaiproses is onderbreek om die battery te beskerm." "Sien alle kennisgewings" "TeleTypewriter geaktiveer." "Luitoestel-vibreer." @@ -501,8 +496,8 @@ "Ontsluit om te gebruik" "Kon nie jou kaarte kry nie; probeer later weer" "Sluitskerminstellings" - - + "QR-kodeskandeerder" + "Dateer tans op" "Werkprofiel" "Vliegtuigmodus" "Jy sal nie jou volgende wekker %1$s hoor nie" @@ -996,4 +991,23 @@ "EE. d MMM." "h:mm" "kk:mm" + "Maak %1$s oop" + "Om die %1$s-app as ’n kortpad by te voeg, moet jy seker maak dat" + "• Die app opgestel is" + "• Minstens een kaart by Wallet gevoeg is" + "• Installeer ’n kamera-app" + "• Die app opgestel is" + "• Minstens een toestel beskikbaar is" + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml index 6c9b07f033c0e..93bb9e81faa55 100644 --- a/packages/SystemUI/res/values-am/strings.xml +++ b/packages/SystemUI/res/values-am/strings.xml @@ -125,8 +125,7 @@ "የድምጽ እርዳታ" "Wallet" "የQR ኮድ መቃኛ" - - + "ተከፍቷል" "መሣሪያ ተቆልፏል" "የቅኝት ፊት" "ላክ" @@ -169,8 +168,7 @@ "መልክን መለየት አልተቻለም" "በምትኩ የጣት አሻራን ይጠቀሙ" - - + "በመልክ መክፈት አይገኝም" "ብሉቱዝ ተያይዟል።" "የባትሪ መቶኛ አይታወቅም።" "ከ%s ጋር ተገናኝቷል።" @@ -181,13 +179,10 @@ "የአውሮፕላን ሁነታ።" "ቪፒኤን በርቷል።" "የባትሪ %d መቶኛ።" - - + "የባትሪ %1$d መቶኛ፣ %2$s" "ባትሪ ኃይል በመሙላት ላይ፣ %d %%." - - - - + "የባትሪ %d መቶኛ፣ ለባትሪ ጥበቃ ኃይል መሙላት ለአፍታ ቆሟል።" + "የባትሪ %1$d መቶኛ፣ %2$s፣ ለባትሪ ጥበቃ ኃይል መሙላት ለአፍታ ቆሟል።" "ሁሉንም ማሳወቂያዎች ይመልከቱ" "TeleTypewriter ነቅቷል።" "የስልክ ጥሪ ይንዘር።" @@ -501,7 +496,8 @@ "ለማየት ይክፈቱ" "የእርስዎን ካርዶች ማግኘት ላይ ችግር ነበር፣ እባክዎ ቆይተው እንደገና ይሞክሩ" "የገጽ መቆለፊያ ቅንብሮች" - + "የQR ኮድ መቃኛ" + "የስራ መገለጫ" "የአውሮፕላን ሁነታ" @@ -996,4 +992,30 @@ "EEE፣ MMM d" "h:mm" "kk:mm" + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml index 384087b4da84f..6b80cd15806a4 100644 --- a/packages/SystemUI/res/values-ar/strings.xml +++ b/packages/SystemUI/res/values-ar/strings.xml @@ -125,8 +125,7 @@ "المساعد الصوتي" "محفظة" "الماسح الضوئي لرمز الاستجابة السريعة" - - + "تم فتح القفل" "الجهاز مُقفل." "مسح الوجه" "إرسال" @@ -169,8 +168,7 @@ "يتعذّر التعرّف على الوجه." "يمكنك استخدام بصمة إصبعك." - - + "ميزة \"فتح الجهاز بالتعرف على الوجه\" غير متاحة." "تم توصيل البلوتوث." "نسبة شحن البطارية غير معروفة." "متصل بـ %s." @@ -181,13 +179,10 @@ "وضع الطيران." "‏الشبكة الافتراضية الخاصة (VPN) قيد التفعيل." "مستوى البطارية %d في المائة." - - + "نسبة شحن البطارية %1$d في المائة؛ %2$s." "جارٍ شحن البطارية، %d%%." - - - - + "نسبة شحن البطارية %d في المئة؛ تم إيقاف الشحن مؤقتًا لحماية البطارية." + "نسبة شحن البطارية %1$d في المئة؛ %2$s؛ تم إيقاف الشحن مؤقتًا لحماية البطارية." "الاطّلاع على جميع الإشعارات" "تم تفعيل المبرقة الكاتبة." "رنين مع الاهتزاز." @@ -501,7 +496,8 @@ "فتح القفل للاستخدام" "حدثت مشكلة أثناء الحصول على البطاقات، يُرجى إعادة المحاولة لاحقًا." "إعدادات شاشة القفل" - + "ماسح ضوئي لرمز الاستجابة السريعة" + "الملف الشخصي للعمل" "وضع الطيران" @@ -996,4 +992,30 @@ "‏EEE،‏ d‏ MMM" "h:mm" "kk:mm" + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml index 411419c280ada..8fc1190a8ee0e 100644 --- a/packages/SystemUI/res/values-as/strings.xml +++ b/packages/SystemUI/res/values-as/strings.xml @@ -125,8 +125,7 @@ "কণ্ঠধ্বনিৰে সহায়" "ৱালেট" "কিউআৰ ক’ড স্কেনাৰ" - - + "আনলক কৰা আছে" "ডিভাইচটো লক হৈ আছে" "চেহেৰা স্কেন কৰি থকা হৈছে" "পঠিয়াওক" @@ -169,8 +168,7 @@ "মুখাৱয়ব চিনিব নোৱাৰি" "ইয়াৰ সলনি ফিংগাৰপ্ৰিণ্ট ব্যৱহাৰ কৰক" - - + "ফেচ আনলক সুবিধা উপলব্ধ নহয়" "ব্লুটুথ সংযোগ হ’ল।" "বেটাৰীৰ চাৰ্জৰ শতাংশ অজ্ঞাত।" "%sৰ লগত সংযোগ কৰা হ’ল।" @@ -181,13 +179,10 @@ "এয়াৰপ্লে’ন ম’ড।" "ভিপিএন অন অৱস্থাত আছে।" "%d শতাংশ বেটাৰী।" - - + "%1$d শতাংশ বেটাৰী, %2$s" "বেটাৰী চাৰ্জ হৈ আছে, %d শতাংশ।" - - - - + "বেটাৰী %d শতাংশ, বেটাৰীৰ সুৰক্ষাৰ বাবে চাৰ্জিং পজ কৰা হৈছে।" + "বেটাৰী %1$d শতাংশ, %2$s, বেটাৰীৰ সুৰক্ষাৰ বাবে চাৰ্জিং পজ কৰা হৈছে।" "আটাইবোৰ জাননী চাওক" "TeleTypewriter সক্ষম কৰা হ\'ল৷" "ৰিংগাৰ কম্পন অৱস্থাত আছে৷" @@ -501,8 +496,8 @@ "ব্যৱহাৰ কৰিবলৈ আনলক কৰক" "আপোনাৰ কাৰ্ড লাভ কৰোঁতে এটা সমস্যা হৈছে, অনুগ্ৰহ কৰি পাছত পুনৰ চেষ্টা কৰক" "লক স্ক্ৰীনৰ ছেটিং" - - + "কিউআৰ ক’ড স্কেনাৰ" + "আপডে’ট কৰি থকা হৈছে" "কৰ্মস্থানৰ প্ৰ\'ফাইল" "এয়াৰপ্লে’ন ম’ড" "আপুনি আপোনাৰ পিছৰটো এলাৰ্ম %1$s বজাত শুনা নাপাব" @@ -996,4 +991,23 @@ "EEE, MMM d" "h:mm" "kk:mm" + "%1$s খোলক" + "%1$s এপ্‌টোক এটা শ্বৰ্টকাট হিচাপে যোগ দিবলৈ, এইকেইটা কথা নিশ্চিত কৰক" + "• এপ্‌টো ছেট আপ কৰা হৈছে" + "• Walletত অতি কমেও এখন কাৰ্ড যোগ দিয়া হৈছে" + "• এটা কেমেৰা এপ্ ইনষ্টল কৰক" + "• এপ্‌টো ছেট আপ কৰা হৈছে" + "• অতি কমেও এটা ডিভাইচ উপলব্ধ" + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml index f3e281fe49a48..9783430ba9bef 100644 --- a/packages/SystemUI/res/values-az/strings.xml +++ b/packages/SystemUI/res/values-az/strings.xml @@ -125,8 +125,7 @@ "Səs Yardımçısı" "Pulqabı" "QR Kodu Skaneri" - - + "Kiliddən çıxarılmış" "Cihaz kilidlənib" "Üzün skan edilməsi" "Göndərin" @@ -169,8 +168,7 @@ "Üzü tanımaq olmur" "Barmaq izi istifadə edin" - - + "Üz ilə kiliddən çıxarma əlçatan deyil" "Bluetooth qoşulub." "Batareyanın faizi naməlumdur." "%s üzərindən qoşuldu." @@ -181,13 +179,10 @@ "Uçuş rejimi" "VPN aktivdir." "Batareya %d faizdir." - - + "Batareya %1$d faizdir, %2$s." "Batareya doldurulur, %d%% faiz." - - - - + "Batareya %d faizdir, batareyanın qorunması üçün şarj durdurulub." + "Batareya %1$d faizdir, %2$s, batareyanın qorunması üçün şarj durdurulub." "Bütün bildirişlərə baxın" "TeleTypewriter aktivləşdirilib." "Zəng vibrasiyası" @@ -501,8 +496,8 @@ "İstifadə etmək üçün kiliddən çıxarın" "Kartların əldə edilməsində problem oldu, sonra yenidən cəhd edin" "Kilid ekranı ayarları" - - + "QR kod skaneri" + "Güncəllənir" "İş profili" "Təyyarə rejimi" "%1$s zaman növbəti xəbərdarlığınızı eşitməyəcəksiniz" @@ -996,4 +991,23 @@ "HHH, AAA g" "s:dd" "ss:dd" + "%1$s tətbiqini açın" + "%1$s tətbiqini qısayol kimi əlavə etmək üçün bunları təmin edin:" + "• Tətbiq ayarlanmalıdır" + "• Pulqabına ən azı bir kart əlavə edilməlidir" + "• Kamera tətbiqini quraşdırın" + "• Tətbiq ayarlanmalıdır" + "• Ən azı bir cihaz əlçatandır" + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml index 0fc6331e6752d..8478adbb9964c 100644 --- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml +++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml @@ -125,8 +125,7 @@ "Glasovna pomoć" "Novčanik" "Skener QR koda" - - + "Otključano" "Uređaj je zaključan" "Skeniranje lica" "Pošalji" @@ -169,8 +168,7 @@ "Lice nije prepoznato" "Koristite otisak prsta" - - + "Otključavanje licem nije dostupno" "Bluetooth je priključen." "Procenat napunjenosti baterije nije poznat." "Povezani ste sa %s." @@ -181,13 +179,10 @@ "Režim rada u avionu." "VPN je uključen." "Baterija je na %d posto." - - + "Baterija je na %1$d posto, %2$s" "Baterija se puni, %d posto." - - - - + "Baterija je na %d posto, punjenje je pauzirano da bi se zaštitila baterija." + "Baterija je na %1$d posto, %2$s, punjenje je pauzirano da bi se zaštitila baterija." "Pogledajte sva obaveštenja" "TeleTypewriter je omogućen." "Vibracija zvona." @@ -501,8 +496,8 @@ "Otključaj radi korišćenja" "Došlo je do problema pri preuzimanju kartica. Probajte ponovo kasnije" "Podešavanja zaključanog ekrana" - - + "Skener QR koda" + "Ažurira se" "Poslovni profil" "Režim rada u avionu" "Nećete čuti sledeći alarm u %1$s" @@ -996,4 +991,23 @@ "DDD, d. MMM" "s:min" "č:min" + "Otvorite: %1$s" + "Da biste dodali aplikaciju %1$s kao prečicu, uverite se:" + "• da je aplikacija podešena" + "• da je u Novčanik dodata barem jedna kartica" + "• da ste instalirali aplikaciju za kameru" + "• da je aplikacija podešena" + "• da je dostupan barem jedan uređaj" + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml index 85458bf2216e8..44ad22765a1a7 100644 --- a/packages/SystemUI/res/values-be/strings.xml +++ b/packages/SystemUI/res/values-be/strings.xml @@ -125,8 +125,7 @@ "Галасавая дапамога" "Кашалёк" "Сканер QR-кодаў" - - + "Разблакіравана" "Прылада заблакіравана" "Сканіраванне твару" "Адправіць" @@ -169,8 +168,7 @@ "Твар не распазнаны" "Скарыстайце адбітак пальца" - - + "Распазнаванне твару не працуе" "Bluetooth-сувязь." "Працэнт зараду акумулятара невядомы." "Падлучаны да %s." @@ -181,13 +179,10 @@ "Рэжым палёту." "VPN уключана." "Працэнт зараду акумулятара: %d." - - + "Працэнт зараду акумулятара: %1$d, %2$s" "Акумулятар зараджаецца. Бягучы зарад: %d%%." - - - - + "Працэнт зараду акумулятара: %d. Дзеля зберажэння акумулятара зарадка прыпынена." + "Працэнт зараду акумулятара: %1$d, %2$s. Дзеля зберажэння акумулятара зарадка прыпынена." "Паказаць усе апавяшчэнні" "TeleTypewriter уключаны." "Выклік з вібрацыяй." @@ -501,8 +496,8 @@ "Разблакіраваць для выкарыстання" "Узнікла праблема з загрузкай вашых карт. Паўтарыце спробу пазней" "Налады экрана блакіроўкі" - - + "Сканер QR-кодаў" + "Абнаўленне…" "Працоўны профіль" "Рэжым палёту" "Вы не пачуеце наступны будзільнік %1$s" @@ -996,4 +991,23 @@ "EEE, d MMM" "h:mm" "kk:mm" + "Адкрыць праграму \"%1$s\"" + "Каб дадаць ярлык для праграмы \"%1$s\", патрабуюцца наступныя ўмовы:" + "• Праграма наладжана." + "• У Кашалёк дададзена хаця б адна картка." + "• Усталявана праграма \"Камера\"." + "• Праграма наладжана." + "• Даступная хаця б адна прылада." + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml index 44ee85c06d5c7..240342a1cb9e8 100644 --- a/packages/SystemUI/res/values-bg/strings.xml +++ b/packages/SystemUI/res/values-bg/strings.xml @@ -125,8 +125,7 @@ "Гласова помощ" "Портфейл" "Скенер за QR кодове" - - + "Отключено" "Устройството е заключено" "Извършва се сканиране на лице" "Изпращане" @@ -169,8 +168,7 @@ "Лицето не е разпознато" "Използвайте отпечатък" - - + "„Отключване с лице“ не е налице" "Bluetooth е включен." "Процентът на батерията е неизвестен." "Има връзка с %s." @@ -181,13 +179,10 @@ "Самолетен режим." "Функцията за виртуална частна мрежа (VPN) е включена." "%d процента батерия." - - + "Батерията е на %1$d процента, до изтощаването ѝ остава %2$s" "Батерията се зарежда, %d%%." - - - - + "Батерията е на %d процента. Зареждането е поставено на пауза с цел да се запази батерията." + "Батерията е на %1$d процента, до изтощаването ѝ остава %2$s. Зареждането е поставено на пауза с цел да се запази батерията." "Вижте всички известия" "TeleTypewriter бе активиран." "Вибрира при звънене." @@ -501,8 +496,8 @@ "Отключване с цел използване" "При извличането на картите ви възникна проблем. Моля, опитайте отново по-късно" "Настройки за заключения екран" - - + "скенер за QR кодове" + "Актуализира се" "Потребителски профил в Work" "Самолетен режим" "Няма да чуете следващия си будилник в %1$s" @@ -996,4 +991,23 @@ "EEE, d MMM" "h:mm" "kk:mm" + "Отваряне на %1$s" + "За да добавите пряк път към приложението %1$s, трябва да се уверите в следното:" + "• Приложението е настроено." + "• В Wallet е добавена поне една карта." + "• Инсталирано е приложение за камера." + "• Приложението е настроено." + "• Налице е поне едно устройство." + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml index 5c4013d0f9953..5f009d763b335 100644 --- a/packages/SystemUI/res/values-bn/strings.xml +++ b/packages/SystemUI/res/values-bn/strings.xml @@ -125,8 +125,7 @@ "ভয়েস সহায়তা" "Wallet" "QR কোড স্ক্যানার" - - + "আনলক করা হয়েছে" "ডিভাইস লক করা আছে" "ফেস স্ক্যান করা হচ্ছে" "পাঠান" @@ -169,8 +168,7 @@ "ফেস শনাক্ত করা যায়নি" "পরিবর্তে ফিঙ্গারপ্রিন্ট ব্যবহার করুন" - - + "\'ফেস আনলক\' উপলভ্য নেই" "ব্লুটুথ সংযুক্ত হয়েছে৷" "ব্যাটারি কত শতাংশ আছে তা জানা যায়নি।" "%sএ সংযুক্ত হয়ে আছে।" @@ -181,13 +179,10 @@ "বিমান মোড৷" "VPN চালু আছে।" "%d শতাংশ ব্যাটারি রয়েছে৷" - - + "ব্যাটারির চার্জ %1$d শতাংশ আছে, %2$s" "ব্যাটারি চার্জ হচ্ছে, এখন %d শতাংশ চার্জ আছে৷" - - - - + "ব্যাটারির চার্জ %d শতাংশ আছে, ব্যাটারির সুরক্ষার জন্য চার্জ দেওয়া পজ করা হয়েছে।" + "ব্যাটারির চার্জ %1$d শতাংশ আছে, %2$s, ব্যাটারির সুরক্ষার জন্য চার্জ দেওয়া পজ করা হয়েছে।" "সমস্ত বিজ্ঞপ্তি দেখুন" "টেলি টাইপরাইটার সক্ষম করা আছে৷" "রিং বাজার সাথে স্পন্দিত করুন৷" @@ -501,8 +496,8 @@ "ব্যবহার করতে আনলক করুন" "আপনার কার্ড সংক্রান্ত তথ্য পেতে সমস্যা হয়েছে, পরে আবার চেষ্টা করুন" "লক স্ক্রিন সেটিংস" - - + "QR কোড স্ক্যানার খুলুন" + "আপডেট করা হচ্ছে" "কাজের প্রোফাইল" "বিমান মোড" "আপনি আপনার পরবর্তী %1$s অ্যালার্ম শুনতে পাবেন না" @@ -996,4 +991,23 @@ "EEE, MMM d" "h:mm" "kk:mm" + "%1$s খুলুন" + "শর্টকাট হিসেবে %1$s অ্যাপ যোগ করতে, এই বিষয়গুলি নিশ্চিত করুন" + "• অ্যাপ সেট-আপ করা হয়ে গেছে" + "• অন্তত একটি কার্ড Wallet-এ যোগ করা হয়েছে" + "• ক্যামেরা অ্যাপ ইনস্টল করুন" + "• অ্যাপ সেট-আপ করা হয়ে গেছে" + "• অন্তত একটি ডিভাইস উপলভ্য" + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml index 6b3c8952a0f2d..4b3da55564be9 100644 --- a/packages/SystemUI/res/values-bs/strings.xml +++ b/packages/SystemUI/res/values-bs/strings.xml @@ -125,8 +125,7 @@ "Glasovna pomoć" "Novčanik" "Skener QR koda" - - + "Otključano" "Uređaj je zaključan" "Skeniranje lica" "Pošalji" @@ -169,8 +168,7 @@ "Nije moguće prepoznati lice" "Koristite otisak prsta" - - + "Otključavanje licem je nedostupno" "Bluetooth je povezan." "Postotak napunjenosti baterije nije poznat" "Povezan na %s." @@ -181,13 +179,10 @@ "Način rada u avionu." "VPN uključen." "Baterija na %d posto." - - + "Baterija je napunjena %1$d posto. %2$s." "Punjenje baterije, %d%%." - - - - + "Baterija je napunjena %d posto. Punjenje je pauzirano radi njene zaštite." + "Baterija je napunjena %1$d posto. %2$s. Punjenje je pauzirano radi njene zaštite." "Vidite sva obavještenja" "Omogućena opcija TeleTypewriter." "Zvuk zvona na vibraciji." @@ -501,7 +496,8 @@ "Otključajte da koristite" "Došlo je do problema prilikom preuzimanja vaših kartica. Pokušajte ponovo kasnije" "Postavke zaključavanja ekrana" - "Čitač QR koda" + "Skener QR koda" + "Ažuriranje" "Profil za posao" "Način rada u avionu" "Nećete čuti sljedeći alarm u %1$s" @@ -995,4 +991,23 @@ "DDD, MMM d" "h:mm" "kk:mm" + "Otvori aplikaciju %1$s" + "Da dodate aplikaciju %1$s kao prečicu, pobrinite se za sljedeće" + "• Aplikacija je postavljena" + "• Najmanje jedna kartica je dodana u Novčanik" + "• Instalirajte aplikaciju kamere" + "• Aplikacija je postavljena" + "• Dostupan je najmanje jedan uređaj" + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml index 9892d26f0c255..25106d6386f3d 100644 --- a/packages/SystemUI/res/values-ca/strings.xml +++ b/packages/SystemUI/res/values-ca/strings.xml @@ -125,8 +125,7 @@ "Assistència per veu" "Wallet" "Escàner de codis QR" - - + "Desbloquejat" "Dispositiu bloquejat" "S\'està escanejant la cara" "Envia" @@ -169,8 +168,7 @@ "No es reconeix la cara" "Utilitza l\'empremta digital" - - + "Desbloqueig facial no està disponible" "Bluetooth connectat." "Es desconeix el percentatge de bateria." "S\'ha connectat a %s." @@ -181,13 +179,10 @@ "Mode d\'avió." "VPN activada" "%d per cent de bateria." - - + "%1$d per cent de bateria fins a les %2$s" "La bateria s\'està carregant (%d%%)." - - - - + "%d per cent de bateria; la càrrega s\'ha posat en pausa per protegir la bateria." + "%1$d per cent de bateria fins a les %2$s; la càrrega s\'ha posat en pausa per protegir la bateria." "Mostra totes les notificacions" "Teletip activat." "Mode vibració." @@ -501,8 +496,8 @@ "Desbloqueja per utilitzar" "Hi ha hagut un problema en obtenir les teves targetes; torna-ho a provar més tard" "Configuració de la pantalla de bloqueig" - - + "escàner de codis QR" + "S\'està actualitzant" "Perfil de treball" "Mode d\'avió" "%1$s no sentiràs la pròxima alarma" @@ -548,7 +543,7 @@ "Les notificacions de trucades no es poden modificar." "Aquest grup de notificacions no es pot configurar aquí" "Notificació mitjançant aplicació intermediària" - "Totes les notificacions de l\'aplicació %1$s" + "Totes les notificacions de: %1$s" "Mostra\'n més" "El sistema <b>ha augmentat a Predeterminat</b> el nivell d\'aquesta notificació." "El sistema <b>ha disminuït a Silenci</b> el nivell d\'aquesta notificació." @@ -996,4 +991,23 @@ "EEE, d MMM" "hh:mm" "kk:mm" + "Obre %1$s" + "Per afegir l\'aplicació %1$s com a drecera, assegura\'t que:" + "• L\'aplicació està configurada." + "• Almenys s\'ha afegit una targeta a Wallet." + "• Tens una aplicació de càmera." + "• L\'aplicació està configurada." + "• Almenys un dispositiu està disponible." + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml index 18894d270aec7..5c5d6372c0a2d 100644 --- a/packages/SystemUI/res/values-cs/strings.xml +++ b/packages/SystemUI/res/values-cs/strings.xml @@ -125,8 +125,7 @@ "Hlasová asistence" "Peněženka" "Čtečka QR kódů" - - + "Odemknuto" "Zařízení uzamčeno" "Skenování obličeje" "Odeslat" @@ -169,8 +168,7 @@ "Obličej nelze rozpoznat" "Použijte otisk prstu" - - + "Odemknutí obličejem není k dispozici" "Rozhraní Bluetooth je připojeno." "Procento baterie není známé." "Připojeno k zařízení %s." @@ -181,13 +179,10 @@ "Režim Letadlo." "VPN je zapnuto." "Stav baterie: %d procent." - - + "Baterie je na %1$d procentech, %2$s" "Baterie se nabíjí. Nabito: %d %%" - - - - + "Baterie je na %d procentech, nabíjení pozastaveno kvůli ochraně baterie." + "Baterie je na %1$d procentech, %2$s, nabíjení pozastaveno kvůli ochraně baterie." "Zobrazit všechna oznámení" "Rozhraní TeleTypewriter zapnuto." "Vibrační vyzvánění." @@ -501,8 +496,8 @@ "Odemknout a použít" "Při načítání karet došlo k problému, zkuste to později" "Nastavení obrazovky uzamčení" - - + "Čtečka QR kódů" + "Probíhá aktualizace" "Pracovní profil" "Režim Letadlo" "Svůj další budík %1$s neuslyšíte" @@ -996,4 +991,23 @@ "EEE d. MMMM" "h:mm" "H:mm" + "Otevřít %1$s" + "Podmínky pro to, aby aplikaci %1$s bylo možné přidat jako zkratku:" + "• Aplikace je nastavena" + "• Do Peněženky byla přidána alespoň jedna karta" + "• Je nainstalována aplikace pro fotoaparát" + "• Aplikace je nastavena" + "• Je k dispozici alespoň jedno zařízení" + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml index 8dbe9786f17fb..5831983beed10 100644 --- a/packages/SystemUI/res/values-da/strings.xml +++ b/packages/SystemUI/res/values-da/strings.xml @@ -125,8 +125,7 @@ "Taleassistent" "Wallet" "QR-kodescanner" - - + "Låst op" "Enheden er låst" "Scanner ansigt" "Send" @@ -169,8 +168,7 @@ "Ansigt kan ikke genkendes" "Brug fingeraftryk i stedet" - - + "Ansigtslås er utilgængelig" "Bluetooth tilsluttet." "Batteriniveauet er ukendt." "Tilsluttet %s." @@ -181,13 +179,10 @@ "Flytilstand." "VPN er slået til." "Batteri %d procent." - - + "Batteriniveauet er på %1$d procent, %2$s" "Batteriet oplades. %d %%." - - - - + "Batteriniveauet er på %d procent, opladning er sat på pause for at beskytte batteriet." + "Batteriniveauet er på %1$d procent, %2$s, opladning er sat på pause for at beskytte batteriet." "Se alle notifikationer" "TeleTypewriter aktiveret." "Ringervibration." @@ -501,8 +496,8 @@ "Lås op for at bruge" "Dine kort kunne ikke hentes. Prøv igen senere." "Lås skærmindstillinger" - - + "QR-kodescanner" + "Opdaterer" "Arbejdsprofil" "Flytilstand" "Du vil ikke kunne høre din næste alarm %1$s" @@ -996,4 +991,23 @@ "EEE d. MMM" "tt.mm" "kk.mm" + "Åbn %1$s" + "Før du tilføjer %1$s-appen som en genvej, skal du sørge for følgende:" + "• Appen er konfigureret" + "• Mindst ét kort er føjet til Wallet" + "• Installer en kameraapp" + "• Appen er konfigureret" + "• Mindst én enhed er tilgængelig" + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml index 5191b47a2c68d..a0a18d211c81b 100644 --- a/packages/SystemUI/res/values-de/strings.xml +++ b/packages/SystemUI/res/values-de/strings.xml @@ -125,8 +125,7 @@ "Sprachassistent" "Wallet" "QR-Code-Scanner" - - + "Entsperrt" "Gerät gesperrt" "Gesicht wird gescannt" "Senden" @@ -169,8 +168,7 @@ "Gesicht nicht erkannt" "Fingerabdruck verwenden" - - + "Entsperrung per Gesichtserkennung nicht verfügbar" "Mit Bluetooth verbunden" "Akkustand unbekannt." "Mit %s verbunden" @@ -181,13 +179,10 @@ "Flugmodus" "VPN an." "Akku bei %d Prozent." - - + "Akku bei %1$d, %2$s" "Akku wird aufgeladen, %d Prozent." - - - - + "Akku bei %d. Zum Schutz des Akkus wurde das Laden pausiert." + "Akku bei %1$d. %2$s. Zum Schutz des Akkus wurde das Laden pausiert." "Alle Benachrichtigungen ansehen" "Schreibtelefonie aktiviert" "Klingeltonmodus \"Vibration\"" @@ -501,8 +496,8 @@ "Zum Verwenden entsperren" "Beim Abrufen deiner Karten ist ein Fehler aufgetreten – bitte versuch es später noch einmal" "Einstellungen für den Sperrbildschirm" - - + "QR-Code-Scanner" + "Wird aktualisiert…" "Arbeitsprofil" "Flugmodus" "Lautloser Weckruf %1$s" @@ -996,4 +991,23 @@ "EEE, d. MMM" "h:mm" "kk:mm" + "%1$s öffnen" + "Wenn du die %1$s App als eine Verknüpfung hinzufügen möchtest, müssen folgende Bedingungen erfüllt sein" + "• Die App ist eingerichtet" + "• Wallet wurde mindestens eine Karte hinzugefügt" + "• Kamera-App ist installiert" + "• Die App ist eingerichtet" + "• Mindestens ein Gerät ist verfügbar" + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml index 448e1e03acb58..bd63f4132685a 100644 --- a/packages/SystemUI/res/values-el/strings.xml +++ b/packages/SystemUI/res/values-el/strings.xml @@ -125,8 +125,7 @@ "Φωνητική υποβοήθηση" "Πορτοφόλι" "Σάρωση κωδικών QR" - - + "Ξεκλειδώθηκε" "Η συσκευή κλειδώθηκε" "Σάρωση προσώπου" "Αποστολή" @@ -169,8 +168,7 @@ "Αδύνατη η αναγν. προσώπου" "Χρησιμ. δακτυλ. αποτύπ." - - + "Ξεκλ. με πρόσωπο μη διαθ." "Το Bluetooth είναι συνδεδεμένο." "Άγνωστο ποσοστό μπαταρίας." "Συνδέθηκε στο %s." @@ -181,13 +179,10 @@ "Λειτουργία πτήσης." "VPN ενεργό." "Μπαταρία %d τοις εκατό." - - + "Μπαταρία %1$d τοις εκατό, %2$s" "Φόρτιση μπαταρίας: %d%%." - - - - + "Μπαταρία %d τοις εκατό, η φόρτιση τέθηκε σε παύση για την προστασία της μπαταρίας." + "Μπαταρία %1$d τοις εκατό, %2$s, η φόρτιση τέθηκε σε παύση για την προστασία της μπαταρίας." "Δείτε όλες τις ειδοποιήσεις" "Το TeleTypewriter ενεργοποιήθηκε." "Δόνηση ειδοποίησης ήχου." @@ -502,6 +497,7 @@ "Παρουσιάστηκε πρόβλημα με τη λήψη των καρτών σας. Δοκιμάστε ξανά αργότερα" "Ρυθμίσεις κλειδώματος οθόνης" "Σάρωση κωδικών QR" + "Ενημέρωση" "Προφίλ εργασίας" "Λειτουργία πτήσης" "Δεν θα ακούσετε το επόμενο ξυπνητήρι σας %1$s" @@ -995,4 +991,23 @@ "ΗΗΗ, ΜΜΜ η" "ώ:λλ" "kk:λλ" + "Άνοιγμα %1$s" + "Για να προσθέσετε την εφαρμογή %1$s ως συντόμευση, βεβαιωθείτε ότι" + "• Η εφαρμογή έχει ρυθμιστεί" + "• Έχει προστεθεί τουλάχιστον μία κάρτα στο Πορτοφόλι" + "• Εγκαταστήσατε μια εφαρμογή κάμερας" + "• Η εφαρμογή έχει ρυθμιστεί" + "• Είναι διαθέσιμη τουλάχιστον μία συσκευή" + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml index bfa63f6e0a596..f9bdb0f682a74 100644 --- a/packages/SystemUI/res/values-en-rAU/strings.xml +++ b/packages/SystemUI/res/values-en-rAU/strings.xml @@ -168,8 +168,7 @@ "Can’t recognise face" "Use fingerprint instead" - - + "Face Unlock unavailable" "Bluetooth connected." "Battery percentage unknown." "Connected to %s." @@ -180,13 +179,10 @@ "Aeroplane mode" "VPN on." "Battery %d per cent." - - + "Battery %1$d per cent; %2$s" "Battery charging, %d percent." - - - - + "Battery %d per cent; charging paused for battery protection." + "Battery %1$d per cent; %2$s, charging paused for battery protection." "See all notifications" "TeleTypewriter enabled." "Ringer vibrate." @@ -501,6 +497,7 @@ "There was a problem getting your cards. Please try again later." "Lock screen settings" "QR code scanner" + "Updating" "Work profile" "Aeroplane mode" "You won\'t hear your next alarm %1$s" @@ -994,4 +991,17 @@ "EEE, MMM d" "h:mm" "kk:mm" + "Open %1$s" + "To add the %1$s app as a shortcut, make sure" + "• The app is set up" + "• At least one card has been added to Wallet" + "• Install a camera app" + "• The app is set up" + "• At least one device is available" + "Cancel" + "Flip now" + "Unfold phone for a better selfie" + "Flip to front display for a better selfie?" + "Use the rear-facing camera for a wider photo with higher resolution." + "✱ This screen will turn off" diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml index 879d88b8a7e61..8a55b0be2fe90 100644 --- a/packages/SystemUI/res/values-en-rCA/strings.xml +++ b/packages/SystemUI/res/values-en-rCA/strings.xml @@ -168,8 +168,7 @@ "Can’t recognize face" "Use fingerprint instead" - - + "Face Unlock unavailable" "Bluetooth connected." "Battery percentage unknown." "Connected to %s." @@ -180,13 +179,10 @@ "Airplane mode." "VPN on." "Battery %d percent." - - + "Battery %1$d percent, %2$s" "Battery charging, %d percent." - - - - + "Battery %d percent, charging paused for battery protection." + "Battery %1$d percent, %2$s, charging paused for battery protection." "See all notifications" "TeleTypewriter enabled." "Ringer vibrate." @@ -370,7 +366,7 @@ "All apps and data of this user will be deleted." "Remove" "%s will have access to all of the information that is visible on your screen or played from your device while recording or casting. This includes information such as passwords, payment details, photos, messages, and audio that you play." - "The service providing this function will have access to all of the information that is visible on your screen or played from your device while recording or casting. This includes information such as passwords, payment details, photos, messages, and audio that you play." + "The service providing this function will have access to all of the information that\'s visible on your screen or played from your device while recording or casting. This includes information such as passwords, payment details, photos, messages and audio that you play." "Start recording or casting?" "Start recording or casting with %s?" "Allow %s to share or record?" @@ -501,6 +497,7 @@ "There was a problem getting your cards, please try again later" "Lock screen settings" "QR code scanner" + "Updating" "Work profile" "Airplane mode" "You won\'t hear your next alarm %1$s" @@ -994,4 +991,17 @@ "EEE, MMM d" "h:mm" "kk:mm" + "Open %1$s" + "To add the %1$s app as a shortcut, make sure" + "• The app is set up" + "• At least one card has been added to Wallet" + "• Install a camera app" + "• The app is set up" + "• At least one device is available" + "Cancel" + "Flip now" + "Unfold phone for a better selfie" + "Flip to front display for a better selfie?" + "Use the rear-facing camera for a wider photo with higher resolution." + "✱ This screen will turn off" diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml index bfa63f6e0a596..f9bdb0f682a74 100644 --- a/packages/SystemUI/res/values-en-rGB/strings.xml +++ b/packages/SystemUI/res/values-en-rGB/strings.xml @@ -168,8 +168,7 @@ "Can’t recognise face" "Use fingerprint instead" - - + "Face Unlock unavailable" "Bluetooth connected." "Battery percentage unknown." "Connected to %s." @@ -180,13 +179,10 @@ "Aeroplane mode" "VPN on." "Battery %d per cent." - - + "Battery %1$d per cent; %2$s" "Battery charging, %d percent." - - - - + "Battery %d per cent; charging paused for battery protection." + "Battery %1$d per cent; %2$s, charging paused for battery protection." "See all notifications" "TeleTypewriter enabled." "Ringer vibrate." @@ -501,6 +497,7 @@ "There was a problem getting your cards. Please try again later." "Lock screen settings" "QR code scanner" + "Updating" "Work profile" "Aeroplane mode" "You won\'t hear your next alarm %1$s" @@ -994,4 +991,17 @@ "EEE, MMM d" "h:mm" "kk:mm" + "Open %1$s" + "To add the %1$s app as a shortcut, make sure" + "• The app is set up" + "• At least one card has been added to Wallet" + "• Install a camera app" + "• The app is set up" + "• At least one device is available" + "Cancel" + "Flip now" + "Unfold phone for a better selfie" + "Flip to front display for a better selfie?" + "Use the rear-facing camera for a wider photo with higher resolution." + "✱ This screen will turn off" diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml index bfa63f6e0a596..f9bdb0f682a74 100644 --- a/packages/SystemUI/res/values-en-rIN/strings.xml +++ b/packages/SystemUI/res/values-en-rIN/strings.xml @@ -168,8 +168,7 @@ "Can’t recognise face" "Use fingerprint instead" - - + "Face Unlock unavailable" "Bluetooth connected." "Battery percentage unknown." "Connected to %s." @@ -180,13 +179,10 @@ "Aeroplane mode" "VPN on." "Battery %d per cent." - - + "Battery %1$d per cent; %2$s" "Battery charging, %d percent." - - - - + "Battery %d per cent; charging paused for battery protection." + "Battery %1$d per cent; %2$s, charging paused for battery protection." "See all notifications" "TeleTypewriter enabled." "Ringer vibrate." @@ -501,6 +497,7 @@ "There was a problem getting your cards. Please try again later." "Lock screen settings" "QR code scanner" + "Updating" "Work profile" "Aeroplane mode" "You won\'t hear your next alarm %1$s" @@ -994,4 +991,17 @@ "EEE, MMM d" "h:mm" "kk:mm" + "Open %1$s" + "To add the %1$s app as a shortcut, make sure" + "• The app is set up" + "• At least one card has been added to Wallet" + "• Install a camera app" + "• The app is set up" + "• At least one device is available" + "Cancel" + "Flip now" + "Unfold phone for a better selfie" + "Flip to front display for a better selfie?" + "Use the rear-facing camera for a wider photo with higher resolution." + "✱ This screen will turn off" diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml index 5f0be61c72287..0c4c62a407079 100644 --- a/packages/SystemUI/res/values-en-rXC/strings.xml +++ b/packages/SystemUI/res/values-en-rXC/strings.xml @@ -168,8 +168,7 @@ "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‎‎‎‏‎‎‏‏‏‏‎‎‎‏‎‎‏‎‎‏‏‏‎‎‏‏‎‎‎‎‏‎‎‎‎‏‏‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‏‏‎Can’t recognize face‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‎‏‎‏‎‏‎‎‎‏‏‏‏‎‎‎‎‏‎‎‏‏‎‎‏‏‎‏‎‎‎‎‎‏‏‎‎‏‎‏‎‎‏‏‏‎‏‎‎‎‎‏‏‏‎‎‎‎‎Use fingerprint instead‎‏‎‎‏‎" - - + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‏‎‏‏‏‏‏‎‏‎‎‎‎‏‏‎‏‏‎‎‏‎‎‎‏‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‏‎‏‏‎‏‏‏‎‏‏‏‏‏‎‎‎‎‎Face Unlock unavailable‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‏‏‏‎‏‏‎‏‎‎‏‎‏‎‎‏‏‎‏‏‎‏‎‏‎‏‎‎‏‎‎‎‎‏‏‏‎‏‎‎‏‏‎‏‏‏‏‎‏‏‏‎‎‎‏‎‏‎Bluetooth connected.‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‏‎‎‎‏‎‏‏‎‏‎‎‎‏‏‏‏‎‎‎‎‎‏‎‏‏‎‎‏‎‏‏‏‏‎‏‎‏‎‏‎‏‎‎‎‎‏‏‎‎‏‏‏‏‎‎‎‎Battery percentage unknown.‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‎‏‎‏‎‎‏‎‎‏‎‎‎‏‎‎‎‏‏‏‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‎‏‎‏‏‏‎‏‏‎‏‎‏‏‏‎‏‏‏‏‎‎Connected to ‎‏‎‎‏‏‎%s‎‏‎‎‏‏‏‎.‎‏‎‎‏‎" @@ -180,13 +179,10 @@ "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‎‎‏‎‏‏‏‎‎‎‏‏‏‏‎‏‏‏‏‎‎‎‎‎‏‏‎‎‎‏‎‏‏‏‎‏‏‎‎‎‎‎‏‎‎‏‏‎‏‏‎‏‎‏‎‎‏‎Airplane mode.‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‏‏‏‎‎‎‏‎‏‏‎‎‎‏‏‏‎‎‏‏‎‏‏‏‎‏‎‎‏‎‎‎‏‎‎‎‎‎‏‎‏‏‎‎‏‎‏‎‎‎‎‎‎‏‏‎‏‏‎VPN on.‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‏‏‏‎‏‏‎‎‎‏‎‎‎‏‎‎‏‎‏‏‏‏‎‏‎‎‎‏‎‎‏‎‎‏‏‎‎‎‏‏‎‏‎‎‎‏‏‏‏‏‎‏‎‎‎‎‏‏‎‎Battery ‎‏‎‎‏‏‎%d‎‏‎‎‏‏‏‎ percent.‎‏‎‎‏‎" - - + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‏‏‎‎‎‎‏‎‏‏‏‏‏‏‎‏‎‏‎‎‏‏‏‎‎‎‏‏‎‎‎‏‏‎‏‏‎‏‏‎‏‎‎‏‎‎‏‏‏‏‎‎‎‎‏‎Battery ‎‏‎‎‏‏‎%1$d‎‏‎‎‏‏‏‎ percent, ‎‏‎‎‏‏‎%2$s‎‏‎‎‏‏‏‎‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‏‎‏‏‎‏‏‎‎‏‏‏‎‏‏‎‏‎‎‎‏‏‎‎‎‎‏‏‎‏‏‎‏‎‏‎‎‎‎‏‎‏‎‏‎‏‎‏‎‎‏‎‎‏‏‎‎‏‎‎‎Battery charging, ‎‏‎‎‏‏‎%d‎‏‎‎‏‏‏‎ percent.‎‏‎‎‏‎" - - - - + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‏‎‏‏‎‏‎‏‎‎‎‏‏‎‎‎‎‎‎‏‏‏‏‎‏‏‎‏‎‏‎‎‎‏‏‏‎‏‏‏‎‏‎‎‏‏‏‎‏‎‎‎‎‏‎‏‏‎Battery ‎‏‎‎‏‏‎%d‎‏‎‎‏‏‏‎ percent, charging paused for battery protection.‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‏‎‏‏‎‏‏‎‏‏‏‎‎‏‏‎‏‎‏‏‏‏‎‏‎‎‏‏‏‎‏‎‏‏‎‎‎‎‏‏‎‎‏‎‏‏‎‏‎‎‎‏‏‏‎‎‏‎‎Battery ‎‏‎‎‏‏‎%1$d‎‏‎‎‏‏‏‎ percent, ‎‏‎‎‏‏‎%2$s‎‏‎‎‏‏‏‎, charging paused for battery protection.‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‏‏‏‎‎‎‏‏‎‏‏‏‏‎‏‎‏‏‎‏‎‏‏‎‏‏‏‏‏‎‏‏‎‎‎‎‎‏‏‏‎‎‏‏‎‎‎‏‏‎‎‎‎‎See all notifications‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‏‏‏‏‎‎‏‎‏‏‎‎‏‎‏‎‏‏‎‏‎‎‏‏‏‎‎‏‏‎‏‏‏‏‎‏‎‎‎‎‎‎‎‏‎‏‏‎‏‎‎‎‏‏‏‏‏‏‎‎TeleTypewriter enabled.‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‎‏‏‏‎‎‏‏‎‏‎‎‎‎‏‏‏‎‏‎‏‏‏‏‎‎‏‎‎‎‏‏‏‎‎‏‏‎‏‎‎‏‎‏‎‎‏‎‎‏‏‎‏‎‏‎‎‎Ringer vibrate.‎‏‎‎‏‎" @@ -501,6 +497,7 @@ "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‎‏‏‏‎‎‏‎‎‏‏‏‎‎‎‏‏‎‎‏‏‏‏‎‎‎‎‏‏‏‏‎‎‏‎‏‏‎‎‎‎‎‎‎‎‎‏‎‎‎‏‏‎‎‏‏‎‏‏‎There was a problem getting your cards, please try again later‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‏‎‎‎‏‏‏‎‏‎‏‏‎‏‏‎‏‏‎‎‎‎‏‎‏‎‎‏‎‏‎‎‏‎‎‎‏‎‏‎‎‏‏‎‎‎‏‏‏‏‏‎‏‎‎‏‎‎Lock screen settings‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‏‎‏‏‏‎‎‏‎‏‏‎‏‏‎‏‏‎‎‏‎‏‎‏‎‎‏‎‎‎‎‎‎‏‏‏‏‎‎‏‏‎‏‏‎‎‏‎‏‎‏‎‏‏‏‏‏‎‎QR code scanner‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‏‎‎‏‏‎‏‏‏‏‏‎‏‏‏‏‎‏‎‏‏‏‏‎‏‎‏‎‏‎‏‎‎‏‎‏‏‏‎‏‏‏‏‏‎‎‏‎‎‎‎‎‎‎‎‎Updating‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‎‏‎‏‏‎‎‏‏‎‏‏‎‎‏‎‏‎‎‎‏‏‎‎‏‎‎‎‎‏‏‎‏‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‏‏‏‏‎‎‎‎‎Work profile‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‏‏‎‏‎‎‏‎‏‎‎‎‎‎‏‏‎‏‎‎‏‏‏‏‎‏‏‏‏‏‏‎‏‏‏‎‏‎‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‎‎‏‎Airplane mode‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‎‏‏‏‎‎‏‎‎‏‎‎‎‎‎‎‏‏‏‏‎‎‎‎‎‎‏‎‎‎‎‏‏‏‎‏‎‎‎‏‏‏‎‏‏‏‏‏‎‏‏‏‏‏‎You won\'t hear your next alarm ‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎‎‏‎‎‏‎" @@ -994,4 +991,17 @@ "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‏‏‎‏‎‏‏‎‏‎‎‎‏‎‏‎‎‎‎‎‏‎‎‏‎‎‏‏‎‎‏‏‎‎‎‏‏‏‎‏‎‎‎‏‏‏‏‏‎‎‎‎‎‏‎‎‎‎EEE, MMM d‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‏‎‎‎‏‏‎‏‎‎‏‏‏‏‎‏‏‎‏‎‎‎‎‏‎‎‏‎‏‎‏‎‏‎‏‏‎‎‎‎‏‎‏‎‎‏‏‏‏‎‏‎‎‏‎‎‏‎h:mm‎‏‎‎‏‎" "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‏‎‏‎‏‏‎‏‏‎‎‏‎‏‏‎‏‎‎‎‏‏‎‏‎‏‏‎‏‏‎‏‎‎‏‎‏‎‎‏‎‏‎‏‎‎‏‏‏‎‎‏‏‎‏‏‎‏‎kk:mm‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‎‏‎‏‎‎‏‏‏‏‎‏‏‎‎‏‏‎‏‏‏‏‎‏‏‏‏‎‎‏‎‏‏‏‏‏‎‏‎‏‎‏‏‎‏‎‎‏‎‎‎‎‏‎‏‎‎‎‎Open ‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‎‏‏‎‏‎‏‏‏‎‏‏‎‏‎‎‏‏‏‎‎‏‏‏‎‏‎‏‎‏‏‏‏‎‎‎‎‏‏‎‏‏‏‏‏‏‎‎‏‏‏‏‏‎‎‎‎‏‎‏‎To add the ‎‏‎‎‏‏‎%1$s‎‏‎‎‏‏‏‎ app as a shortcut, make sure‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‎‏‏‏‏‏‏‎‏‎‏‏‎‏‏‎‎‎‏‏‎‏‎‏‎‎‏‏‏‎‏‏‎‎‏‏‏‏‏‎‎‏‎‎‏‏‎‎‎‎‏‏‏‎‎• The app is set up‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‎‏‏‏‏‏‏‎‏‏‏‏‎‎‏‎‏‏‏‏‏‎‎‎‏‏‏‏‎‎‎‎‎‏‎‏‎‎‎‎‏‏‏‎‏‏‎‎‏‎‏‏‏‎‎‏‎‏‏‎• At least one card has been added to Wallet‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‏‎‎‏‎‏‎‎‏‏‏‏‎‎‎‎‏‏‎‏‎‎‎‏‎‎‎‎‎‏‏‏‏‏‏‏‎‎‏‎‎‏‎‎‏‎‎‎‏‏‏‏‏‎‏‏‏‏‎• Install a camera app‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‏‎‎‎‏‏‎‏‎‏‏‏‎‎‏‏‏‎‏‎‎‏‏‎‏‎‏‏‏‏‎‎‎‎‏‏‎‎‏‏‏‎‎‏‎‎‎‏‎‏‎‏‏‏‎‎‏‎• The app is set up‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‎‏‎‎‏‏‎‏‏‏‎‎‏‏‏‏‏‏‎‏‎‎‎‏‎‏‏‎‏‎‎‏‎‎‏‏‏‎‏‎‏‏‏‏‏‏‏‎‏‏‎‏‎‏‎‎‎• At least one device is available‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‎‎‎‎‎‎‏‎‎‏‏‎‎‏‏‎‏‏‏‎‎‏‎‏‎‏‏‎‎‏‏‏‎‎‏‏‎‎‎‎‏‎‎‏‏‎‏‏‏‎‏‏‎‎‎‎‎‎‎Cancel‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‏‏‎‎‏‏‎‏‎‏‎‎‏‏‎‎‏‏‏‏‏‎‎‎‏‏‎‏‏‎‏‎‏‎‎‎‎‏‏‎‏‏‎‏‎‏‏‏‏‏‎‎‏‎‎‏‎‏‏‎‎Flip now‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‎‎‏‏‎‎‏‎‏‏‏‏‏‏‎‏‎‎‏‏‏‏‎‏‎‏‏‏‎‏‎‎‎‎‎‏‏‏‎‎‎‏‏‏‎‏‏‎‎‎‎‎‎‏‏‎‎‎Unfold phone for a better selfie‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‏‎‏‏‎‏‎‏‎‎‏‏‎‎‏‎‏‎‏‎‏‏‎‏‏‏‏‎‎‏‏‎‎‎‏‎‎‎‎‎‏‏‎‎‎‎‎‎‎‎‎‎‏‎‎‎‏‎‏‎Flip to front display for a better selfie?‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‏‎‎‏‏‎‏‏‎‏‎‏‏‏‏‏‏‎‏‏‎‎‏‎‏‎‏‎‏‏‎‎‎‎‏‏‎‏‎‎‏‏‏‏‏‏‎‎‎‏‎‏‎‏‏‏‎‎‎‎‎Use the rear-facing camera for a wider photo with higher resolution.‎‏‎‎‏‎" + "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‎‏‎‏‏‎‎‎‏‏‏‎‏‏‎‏‏‎‏‎‏‏‎‎‎‏‎‏‏‏‎‎‎‎‎‏‏‏‏‎‎‏‏‏‎‎‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‎‎‏‎‎‏‏‎""‎‏‎‎‏‏‏‎✱ This screen will turn off‎‏‎‎‏‏‎""‎‏‎‎‏‏‏‎‎‏‎‎‏‎" diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml index 639e50d0b22ed..d0908ab88c033 100644 --- a/packages/SystemUI/res/values-es-rUS/strings.xml +++ b/packages/SystemUI/res/values-es-rUS/strings.xml @@ -125,8 +125,7 @@ "Asistente voz" "Billetera" "Escáner de código QR" - - + "Desbloqueado" "Dispositivo bloqueado" "Escaneando rostro" "Enviar" @@ -169,8 +168,7 @@ "No se reconoce el rostro" "Usa la huella dactilar" - - + "Desbloqueo facial no disponible" "Bluetooth conectado" "Se desconoce el porcentaje de la batería." "Conectado a %s" @@ -181,13 +179,10 @@ "Modo de avión" "VPN activada" "Batería %d por ciento" - - + "Batería: %1$d por ciento; %2$s" "Batería cargando: %d%%" - - - - + "Batería: %d por ciento. Se pausó la carga para proteger la batería." + "Batería: %1$d por ciento. %2$s. Se pausó la carga para proteger la batería." "Ver todas las notificaciones" "Teletipo habilitado" "Timbre en vibración" @@ -501,8 +496,8 @@ "Desbloquear para usar" "Ocurrió un problema al obtener las tarjetas; vuelve a intentarlo más tarde" "Configuración de pantalla de bloqueo" - - + "Escáner de código QR" + "Actualizando" "Perfil de trabajo" "Modo de avión" "No oirás la próxima alarma a la(s) %1$s" @@ -996,4 +991,23 @@ "EEE, d de MMM" "h:mm" "kk:mm" + "Abrir %1$s" + "Para agregar la app %1$s como acceso directo, asegúrate que se cumplan los siguientes requisitos:" + "• Se configuró la app." + "• Se agregó al menos una tarjeta a la Billetera." + "• Se instaló la app de Cámara." + "• Se configuró la app." + "• Hay al menos un dispositivo disponible." + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml index 9acbe6f1b884c..bd8ef36d56e1b 100644 --- a/packages/SystemUI/res/values-es/strings.xml +++ b/packages/SystemUI/res/values-es/strings.xml @@ -125,8 +125,7 @@ "Asistente voz" "Wallet" "Escáner de códigos QR" - - + "Desbloqueado" "Dispositivo bloqueado" "Escaneando cara" "Enviar" @@ -169,8 +168,7 @@ "No se reconoce la cara" "Usa la huella digital" - - + "Desbloqueo facial no disponible" "Bluetooth conectado" "Porcentaje de batería desconocido." "Conectado a %s." @@ -181,13 +179,10 @@ "Modo Avión" "La red VPN está activada." "%d por ciento de batería" - - + "Batería al %1$d por ciento, %2$s" "Batería cargándose (%d %%)." - - - - + "Batería al %d por ciento, carga pausada para proteger la batería." + "Batería al %1$d por ciento, %2$s, carga pausada para proteger la batería." "Ver todas las notificaciones" "Teletipo habilitado" "Modo vibración" @@ -501,8 +496,8 @@ "Desbloquear para usar" "Se ha producido un problema al obtener tus tarjetas. Inténtalo de nuevo más tarde." "Ajustes de pantalla de bloqueo" - - + "Escáner de códigos QR" + "Actualizando" "Perfil de trabajo" "Modo Avión" "No oirás la próxima alarma (%1$s)" @@ -996,4 +991,23 @@ "EEE, d MMM" "h:mm" "kk:mm" + "Abrir %1$s" + "Para añadir la aplicación %1$s como acceso directo:" + "• La aplicación debe estar configurada" + "• Se debe haber añadido al menos una tarjeta a Wallet" + "• Debes instalar una aplicación de cámara" + "• La aplicación debe estar configurada" + "• Al menos un dispositivo debe estar disponible" + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml index 55ace2faa4393..5a783c4284a7f 100644 --- a/packages/SystemUI/res/values-et/strings.xml +++ b/packages/SystemUI/res/values-et/strings.xml @@ -125,8 +125,7 @@ "Häälabi" "Wallet" "QR-koodi skanner" - - + "Avatud" "Seade on lukustatud" "Näo skannimine" "Saada" @@ -169,8 +168,7 @@ "Nägu ei õnnestu tuvastada" "Kasutage sõrmejälge" - - + "Näoga avamine pole saadaval" "Bluetooth on ühendatud." "Aku laetuse protsent on teadmata." "Ühendatud: %s." @@ -181,13 +179,10 @@ "Lennukirežiim." "VPN on sees." "Aku: %d protsenti." - - + "Aku: %1$d protsenti; akutoite kestus: %2$s." "Akut laetakse (%d%%)." - - - - + "Aku on %d protsenti laetud, laadimine on aku kaitsmiseks peatatud." + "Aku on %1$d protsenti laetud; akutoite kestus: %2$s; laadimine on aku kaitsmiseks peatatud." "Kõikide märguannete kuvamine" "TeleTypewriter lubatud." "Vibreeriv kõlisti." @@ -501,8 +496,8 @@ "Avage kasutamiseks" "Teie kaartide hankimisel ilmnes probleem, proovige hiljem uuesti" "Lukustuskuva seaded" - - + "QR-koodi skanner" + "Värskendamine" "Tööprofiil" "Lennukirežiim" "Te ei kuule järgmist äratust kell %1$s" @@ -996,4 +991,23 @@ "EEE, d. MMM" "h:mm" "kk:mm" + "Ava %1$s" + "Rakenduse %1$s otsetee lisamiseks veenduge järgmises." + "• Rakendus on seadistatud" + "• Vähemalt üks kaart on Walletisse lisatud" + "• Installige kaamerarakendus" + "• Rakendus on seadistatud" + "• Vähemalt üks seade on saadaval" + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml index 89f1ebe163a96..d45bf6fda63e6 100644 --- a/packages/SystemUI/res/values-eu/strings.xml +++ b/packages/SystemUI/res/values-eu/strings.xml @@ -125,8 +125,7 @@ "Ahots-laguntza" "Diru-zorroa" "QR kodeen eskanerra" - - + "Desblokeatuta" "Gailua blokeatuta dago" "Aurpegia eskaneatzen" "Bidali" @@ -169,8 +168,7 @@ "Ezin da ezagutu aurpegia" "Erabili hatz-marka" - - + "Aurpegi bidez desblokeatzeko eginbidea ez dago erabilgarri" "Bluetootha konektatuta." "Bateriaren ehunekoa ezezaguna da." "%s gailura konektatuta." @@ -181,13 +179,10 @@ "Hegaldi-modua" "VPN eginbidea aktibatuta." "Bateriaren karga: %d." - - + "Bateriak ehuneko %1$d dauka, %2$s" "Kargatzen ari da bateria. Ehuneko %d arte kargatu da oraingoz." - - - - + "Bateriak ehuneko %d dauka, kargatze-prozesua pausatuta dago bateria babesteko." + "Bateriak ehuneko %1$d dauka, %2$s, kargatze-prozesua pausatuta dago bateria babesteko." "Ikusi jakinarazpen guztiak" "TeleTypewriter gaituta." "Tonu-jotzailea dardara moduan." @@ -501,7 +496,8 @@ "Desblokeatu erabiltzeko" "Arazo bat izan da txartelak eskuratzean. Saiatu berriro geroago." "Pantaila blokeatuaren ezarpenak" - + "QR kodeen eskanerra" + "Work profila" "Hegaldi modua" @@ -996,4 +992,24 @@ "EEE, MMM d" "h:mm" "kk:mm" + + + + + + + + + + + + + + + "Utzi" + "Irauli" + "Ireki telefonoa autoargazki hobeak ateratzeko" + "Telefonoa irauli nahi duzu autoargazki hobeak ateratzeko?" + "Erabili atzeko kamera kalitate handiagoko argazki zabalago bat ateratzeko." + "✱ Pantaila itzali egingo da" diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml index 1a8553cf0e5ce..3d4e38b4e3aa0 100644 --- a/packages/SystemUI/res/values-fa/strings.xml +++ b/packages/SystemUI/res/values-fa/strings.xml @@ -125,8 +125,7 @@ "دستیار صوتی" "کیف پول" "کدخوان پاسخ‌سریع" - - + "قفل‌نشده" "دستگاه قفل است" "درحال اسکن کردن چهره" "ارسال" @@ -169,8 +168,7 @@ "چهره شناسایی نشد" "از اثر انگشت استفاده کنید" - - + "«قفل‌گشایی با چهره» دردسترس نیست" "بلوتوث متصل است." "درصد شارژ باتری مشخص نیست." "به %s متصل شد." @@ -181,13 +179,10 @@ "حالت هواپیما." "‏VPN روشن است." "باتری %d درصد." - - + "درصد شارژ باتری: %1$d، %2$s" "در حال شارژ باتری، %d درصد" - - - - + "درصد شارژ باتری: %d، شارژ شدن برای محافظت از باتری موقتاً متوقف شد." + "درصد شارژ باتری: %1$d، %2$s، شارژ شدن برای محافظت از باتری موقتاً متوقف شد." "دیدن همه اعلان‌ها" "تله‌تایپ فعال شد." "زنگ لرزشی." @@ -501,8 +496,8 @@ "برای استفاده، قفل را باز کنید" "هنگام دریافت کارت‌ها مشکلی پیش آمد، لطفاً بعداً دوباره امتحان کنید" "تنظیمات صفحه قفل" - - + "کدخوان پاسخ‌سریع" + "درحال به‌روزرسانی" "نمایه کاری" "حالت هواپیما" "در ساعت %1$s، دیگر صدای زنگ ساعت را نمی‌شنوید" @@ -996,4 +991,23 @@ "EEE d MMM" "h:mm" "kk:mm" + "باز کردن %1$s" + "برای افزودن برنامه %1$s به‌عنوان میان‌بر، مطمئن شوید" + "• برنامه راه‌اندازی شده باشد" + "• حداقل یک کارت به «کیف پول» اضافه شده باشد" + "• برنامه دوربین نصب شده باشد" + "• برنامه راه‌اندازی شده باشد" + "• حداقل یک دستگاه دردسترس باشد" + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml index 12e9797e783b7..e228c0a786ffa 100644 --- a/packages/SystemUI/res/values-fi/strings.xml +++ b/packages/SystemUI/res/values-fi/strings.xml @@ -125,8 +125,7 @@ "Ääniapuri" "Wallet" "QR-koodiskanneri" - - + "Lukitus avattu" "Laite lukittu" "Kasvojen skannaus" "Lähetä" @@ -169,8 +168,7 @@ "Kasvoja ei voi tunnistaa" "Käytä sormenjälkeä" - - + "Kasvojentunnistusavaus ei ole saatavilla" "Bluetooth yhdistetty." "Akun varaustaso ei tiedossa." "Yhteys: %s." @@ -181,13 +179,10 @@ "Lentokonetila." "VPN päällä" "Akun virta %d prosenttia." - - + "Akun virta %1$d prosenttia, %2$s" "Akku latautuu: %d prosenttia" - - - - + "Akun virta %d prosenttia, lataaminen keskeytetty akun suojelemiseksi." + "Akun virta %1$d prosenttia, %2$s, lataaminen keskeytetty akun suojelemiseksi." "Näytä kaikki ilmoitukset" "Tekstipuhelin käytössä." "Soittoääni: värinä." @@ -501,8 +496,8 @@ "Avaa lukitus ja käytä" "Korttien noutamisessa oli ongelma, yritä myöhemmin uudelleen" "Lukitusnäytön asetukset" - - + "QR-koodiskanneri" + "Päivitetään" "Työprofiili" "Lentokonetila" "Et kuule seuraavaa hälytystäsi (%1$s)." @@ -996,4 +991,23 @@ "VKP, KKK p" "h:mm" "kk:mm" + "Avaa %1$s" + "Jos haluat, että %1$s lisätään pikakuvakkeeksi, varmista nämä:" + "• Sovellus on otettu käyttöön" + "• Ainakin yksi kortti on lisätty Walletiin" + "• Asenna kamerasovellus" + "• Sovellus on otettu käyttöön" + "• Ainakin yksi laite on käytettävissä" + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml index 99e8c7fce656b..6ec97d7b9d785 100644 --- a/packages/SystemUI/res/values-fr-rCA/strings.xml +++ b/packages/SystemUI/res/values-fr-rCA/strings.xml @@ -125,8 +125,7 @@ "Assistance vocale" "Portefeuille" "Lecteur de code QR" - - + "Déverrouillé" "Appareil verrouillé" "Numérisation du visage" "Envoyer" @@ -169,8 +168,7 @@ "Visage non reconnu" "Utiliser l\'empreinte digitale" - - + "Déverrouillage par reconnaissance faciale inaccessible." "Bluetooth connecté" "Pourcentage de la pile inconnu." "Connecté à : %s" @@ -181,13 +179,10 @@ "Mode Avion" "RPV activé." "Pile : %d pour cent" - - + "Pile à %1$dpour cent, %2$s" "Pile en charge : %d %%." - - - - + "Pile à %d pour cent, recharge interrompue pour protéger la pile." + "Pile à %1$d pour cent, %2$s, recharge interrompue pour protéger la pile." "Afficher toutes les notifications" "Téléscripteur activé" "Sonnerie en mode vibreur" @@ -371,7 +366,7 @@ "Toutes les applications et les données de cet utilisateur seront supprimées." "Supprimer" "%s aura accès à toute l\'information visible sur votre écran ou qui joue sur votre appareil durant l\'enregistrement ou la diffusion. Cela comprend des renseignements comme les mots de passe, les détails du paiement, les photos, les messages et le contenu audio que vous faites jouer." - "Le service offrant cette fonction aura accès à toute l\'information qui est visible sur votre écran ou sur ce qui joue sur votre appareil durant l\'enregistrement ou la diffusion. Cela comprend des renseignements comme les mots de passe, les détails du paiement, les photos, les messages et le contenu audio que vous faites jouer." + "Le service offrant cette fonction aura accès à toute l\'information qui est visible sur votre écran ou à ce qui joue sur votre appareil durant l\'enregistrement ou la diffusion. Cela comprend des renseignements comme les mots de passe, les détails du paiement, les photos, les messages et le contenu audio que vous faites jouer." "Commencer à enregistrer ou à diffuser?" "Commencer à enregistrer ou à diffuser avec %s?" "Autoriser %s à partager ou à enregistrer?" @@ -502,6 +497,7 @@ "Un problème est survenu lors de la récupération de vos cartes, veuillez réessayer plus tard" "Paramètres de l\'écran de verrouillage" "lecteur de code QR" + "Mise à jour en cours…" "Profil professionnel" "Mode Avion" "Vous n\'entendrez pas votre prochaine alarme à %1$s" @@ -995,4 +991,23 @@ "EEE, d MMM" "h:mm" "kk:mm" + "Ouvrir %1$s" + "Pour ajouter l\'application %1$s en tant que raccourci, assurez-vous" + "• que cette application est configurée;" + "• qu\'au moins une carte a été ajoutée à Portefeuille." + "• qu\'une application de caméra est installée;" + "• que cette application est configurée;" + "• qu\'au moins un appareil est utilisable;" + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml index 68fae123e7fcd..3c2a59b959019 100644 --- a/packages/SystemUI/res/values-fr/strings.xml +++ b/packages/SystemUI/res/values-fr/strings.xml @@ -125,8 +125,7 @@ "Assistance vocale" "Wallet" "Lecteur de code QR" - - + "Déverrouillé" "Appareil verrouillé" "Analyse du visage en cours" "Envoyer" @@ -169,8 +168,7 @@ "Visage non reconnu" "Utilisez empreinte digit." - - + "Déverrouillage par reconnaissance faciale indisponible" "Bluetooth connecté" "Pourcentage de la batterie inconnu." "Connecté à : %s" @@ -181,13 +179,10 @@ "Mode Avion" "Le VPN est activé." "Batterie : %d pour cent" - - + "Batterie : %1$d pour cent. Utilisable %2$s" "Batterie en charge : %d %%." - - - - + "Batterie : %d pour cent. Recharge interrompue pour protéger la batterie." + "Batterie : %1$d pour cent. Utilisable %2$s. Recharge interrompue pour protéger la batterie." "Afficher toutes les notifications" "Téléscripteur activé" "Sonnerie en mode vibreur" @@ -501,8 +496,8 @@ "Déverrouiller pour utiliser" "Problème de récupération de vos cartes. Réessayez plus tard" "Paramètres de l\'écran de verrouillage" - - + "Lecteur de code QR" + "Mise à jour" "Profil professionnel" "Mode Avion" "Vous n\'entendrez pas votre prochaine alarme %1$s." @@ -996,4 +991,23 @@ "EEE, MMM j" "hh:mm" "kk:mm" + "Ouvrir %1$s" + "Pour ajouter l\'appli %1$s comme raccourci, procédez aux vérifications suivantes" + "• L\'appli est configurée" + "• Au moins une carte a été ajoutée à Wallet" + "• Installer une appli d\'appareil photo" + "• L\'appli est configurée" + "• Au moins un appareil est disponible" + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml index fd554badf49da..fb255e4be0b6b 100644 --- a/packages/SystemUI/res/values-gl/strings.xml +++ b/packages/SystemUI/res/values-gl/strings.xml @@ -125,8 +125,7 @@ "Asistente de voz" "Wallet" "Escáner de código QR" - - + "Desbloqueouse" "Dispositivo bloqueado" "Analizando cara" "Enviar" @@ -169,8 +168,7 @@ "Non se recoñeceu a cara" "Usa a impresión dixital" - - + "O desbloqueo facial non está dispoñible" "Bluetooth conectado" "Descoñécese a porcentaxe da batería." "Conectado a %s." @@ -181,13 +179,10 @@ "Modo avión" "A VPN está activada." "Carga da batería: %d por cento." - - + "Carga da batería: %1$d por cento (%2$s)" "Batería cargando. Nivel: %d por cento." - - - - + "Carga da batería: %d por cento. Púxose en pausa a carga para protexer a batería." + "Carga da batería: %1$d por cento (%2$s). Púxose en pausa a carga para protexer a batería." "Ver todas as notificacións" "Teletipo activado" "Timbre en vibración" @@ -501,8 +496,8 @@ "Desbloquear para usar" "Produciuse un problema ao obter as tarxetas. Téntao de novo máis tarde" "Configuración da pantalla de bloqueo" - - + "Escáner de códigos QR" + "Actualizando" "Perfil de traballo" "Modo avión" "Non escoitarás a alarma seguinte %1$s" @@ -531,7 +526,7 @@ "Automática" "Sen son nin vibración" "Sen son nin vibración, e aparecen máis abaixo na sección de conversas" - "Poderían facer que o teléfono soe ou vibre en función da súa configuración" + "O teléfono pode soar ou vibrar en función da súa configuración" "Poderían facer que o teléfono soe ou vibre en función da súa configuración. Conversas desde a burbulla da aplicación %1$s de forma predeterminada." "Fai que o sistema determine se a notificación debe emitir un son ou unha vibración" "<b>Estado:</b> ascendeuse a Predeterminada" @@ -996,4 +991,23 @@ "EEE, d MMM" "h:mm" "kk:mm" + "Abrir %1$s" + "Para engadir a aplicación %1$s como atallo, asegúrate de que se cumpra o seguinte:" + "• A aplicación debe estar configurada" + "• Ten que haber polo menos unha tarxeta engadida a Wallet" + "• Debes instalar a aplicación de cámara" + "• A aplicación debe estar configurada" + "• Ten que haber polo menos un dispositivo dispoñible" + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml index 72c535b34a3c1..2df50433036bb 100644 --- a/packages/SystemUI/res/values-gu/strings.xml +++ b/packages/SystemUI/res/values-gu/strings.xml @@ -125,8 +125,7 @@ "વૉઇસ સહાય" "Wallet" "QR કોડ સ્કૅનર" - - + "અનલૉક કર્યું છે" "ડિવાઇસ લૉક કરેલું છે" "ચહેરો સ્કૅન કરવો" "મોકલો" @@ -169,8 +168,7 @@ "ચહેરો ઓળખાતો નથી" "તો ફિંગરપ્રિન્ટ વાપરો" - - + "ફેસ અનલૉક સુવિધા ઉપલબ્ધ નથી" "બ્લૂટૂથ કનેક્ટ થયું." "બૅટરીની ટકાવારી અજાણ છે." "%s થી કનેક્ટ થયાં." @@ -181,13 +179,10 @@ "એરપ્લેન મોડ." "VPN ચાલુ છે." "બૅટરી %d ટકા." - - + "બૅટરી %1$d, %2$s" "બૅટરી ચાર્જ થઈ રહી છે, %d%%." - - - - + "બૅટરી %d, બૅટરીની સુરક્ષા માટે ચાર્જિંગ થોભાવ્યું છે." + "બૅટરી %1$d, %2$s, બૅટરીની સુરક્ષા માટે ચાર્જિંગ થોભાવ્યું છે." "બધી સૂચના જુઓ" "ટેલિટાઇપરાઇટર સક્ષમ કર્યું." "રિંગર વાઇબ્રેટ." @@ -501,7 +496,8 @@ "ઉપયોગ કરવા માટે અનલૉક કરો" "તમારા કાર્ડની માહિતી મેળવવામાં સમસ્યા આવી હતી, કૃપા કરીને થોડા સમય પછી ફરી પ્રયાસ કરો" "લૉક સ્ક્રીનના સેટિંગ" - + "QR કોડ સ્કૅનર" + "ઑફિસની પ્રોફાઇલ" "એરપ્લેન મોડ" @@ -996,4 +992,24 @@ "EEE, d MMM" "h:mm" "kk:mm" + + + + + + + + + + + + + + + "રદ કરો" + "હમણાં જ ફ્લિપ કરો" + "બહેતર સેલ્ફી લેવા માટે ફોન ખોલો" + "બહેતર સેલ્ફી લેવા ફ્રન્ટ ડિસ્પ્લે પર ફ્લિપ કરીએ?" + "વધુ ઉચ્ચ રિઝોલ્યુશનવાળો વિશાળ ફોટો લેવા માટે પાછલા કૅમેરાનો ઉપયોગ કરો." + "✱ આ સ્ક્રીન બંધ થઈ જશે" diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml index a49c8d08172ff..6882daf73fe79 100644 --- a/packages/SystemUI/res/values-hi/strings.xml +++ b/packages/SystemUI/res/values-hi/strings.xml @@ -125,8 +125,7 @@ "आवाज़ से डिवाइस का इस्तेमाल" "Wallet" "क्यूआर कोड स्कैनर" - - + "अनलॉक है" "डिवाइस लॉक है" "डिवाइस अनलॉक करने के लिए चेहरा स्कैन किया जाता है" "भेजें" @@ -169,8 +168,7 @@ "चेहरे की पहचान नहीं हुई" "फ़िंगरप्रिंट इस्तेमाल करें" - - + "फ़ेस अनलॉक की सुविधा उपलब्ध नहीं है" "ब्लूटूथ कनेक्ट किया गया." "इस बारे में जानकारी नहीं है कि अभी बैटरी कितने प्रतिशत चार्ज है." "%s से कनेक्ट किया गया." @@ -181,13 +179,10 @@ "हवाई जहाज़ मोड." "VPN चालू." "%d प्रति‍शत बैटरी." - - + "बैटरी %1$d प्रतिशत चार्ज है, जो कि %2$s चल जाएगी" "बैटरी चार्ज हो रही है, %d प्रतिशत." - - - - + "बैटरी %d प्रतिशत चार्ज हुई. बैटरी खराब होने से बचाने के लिए, चार्जिंग रोक दी गई है." + "बैटरी %1$d प्रतिशत चार्ज हुई, जो कि %2$s चल जाएगी. बैटरी खराब होने से बचाने के लिए, चार्जिंग रोक दी गई है." "पूरी सूचनाएं देखें" "टेलीटाइपराइटर सक्षम." "रिंगर कंपन (वाइब्रेशन)." @@ -501,7 +496,8 @@ "इस्तेमाल करने के लिए, डिवाइस अनलॉक करें" "आपके कार्ड की जानकारी पाने में कोई समस्या हुई है. कृपया बाद में कोशिश करें" "लॉक स्क्रीन की सेटिंग" - + "क्यूआर कोड स्कैनर" + "वर्क प्रोफ़ाइल" "हवाई जहाज़ मोड" @@ -996,4 +992,30 @@ "EEE, MMM d" "h:mm" "kk:mm" + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml index 71ba52c996918..20942747a3577 100644 --- a/packages/SystemUI/res/values-hr/strings.xml +++ b/packages/SystemUI/res/values-hr/strings.xml @@ -125,8 +125,7 @@ "Glasovna pomoć" "Wallet" "Čitač QR koda" - - + "Otključano" "Uređaj je zaključan" "Skeniranje lica" "Pošalji" @@ -169,8 +168,7 @@ "Lice nije prepoznato" "Upotrijebite otisak prsta" - - + "Otključavanje licem nije dostupno" "Bluetooth povezan." "Postotak baterije nije poznat." "Spojen na %s ." @@ -181,13 +179,10 @@ "Način rada u zrakoplovu" "VPN uključen." "Baterija %d posto." - - + "Postotak baterije: %1$d, vrijeme: %2$s" "Baterija se puni, %d posto." - - - - + "Postotak baterije %d, punjenje je pauzirano radi zaštite baterije." + "Postotak baterije %1$d, %2$s, punjenje je pauzirano radi zaštite baterije" "Pogledajte sve obavijesti" "TeleTypewriter je omogućen." "Vibracija softvera zvona." @@ -502,6 +497,7 @@ "Pojavio se problem prilikom dohvaćanja kartica, pokušajte ponovo kasnije" "Postavke zaključanog zaslona" "Čitač QR koda" + "Ažuriranje" "Poslovni profil" "Način rada u zrakoplovu" "Nećete čuti sljedeći alarm %1$s" @@ -995,4 +991,23 @@ "EEE., d. MMM." "h:mm" "kk:mm" + "Otvorite %1$s" + "Da biste dodali aplikaciju %1$s kao prečac, provjerite sljedeće" + "• Aplikacija je postavljena" + "• Najmanje jedna kartica dodana je u Wallet" + "• Instalirajte aplikaciju fotoaparata" + "• Aplikacija je postavljena" + "• Dostupan je najmanje jedan uređaj" + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml index d9c438ceb8a2c..1b9dc9a985821 100644 --- a/packages/SystemUI/res/values-hu/strings.xml +++ b/packages/SystemUI/res/values-hu/strings.xml @@ -125,8 +125,7 @@ "Hangsegéd" "Wallet" "QR-kód-szkennelő" - - + "Feloldva" "Az eszköz zárolva van" "Arc keresése" "Küldés" @@ -169,8 +168,7 @@ "Az arc nem ismerhető fel" "Használjon ujjlenyomatot" - - + "Nem áll rendelkezésre az Arcalapú feloldás" "Bluetooth csatlakoztatva." "Az akkumulátor töltöttségi szintje ismeretlen." "Csatlakoztatva a következőhöz: %s." @@ -181,13 +179,10 @@ "Repülőgép üzemmód." "VPN bekapcsolva." "Akkumulátor %d százalék." - - + "Az akkumulátor töltöttségi szinte %1$d százalék; %2$s." "Tölt az akkumulátor, %d százalék." - - - - + "Az akkumulátor töltöttségi szintje %d százalék; töltés szüneteltetve az akkumulátor védelme érdekében." + "Az akkumulátor töltöttségi szintje %1$d százalék; %2$s. Töltés szüneteltetve az akkumulátor védelme érdekében." "Összes értesítés megtekintése" "TeleTypewriter engedélyezve." "Csengő rezeg." @@ -501,8 +496,8 @@ "Oldja fel a használathoz" "Probléma merült fel a kártyák lekérésekor, próbálja újra később" "Lezárási képernyő beállításai" - - + "QR-kód-szkennelő" + "Frissítés…" "Munkahelyi profil" "Repülős üzemmód" "Nem fogja hallani az ébresztést ekkor: %1$s" @@ -996,4 +991,23 @@ "EEE, HHH n" "ó:pp" "óó:pp" + "A(z) %1$s megnyitása" + "Ha szeretné felvenni a(z) %1$s alkalmazást parancsikonként, gondoskodjon a következőkről:" + "• Az alkalmazás be van állítva" + "• Legalább egy kártya hozzá lett adva a Wallethez" + "• Kameraalkalmazás telepítése" + "• Az alkalmazás be van állítva" + "• Legalább egy eszköz rendelkezésre áll" + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml index 820b66669dda5..840bc261e9dc4 100644 --- a/packages/SystemUI/res/values-hy/strings.xml +++ b/packages/SystemUI/res/values-hy/strings.xml @@ -125,8 +125,7 @@ "Ձայնային հուշումներ" "Wallet" "QR կոդերի սկաներ" - - + "Ապակողպված է" "Սարքը կողպված է" "Դեմքի սկանավորում" "Ուղարկել" @@ -169,8 +168,7 @@ "Դեմքը չի ճանաչվել" "Օգտագործեք մատնահետք" - - + "Դեմքով ապակողպումն անհասանելի է" "Bluetooth-ը միացված է:" "Մարտկոցի լիցքի մակարդակն անհայտ է։" "Միացված է %s-ին:" @@ -181,13 +179,10 @@ "Ավիառեժիմ" "Միացնել VPN-ը։" "Մարտկոցը %d տոկոս է:" - - + "Մարտկոցի լիցքը %1$d տոկոս է։ Այն կաշխատի %2$s։" "Մարտկոցը լիցքավորվում է: Լիցքը %d տոկոս է:" - - - - + "Մարտկոցի լիցքը %d է։ Լիցքավորումը դադարեցվել է՝ մարտկոցը պաշտպանելու համար։" + "Մարտկոցի լիցքը %1$d է։ Այն կաշխատի %2$s։ Լիցքավորումը դադարեցվել է՝ մարտկոցը պաշտպանելու նպատակով։" "Տեսնել բոլոր ծանուցումները" "Հեռատիպը միացված է:" "Թրթռազանգ:" @@ -501,8 +496,8 @@ "Ապակողպել՝ օգտագործելու համար" "Չհաջողվեց բեռնել քարտերը։ Նորից փորձեք։" "Կողպէկրանի կարգավորումներ" - - + "QR կոդերի սկաներ" + "Թարմացում" "Android for Work-ի պրոֆիլ" "Ավիառեժիմ" "Ժամը %1$s-ի զարթուցիչը չի զանգի" @@ -996,4 +991,23 @@ "EEE, MMM d" "h:mm" "kk:mm" + "Բացել %1$s հավելվածը" + "%1$s հավելվածի դյուրանցումն ավելացնելու համար համոզվեք, որ՝" + "• Հավելվածը կարգավորված է" + "• Առնվազն մեկ քարտ ավելացված է Wallet-ում" + "• «Տեսախցիկ» հավելվածը տեղադրված է" + "• Հավելվածը կարգավորված է" + "• Հասանելի է առնվազն մեկ սարք" + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml index a5ff4915c3bdf..351d5e651b7b0 100644 --- a/packages/SystemUI/res/values-in/strings.xml +++ b/packages/SystemUI/res/values-in/strings.xml @@ -125,8 +125,7 @@ "Bantuan Suara" "Wallet" "Pemindai Kode QR" - - + "Tidak terkunci" "Perangkat terkunci" "Memindai wajah" "Kirim" @@ -169,8 +168,7 @@ "Tidak mengenali wajah" "Gunakan sidik jari" - - + "Buka dengan Wajah tidak tersedia" "Bluetooth terhubung." "Persentase baterai tidak diketahui." "Terhubung ke %s." @@ -181,13 +179,10 @@ "Mode pesawat." "VPN aktif." "Baterai %d persen." - - + "Baterai %1$d persen, %2$s" "Mengisi daya baterai, %d persen." - - - - + "Baterai %d persen, pengisian daya dijeda untuk melindungi baterai." + "Baterai %1$d persen, %2$s, pengisian daya dijeda untuk melindungi baterai." "Lihat semua notifikasi" "TeleTypewriter diaktifkan." "Pendering bergetar." @@ -501,8 +496,8 @@ "Buka kunci untuk menggunakan" "Terjadi error saat mendapatkan kartu Anda, coba lagi nanti" "Setelan layar kunci" - - + "Pemindai kode QR" + "Mengupdate" "Profil kerja" "Mode pesawat" "Anda tidak akan mendengar alarm berikutnya %1$s" @@ -996,4 +991,23 @@ "EEE, d MMM" "h:mm" "kk:mm" + "Buka %1$s" + "Untuk menambahkan aplikasi %1$s sebagai pintasan, pastikan" + "• Aplikasi disiapkan" + "• Minimal satu kartu telah ditambahkan ke Wallet" + "• Menginstal aplikasi kamera" + "• Aplikasi disiapkan" + "• Tersedia minimal satu perangkat" + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml index bc84dc937dc06..973f17ad5c03a 100644 --- a/packages/SystemUI/res/values-is/strings.xml +++ b/packages/SystemUI/res/values-is/strings.xml @@ -125,8 +125,7 @@ "Raddaðstoð" "Veski" "QR-kóðaskanni" - - + "Ólæst" "Tækið er læst" "Andlit skannað" "Senda" @@ -169,8 +168,7 @@ "Andlit þekkist ekki" "Nota fingrafar í staðinn" - - + "Andlitskenni ekki í boði" "Bluetooth tengt." "Staða rafhlöðu óþekkt." "Tengt við %s." @@ -181,13 +179,10 @@ "Flugstilling" "Kveikt á VPN." "%d prósent á rafhlöðu." - - + "Hleðsla rafhlöðu er %1$d prósent, %2$s" "Rafhlaða í hleðslu, %d%%." - - - - + "Hleðsla rafhlöðu er %d prósent, hlé gert á hleðslu til að vernda rafhlöðuna." + "Hleðsla rafhlöðu er %1$d prósent, %2$s, hlé gert á hleðslu til að vernda rafhlöðuna." "Sjá allar tilkynningar" "Fjarriti virkur." "Titrar við hringingu." @@ -501,8 +496,8 @@ "Taktu úr lás til að nota" "Vandamál kom upp við að sækja kortin þín. Reyndu aftur síðar" "Stillingar fyrir læstan skjá" - - + "QR-kóðaskanni" + "Uppfærir" "Vinnusnið" "Flugstilling" "Ekki mun heyrast í vekjaranum %1$s" @@ -996,4 +991,23 @@ "EEE, MMM d" "k:mm" "kk:mm" + "Opna %1$s" + "Til að bæta forritinu %1$s við sem flýtileið skaltu ganga úr skugga um að" + "• Forritið er uppsett" + "• Að minnsta kosti einu korti var bætt við Veski" + "• Setja upp myndavélarforrit" + "• Forritið er uppsett" + "• Að minnsta kosti eitt tæki er tiltækt" + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml index 0d2c3b1bc46b1..ab18d29c60b70 100644 --- a/packages/SystemUI/res/values-it/strings.xml +++ b/packages/SystemUI/res/values-it/strings.xml @@ -125,8 +125,7 @@ "Voice Assist" "Wallet" "Scanner codici QR" - - + "Sbloccato" "Dispositivo bloccato" "Scansione del viso" "Invia" @@ -169,8 +168,7 @@ "Volto non riconosciuto" "Usa l\'impronta" - - + "Sblocco con il volto non disponibile" "Bluetooth collegato." "Percentuale della batteria sconosciuta." "Connesso a %s." @@ -181,13 +179,10 @@ "Modalità aereo." "VPN attiva." "Batteria: %d percento." - - + "Batteria a %1$d per cento, %2$s" "Batteria in carica, %d%%." - - - - + "Batteria a %d per cento; ricarica in pausa per proteggere la batteria." + "Batteria a %1$d per cento, %2$s; ricarica in pausa per proteggere la batteria." "Visualizza tutte le notifiche" "Telescrivente abilitata." "Suoneria vibrazione." @@ -501,8 +496,8 @@ "Sblocca per usare" "Si è verificato un problema durante il recupero delle tue carte. Riprova più tardi." "Impostazioni schermata di blocco" - - + "Scanner codici QR" + "Aggiornamento in corso…" "Profilo di lavoro" "Modalità aereo" "Non sentirai la tua prossima sveglia %1$s" @@ -996,4 +991,17 @@ "EEE, MMM g" "h:mm" "kk:mm" + "Apri %1$s" + "Per aggiungere l\'app %1$s come scorciatoia, assicurati che:" + "• L\'app sia configurata" + "• Sia stata aggiunta almeno una carta a Wallet" + "• Sia installata un\'app fotocamera" + "• L\'app sia configurata" + "• Ci sia almeno un dispositivo disponibile" + "Annulla" + "Gira ora" + "Apri il telefono per un selfie migliore" + "Girare su display frontale per un selfie migliore?" + "Utilizza la fotocamera posteriore per una foto più ampia con maggiore risoluzione." + "✱ Questo schermo verrà disattivato" diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml index 453e8d604d4f3..c5df1690c91c6 100644 --- a/packages/SystemUI/res/values-iw/strings.xml +++ b/packages/SystemUI/res/values-iw/strings.xml @@ -168,8 +168,7 @@ "לא ניתן לזהות את הפנים" "שימוש בטביעת אצבע במקום זאת" - - + "אי אפשר לפתוח בזיהוי פנים" "‏Bluetooth מחובר." "אחוז טעינת הסוללה לא ידוע." "התבצע חיבור אל %s." @@ -180,13 +179,10 @@ "מצב טיסה" "‏VPN פועל." "%d אחוזים של סוללה." - - + "רמת הטעינה של הסוללה היא %1$d אחוזים, %2$s" "הסוללה בטעינה, %d%%." - - - - + "רמת הטעינה של הסוללה היא %d אחוזים. הטעינה הושהתה כדי להגן על הסוללה." + "רמת הטעינה של הסוללה היא %1$d אחוזים, %2$s. הטעינה הושהתה כדי להגן על הסוללה." "הצגת כל ההתראות" "‏TeleTypewriter מופעל" "צלצול ורטט." @@ -500,8 +496,8 @@ "יש לבטל את הנעילה כדי להשתמש" "הייתה בעיה בקבלת הכרטיסים שלך. כדאי לנסות שוב מאוחר יותר" "הגדרות מסך הנעילה" - - + "‏סורק קודי QR" + "מתבצע עדכון" "פרופיל עבודה" "מצב טיסה" "לא ניתן יהיה לשמוע את ההתראה הבאה שלך %1$s" @@ -995,4 +991,17 @@ "‏יום EEE,‏ d בMMM" "h:mm" "kk:mm" + "פתיחת %1$s" + "כדי להוסיף את האפליקציה %1$s כקיצור דרך, צריך לוודא" + "• האפליקציה מוגדרת" + "‏• לפחות כרטיס אחד נוסף ל-Wallet" + "• התקנה של אפליקציית מצלמה" + "• האפליקציה מוגדרת" + "• יש לפחות מכשיר אחד זמין" + "ביטול" + "הפכת את המכשיר" + "כדי לצלם תמונת סלפי טובה יותר, פותחים את הטלפון" + "להפוך למסך הקדמי כדי לצלם תמונת סלפי טובה יותר?" + "במצלמה האחורית אפשר לצלם תמונה רחבה יותר ברזולוציה גבוהה יותר." + "✱ המסך יכבה" diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml index 7efa1a29dbc09..c1edf400a5a5a 100644 --- a/packages/SystemUI/res/values-ja/strings.xml +++ b/packages/SystemUI/res/values-ja/strings.xml @@ -168,8 +168,7 @@ "顔を認識できません" "指紋認証をお使いください" - - + "顔認証を利用できません" "Bluetoothに接続済み。" "バッテリー残量は不明です。" "%sに接続しました。" @@ -180,13 +179,10 @@ "機内モード。" "VPN は ON です。" "バッテリー残量: %dパーセント" - - + "バッテリー残量 %1$d、%2$s" "電池充電中: %dパーセント" - - - - + "バッテリー残量 %d: バッテリー保護のため、充電を一時停止しました。" + "バッテリー残量 %1$d、%2$s: バッテリー保護のため、充電を一時停止しました。" "通知をすべて表示" "テレタイプライターが有効です。" "バイブレーション着信。" @@ -501,6 +497,7 @@ "カードの取得中に問題が発生しました。しばらくしてからもう一度お試しください" "ロック画面の設定" "QR コードスキャナ" + "更新しています" "仕事用プロファイル" "機内モード" "次回のアラーム(%1$s)は鳴りません" @@ -994,4 +991,17 @@ "EEE, MMM d" "h:mm" "kk:mm" + "%1$s を開く" + "%1$s アプリをショートカットとして追加するための手順" + "• アプリが設定されている" + "• ウォーレットに追加されているカードが 1 枚以上ある" + "• カメラアプリをインストールする" + "• アプリが設定されている" + "• 利用できるデバイスが 1 台以上ある" + "キャンセル" + "切り替えましょう" + "高画質で撮るにはスマートフォンを開いてください" + "前面ディスプレイに切り替えて綺麗に撮りましょう" + "高解像度で広い範囲を撮影するには、背面カメラを使用してください。" + "✱この画面は OFF になります" diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml index 292aaa4a83ef7..3fd445443c206 100644 --- a/packages/SystemUI/res/values-ka/strings.xml +++ b/packages/SystemUI/res/values-ka/strings.xml @@ -125,8 +125,7 @@ "ხმოვანი დახმარება" "საფულე" "QR კოდის სკანერი" - - + "გახსნილი" "მოწყობილობა ჩაკეტილია" "მიმდინარეობს სახის სკანირება" "გაგზავნა" @@ -169,8 +168,7 @@ "სახის ამოცნობა შეუძლებ." "გამოიყენეთ თითის ანაბეჭდი" - - + "სახით განბლოკვა მიუწვდომელია." "Bluetooth დაკავშირებულია." "ბატარეის პროცენტული მაჩვენებელი უცნობია." "დაკავშირებულია %s-თან." @@ -181,13 +179,10 @@ "თვითმფრინავის რეჟიმი" "VPN ჩართულია." "ბატარეა: %d პროცენტი." - - + "ბატარეა: %1$d პროცენტი, %2$s" "ბატარეა იტენება. ამჟამად არის %d პროცენტი." - - - - + "ბატარეა: %d პროცენტი, დატენვა შეჩერებულია ბატარეის დასაცავად." + "ბატარეა: %1$d პროცენტი, %2$s, დატენვა შეჩერებულია ბატარეის დასაცავად." "ყველა შეტყობინების ნახვა" "ტელეტაიპი ჩართულია." "ვიბრაციის რეჟიმი." @@ -502,6 +497,7 @@ "თქვენი ბარათების მიღებისას პრობლემა წარმოიშვა. ცადეთ ხელახლა მოგვიანებით" "ჩაკეტილი ეკრანის პარამეტრები" "QR კოდის სკანერი" + "მიმდინარეობს განახლება" "სამსახურის პროფილი" "თვითმფრინავის რეჟიმი" "ვერ გაიგონებთ მომდევნო მაღვიძარას %1$s-ზე" @@ -995,4 +991,23 @@ "დდდ, თთთ თ" "სთ:წთ" "სთ:წთ" + "%1$s აპის გახსნა" + "%1$s აპი რომ მალსახმობის სახით დაამატოთ, დარწმუნდით, რომ" + "• აპი დაყენებულია" + "• საფულეში დამატებულია მინიმუმ ერთი ბარათი" + "• დააინსტალირეთ კამერის აპი" + "• აპი დაყენებულია" + "• ხელმისაწვდომია მინიმუმ ერთი მოწყობილობა" + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml index bffda32ea2843..d14fbed2276fd 100644 --- a/packages/SystemUI/res/values-kk/strings.xml +++ b/packages/SystemUI/res/values-kk/strings.xml @@ -125,8 +125,7 @@ "Дауыс көмекшісі" "Wallet" "QR кодын сканерлеу қолданбасы" - - + "Құлпы ашылған" "Құрылғы құлыпталды." "Бетті сканерлеу" "Жіберу" @@ -169,8 +168,7 @@ "Бет танылмады." "Орнына саусақ ізін пайдаланыңыз." - - + "Бет тану функциясы қолжетімсіз." "Bluetooth қосылған." "Батарея зарядының мөлшері белгісіз." "%s қосылған." @@ -181,13 +179,10 @@ "Ұшақ режимі." "VPN қосулы." "Батарея %d пайыз." - - + "Батарея заряды: %1$d пайыз. Жететін мерзімі: %2$s." "Батарея зарядталуда, %d %%." - - - - + "Батарея заряды: %d пайыз. Батареяны қорғау үшін зарядтау кідіртілді." + "Батарея заряды: %1$d пайыз. Жететін мерзімі: %2$s. Батареяны қорғау үшін зарядтау кідіртілді." "Барлық хабарландыруды қарау" "Телетайп қосылған." "Қоңырау тербелісі." @@ -501,8 +496,8 @@ "Пайдалану үшін құлыпты ашу" "Карталарыңыз алынбады, кейінірек қайталап көріңіз." "Экран құлпының параметрлері" - - + "QR кодының сканері" + "Жаңартылып жатыр" "Жұмыс профилі" "Ұшақ режимі" "Келесі %1$s дабылыңызды есітпейсіз" @@ -996,4 +991,23 @@ "d MMM EEEE" "h:mm" "kk:mm" + "%1$s ашу" + "%1$s қолданбасын таңбаша ретінде қосу үшін келесі әрекеттерді орындауды ұмытпаңыз:" + "• Қолданба реттелген" + "• Wallet-ке кемінде бір карта қосылған" + "• Камера қолданбасын орнатыңыз" + "• Қолданба реттелген" + "• Кемінде бір құрылғы қолжетімді" + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml index 6d2e5a8e48d13..3ace0e6a34b96 100644 --- a/packages/SystemUI/res/values-km/strings.xml +++ b/packages/SystemUI/res/values-km/strings.xml @@ -125,8 +125,7 @@ "ជំនួយសំឡេង" "Wallet" "កម្មវិធីស្កេនកូដ QR" - - + "បានដោះសោ" "បានចាក់សោ​ឧបករណ៍" "ការ​ស្កេន​មុខ" "ផ្ញើ" @@ -169,8 +168,7 @@ "មិនអាចសម្គាល់មុខបានទេ" "ប្រើស្នាមម្រាមដៃជំនួសវិញ​" - - + "មិនអាចប្រើការដោះសោតាមទម្រង់មុខបានទេ" "បាន​តភ្ជាប់​ប៊្លូធូស។" "មិនដឹងអំពី​ភាគរយថ្មទេ។" "បាន​ភ្ជាប់​ទៅ %s ។" @@ -181,13 +179,10 @@ "ពេល​ជិះ​យន្តហោះ" "បើក VPN ។" "ថ្ម %d ភាគរយ។" - - + "ថ្ម %1$d ភាគរយ, %2$s" "កំពុងសាកថ្ម %d ភាគរយ" - - - - + "ថ្ម %d ភាគរយ, ការសាកថ្មបានផ្អាកដើម្បីការការពារថ្ម។" + "ថ្ម %1$d ភាគរយ, %2$s, ការសាកថ្មបានផ្អាកដើម្បីការការពារថ្ម។" "មើល​ការជូនដំណឹង​ទាំងអស់" "បាន​បើក​ម៉ាស៊ីន​អង្គុលីលេខ​" "កម្មវិធី​រោទ៍​ញ័រ។" @@ -501,8 +496,8 @@ "ដោះសោដើម្បីប្រើប្រាស់" "មានបញ្ហា​ក្នុងការទាញយក​កាត​របស់អ្នក សូម​ព្យាយាមម្ដងទៀត​នៅពេលក្រោយ" "ការកំណត់អេក្រង់ចាក់សោ" - - + "កម្មវិធី​ស្កេនកូដ QR" + "កំពុងដំឡើង​កំណែ" "ប្រវត្តិរូបការងារ" "ពេលជិះយន្តហោះ" "អ្នកនឹងមិនលឺម៉ោងរោទ៍ %1$s បន្ទាប់របស់អ្នកទេ" @@ -996,4 +991,23 @@ "EEE, MMM d" "h:mm" "kk:mm" + "បើក %1$s" + "ដើម្បីបញ្ចូលកម្មវិធី %1$s ជាផ្លូវកាត់ សូមប្រាកដថា" + "• កម្មវិធីត្រូវបានរៀបចំ" + "• កាតយ៉ាងតិចមួយត្រូវបានបញ្ចូលទៅក្នុង Wallet" + "• ដំឡើងកម្មវិធីកាមេរ៉ា" + "• កម្មវិធីត្រូវបានរៀបចំ" + "• ឧបករណ៍យ៉ាងតិចមួយអាចប្រើបាន" + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml index 099139f271850..27691e1970ed2 100644 --- a/packages/SystemUI/res/values-kn/strings.xml +++ b/packages/SystemUI/res/values-kn/strings.xml @@ -125,8 +125,7 @@ "ಧ್ವನಿ ಸಹಾಯಕ" "ವಾಲೆಟ್" "QR ಕೋಡ್ ಸ್ಕ್ಯಾನರ್" - - + "ಅನ್‌ಲಾಕ್ ಮಾಡಲಾಗಿದೆ" "ಸಾಧನ ಲಾಕ್ ಆಗಿದೆ" "ಮುಖವನ್ನು ಸ್ಕ್ಯಾನ್ ಮಾಡಲಾಗುತ್ತಿದೆ" "ಕಳುಹಿಸಿ" @@ -169,8 +168,7 @@ "ಮುಖ ಗುರುತಿಸಲಾಗುತ್ತಿಲ್ಲ" "ಬದಲಿಗೆ ಫಿಂಗರ್‌ಪ್ರಿಂಟ್ ಬಳಸಿ" - - + "ಫೇಸ್ ಅನ್‌ಲಾಕ್ ಲಭ್ಯವಿಲ್ಲ" "ಬ್ಲೂಟೂತ್‌‌ ಸಂಪರ್ಕಗೊಂಡಿದೆ." "ಬ್ಯಾಟರಿ ಶೇಕಡಾವಾರು ತಿಳಿದಿಲ್ಲ." "%s ಗೆ ಸಂಪರ್ಕಪಡಿಸಲಾಗಿದೆ." @@ -181,13 +179,10 @@ "ಏರೋಪ್ಲೇನ್‌ ಮೋಡ್‌" "ನಲ್ಲಿ VPN" "ಬ್ಯಾಟರಿ %d ಪ್ರತಿಶತ." - - + "ಬ್ಯಾಟರಿ %1$d ರಷ್ಟಿದ್ದು %2$s ಗಳ ಕಾಲ ಇರುತ್ತದೆ" "ಬ್ಯಾಟರಿ %d ಪ್ರತಿಶತ ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ." - - - - + "ಬ್ಯಾಟರಿ %d ರಷ್ಟಿದೆ, ಬ್ಯಾಟರಿ ರಕ್ಷಣೆಗಾಗಿ ಚಾರ್ಜಿಂಗ್ ಅನ್ನು ವಿರಾಮಗೊಳಿಸಲಾಗಿದೆ." + "ಬ್ಯಾಟರಿ %1$d ರಷ್ಟಿದ್ದು %2$s ಗಳ ಕಾಲ ಇರುತ್ತದೆ, ಬ್ಯಾಟರಿ ರಕ್ಷಣೆಗಾಗಿ ಚಾರ್ಜಿಂಗ್ ಅನ್ನು ವಿರಾಮಗೊಳಿಸಲಾಗಿದೆ." "ಎಲ್ಲಾ ಅಧಿಸೂಚನೆಗಳನ್ನು ನೋಡಿ" "ಟೆಲಿಟೈಪ್‌ರೈಟರ್ ಸಕ್ರಿಯವಾಗಿದೆ." "ರಿಂಗರ್ ವೈಬ್ರೇಟ್‌." @@ -501,8 +496,8 @@ "ಬಳಸಲು ಅನ್‌ಲಾಕ್ ಮಾಡಿ" "ನಿಮ್ಮ ಕಾರ್ಡ್‌ಗಳನ್ನು ಪಡೆಯುವಾಗ ಸಮಸ್ಯೆ ಉಂಟಾಗಿದೆ, ನಂತರ ಪುನಃ ಪ್ರಯತ್ನಿಸಿ" "ಲಾಕ್ ಸ್ಕ್ರ್ರೀನ್ ಸೆಟ್ಟಿಂಗ್‌ಗಳು" - - + "QR ಕೋಡ್ ಸ್ಕ್ಯಾನರ್" + "ಅಪ್‌ಡೇಟ್‌‌ ಮಾಡಲಾಗುತ್ತಿದೆ" "ಕೆಲಸದ ಪ್ರೊಫೈಲ್" "ಏರ್‌ಪ್ಲೇನ್ ಮೋಡ್" "ನಿಮ್ಮ ಮುಂದಿನ %1$s ಅಲಾರಮ್ ಅನ್ನು ನೀವು ಆಲಿಸುವುದಿಲ್ಲ" @@ -996,4 +991,17 @@ "EEE, MMM d" "h:mm" "kk:mm" + "%1$s ಅನ್ನು ತೆರೆಯಿರಿ" + "%1$s ಆ್ಯಪ್ ಅನ್ನು ಶಾರ್ಟ್‌ಕಟ್ ಆಗಿ ಸೇರಿಸಲು ಕೆಳಗಿನವುಗಳನ್ನು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಿ" + "• ಆ್ಯಪ್ ಅನ್ನು ಸೆಟಪ್ ಮಾಡಲಾಗಿದೆ" + "• ವಾಲೆಟ್‌ಗೆ ಕನಿಷ್ಠ ಒಂದು ಕಾರ್ಡ್ ಅನ್ನು ಸೇರಿಸಲಾಗಿದೆ" + "• ಕ್ಯಾಮರಾ ಆ್ಯಪ್ ಒಂದನ್ನು ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡಿ" + "• ಆ್ಯಪ್ ಅನ್ನು ಸೆಟಪ್ ಮಾಡಲಾಗಿದೆ" + "• ಕನಿಷ್ಠ ಒಂದು ಸಾಧನ ಲಭ್ಯವಿದೆ" + "ರದ್ದುಗೊಳಿಸಿ" + "ಈಗ ಫ್ಲಿಪ್ ಮಾಡಿ" + "ಉತ್ತಮ ಸೆಲ್ಫೀಗಾಗಿ ಫೋನ್ ಅನ್ನು ಅನ್‌ಫೋಲ್ಡ್ ಮಾಡಿ" + "ಉತ್ತಮ ಸೆಲ್ಫೀಗಾಗಿ ಮುಂಭಾಗದ ಕ್ಯಾಮರಾಗೆ ಫ್ಲಿಪ್ ಮಾಡಬೇಕೆ?" + "ಹೆಚ್ಚಿನ ರೆಸಲ್ಯೂಷನ್ ಹೊಂದಿರುವ ವಿಶಾಲವಾದ ಫೋಟೋಗಾಗಿ ಹಿಂಭಾಗದ ಕ್ಯಾಮರಾವನ್ನು ಬಳಸಿ." + "✱ ಈ ಸ್ಕ್ರೀನ್ ಆಫ್ ಆಗುತ್ತದೆ" diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml index 9e3d6c36aef07..a0f0b1d677e2d 100644 --- a/packages/SystemUI/res/values-ko/strings.xml +++ b/packages/SystemUI/res/values-ko/strings.xml @@ -125,8 +125,7 @@ "음성 지원" "월렛" "QR 코드 스캐너" - - + "잠금 해제됨" "기기 잠김" "얼굴 스캔 중" "보내기" @@ -169,8 +168,7 @@ "얼굴을 인식할 수 없습니다." "대신 지문을 사용하세요." - - + "얼굴 인식 잠금 해제를 사용할 수 없습니다." "블루투스가 연결되었습니다." "배터리 잔량을 알 수 없습니다." "%s에 연결되었습니다." @@ -181,13 +179,10 @@ "비행기 모드입니다." "VPN 켜짐" "배터리 %d퍼센트" - - + "배터리가 %1$d퍼센트로 %2$s 동안 사용 가능합니다." "배터리 충전 중, %d%%입니다." - - - - + "배터리가 %d퍼센트 입니다. 배터리 보호를 위해 충전이 일시중지되었습니다." + "배터리가 %1$d퍼센트로 %2$s 동안 사용 가능합니다. 배터리 보호를 위해 충전이 일시중지되었습니다." "모든 알림 보기" "전신 타자기(TTY)가 사용 설정되었습니다." "벨소리가 진동입니다." @@ -501,8 +496,8 @@ "잠금 해제하여 사용" "카드를 가져오는 중에 문제가 발생했습니다. 나중에 다시 시도해 보세요." "잠금 화면 설정" - - + "QR 코드 스캐너" + "업데이트 중" "직장 프로필" "비행기 모드" "%1$s에 다음 알람을 들을 수 없습니다." @@ -996,4 +991,23 @@ "MMM d일 EEE" "h:mm" "kk:mm" + "%1$s 열기" + "%1$s 앱을 바로가기로 추가하려면 다음을 확인하세요." + "• 앱이 설정되어 있습니다." + "• 1개 이상의 카드가 월렛에 추가되어 있습니다." + "• 카메라 앱이 설치되어 있습니다." + "• 앱이 설정되어 있습니다." + "• 1대 이상의 기기를 사용할 수 있습니다." + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml index bfa6bb8cfcfb0..8d6a0e51cbbe4 100644 --- a/packages/SystemUI/res/values-ky/strings.xml +++ b/packages/SystemUI/res/values-ky/strings.xml @@ -125,8 +125,7 @@ "Үн жардамчысы" "Капчык" "QR коддорунун сканери" - - + "Кулпусу ачылды" "Түзмөк кулпуланды" "Жүз скандалууда" "Жөнөтүү" @@ -169,8 +168,7 @@ "Жүз таанылбай жатат" "Манжа изин колдонуңуз" - - + "\"Жүзүнөн таанып ачуу\" жеткиликсиз" "Bluetooth байланышта" "Батарея кубатынын деңгээли белгисиз." "%s менен туташкан." @@ -181,13 +179,10 @@ "Учак тартиби." "VPN күйүк." "Батарея %d пайыз." - - + "Батареянын кубаты %1$d пайыз, %2$s" "Батарея кубатталууда, %d%%." - - - - + "Батареянын кубаты %d пайыз. Батареяны коргоо үчүн кубаттоо тындырылды." + "Батареянын кубаты %1$d пайыз, %2$s. Батареяны коргоо үчүн кубаттоо тындырылды." "Бардык билдирмелерди көрүү" "ТелеТайп терүүсү жандырылган." "Шыңгыраганда титирөө." @@ -501,8 +496,8 @@ "Колдонуу үчүн кулпусун ачыңыз" "Кыйытмаларды алууда ката кетти. Бир аздан кийин кайталап көрүңүз." "Экранды кулпулоо параметрлери" - - + "QR кодунун сканери" + "Жаңырууда" "Жумуш профили" "Учак режими" "%1$s боло турган кийинки эскертмени укпайсыз" @@ -996,4 +991,23 @@ "EEE, MMM d" "h:mm" "kk:mm" + "%1$s ачуу" + "%1$s колдонмосун ыкчам баскыч катары кошуу үчүн төмөнкүлөрдү аткарыңыз:" + "• Колдонмо туураланды" + "• Капчыкка кеминде бир карта кошулду" + "• Камера колдонмосун орнотуу" + "• Колдонмо туураланды" + "• Кеминде бир түзмөк жеткиликтүү" + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml index e3a9079b6b802..a22bf1fc7debb 100644 --- a/packages/SystemUI/res/values-lo/strings.xml +++ b/packages/SystemUI/res/values-lo/strings.xml @@ -125,8 +125,7 @@ "ຊ່ວຍ​ເຫຼືອ​ທາງ​ສຽງ" "Wallet" "ຕົວສະແກນລະຫັດ QR" - - + "ປົດລັອກແລ້ວ" "ອຸປະກອນຖືກລັອກໄວ້" "ການສະແກນໜ້າ" "ສົ່ງ" @@ -169,8 +168,7 @@ "ບໍ່ສາມາດຈຳແນກໃບໜ້າໄດ້" "ກະລຸນາໃຊ້ລາຍນິ້ວມືແທນ" - - + "ໃຊ້ການປົດລັອກດ້ວຍໜ້າບໍ່ໄດ້" "ເຊື່ອມຕໍ່ Bluetooth ແລ້ວ." "ບໍ່ຮູ້ເປີເຊັນແບັດເຕີຣີ." "ເຊື່ອມ​ຕໍ່​ຫາ %s ແລ້ວ." @@ -181,13 +179,10 @@ "ໂໝດໃນຍົນ." "VPN ເປີດ." "ແບັດເຕີຣີ %d ເປີເຊັນ." - - + "ແບັດເຕີຣີ %1$d ເປີເຊັນ, ໃຊ້ໄດ້ຈົນເຖິງ %2$s" "ກຳລັງສາກແບັດເຕີຣີ, %d ເປີເຊັນ." - - - - + "ແບັດເຕີຣີ %d ເປີເຊັນ, ການສາກຢຸດໄວ້ຊົ່ວຄາວເພື່ອການຮັກສາແບັດເຕີຣີ." + "ແບັດເຕີຣີ %1$d ເປີເຊັນ, ໃຊ້ໄດ້ຈົນເຖິງ %2$s, ການສາກຢຸດໄວ້ຊົ່ວຄາວເພື່ອການຮັກສາແບັດເຕີຣີ." "ເບິ່ງການແຈ້ງເຕືອນທັງໝົດ" "TeleTypewriter ຖືກເປີດຢູ່." "ສັ່ນເຕືອນພ້ອມສຽງເອີ້ນເຂົ້າ." @@ -501,8 +496,8 @@ "ປົດລັອກເພື່ອໃຊ້" "ເກີດບັນຫາໃນການໂຫຼດບັດຂອງທ່ານ, ກະລຸນາລອງໃໝ່ໃນພາຍຫຼັງ" "ການຕັ້ງຄ່າໜ້າຈໍລັອກ" - - + "ຕົວສະແກນລະຫັດ QR" + "ກຳລັງອັບເດດ" "​ໂປຣ​ໄຟລ໌​ບ່ອນ​ເຮັດ​ວຽກ" "ໂໝດເຮືອ​ບິນ" "ທ່ານ​ຈະ​ບໍ່​ໄດ້​ຍິນ​ສຽງ​ໂມງ​ປ %1$s" @@ -996,4 +991,23 @@ "EEE, MMM d" "ຊມ:ນທ" "ຊມ:ນທ" + "ເປີດ %1$s" + "ເພື່ອເພີ່ມແອັບ %1$s ເປັນທາງລັດ, ກະລຸນາກວດສອບໃຫ້ແນ່ໃຈວ່າ" + "• ແອັບໄດ້ຮັບການຕັ້ງຄ່າແລ້ວ" + "• ມີການເພີ່ມຢ່າງໜ້ອຍ 1 ບັດໃສ່ໃນ Wallet" + "• ຕິດຕັ້ງແອັບກ້ອງຖ່າຍຮູບ" + "• ແອັບໄດ້ຮັບການຕັ້ງຄ່າແລ້ວ" + "• ມີຢ່າງໜ້ອຍ 1 ອຸປະກອນພ້ອມໃຫ້ນຳໃຊ້" + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml index 7daedbd20d2d2..ebb6f3f09665d 100644 --- a/packages/SystemUI/res/values-lt/strings.xml +++ b/packages/SystemUI/res/values-lt/strings.xml @@ -125,8 +125,7 @@ "Voice Assist" "Wallet" "QR kodų skaitytuvas" - - + "Atrakinta" "Įrenginys užrakintas" "Nuskaitomas veidas" "Siųsti" @@ -169,8 +168,7 @@ "Veidas neatpažintas" "Naudoti piršto antspaudą" - - + "Atrakinimo pagal veidą funkcija nepasiekiama" "„Bluetooth“ prijungtas." "Akumuliatoriaus energija procentais nežinoma." "Prisijungta prie „%s“." @@ -181,13 +179,10 @@ "Lėktuvo režimas." "VPN įjungtas." "Akumuliatorius: %d proc." - - + "Akumuliatoriaus įkrova %1$d proc., %2$s" "Įkraunamas akumuliatorius, %d%%." - - - - + "Akumuliatoriaus įkrova %d proc., įkrovimas pristabdytas siekiant apsaugoti akumuliatorių." + "Akumuliatoriaus įkrova %1$d proc., %2$s, įkrovimas pristabdytas siekiant apsaugoti akumuliatorių." "Žr. visus pranešimus" "„TeleTypewriter“ įgalinta." "Vibracija skambinant." @@ -501,8 +496,8 @@ "Atrakinti, kad būtų galima naudoti" "Gaunant korteles kilo problema, bandykite dar kartą vėliau" "Užrakinimo ekrano nustatymai" - - + "QR kodų skaitytuvas" + "Atnaujinama" "Darbo profilis" "Lėktuvo režimas" "Negirdėsite kito signalo %1$s" @@ -996,4 +991,17 @@ "EEE, MMM d" "h:mm" "kk:mm" + "Atidaryti „%1$s“" + "Jei norite pridėti programą „%1$s“ kaip šaukinį, įsitikinkite, kad atitinkate reikalavimus." + "• Programa nustatyta" + "• Prie „Wallet“ pridėta bent viena kortelė" + "• Įdiekite Fotoaparato programą" + "• Programa nustatyta" + "• Pasiekiamas bent vienas įrenginys" + "Atšaukti" + "Apversti dabar" + "Užfiksuokite geresnę asmenukę atlenkę telefoną" + "Užfiksuoti geresnę asmenukę įjungus priekinį rodinį?" + "Naudokite galinį fotoaparatą, kad nuotrauka būtų platesnė ir didesnės skyros." + "✱ Šis ekranas išsijungs" diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml index d431233e299e1..93f703fd88119 100644 --- a/packages/SystemUI/res/values-lv/strings.xml +++ b/packages/SystemUI/res/values-lv/strings.xml @@ -125,8 +125,7 @@ "Balss palīgs" "Maks" "Kvadrātkoda skeneris" - - + "Atbloķēta" "Ierīce ir bloķēta" "Sejas skenēšana" "Sūtīt" @@ -169,8 +168,7 @@ "Nevar atpazīt seju" "Lietot pirksta nospiedumu" - - + "Autorizācija pēc sejas nav pieejama" "Bluetooth savienojums ir izveidots." "Akumulatora uzlādes līmenis procentos nav zināms." "Ir izveidots savienojum ar %s." @@ -181,13 +179,10 @@ "Lidmašīnas režīms." "VPN ieslēgts" "Akumulators: %d procenti" - - + "Akumulatora uzlādes līmenis: %1$d, %2$s" "Notiek akumulatora uzlāde, %d%%." - - - - + "Akumulatora uzlādes līmenis: %d, uzlāde ir apturēta, lai aizsargātu akumulatoru." + "Akumulatora uzlādes līmenis: %1$d, %2$s, uzlāde ir apturēta, lai aizsargātu akumulatoru." "Skatīt visus paziņojumus" "Teletaips ir iespējots." "Zvana signāls — vibrācija." @@ -501,8 +496,8 @@ "Lai izmantotu, atbloķējiet ekrānu" "Ienesot jūsu kartes, radās problēma. Lūdzu, vēlāk mēģiniet vēlreiz." "Bloķēšanas ekrāna iestatījumi" - - + "Kvadrātkoda skeneris" + "Notiek atjaunināšana" "Darba profils" "Lidojuma režīms" "Nākamais signāls (%1$s) netiks atskaņots." @@ -996,4 +991,23 @@ "EEE, d. MMM" "hh:mm" "kk:mm" + "Atvērt lietotni %1$s" + "Lai pievienotu lietotni %1$s kā saīsni, jābūt izpildītiem tālāk minētajiem nosacījumiem." + "• Lietotne ir iestatīta." + "• Makam ir pievienota vismaz viena karte." + "• Ir instalēta kameras lietotne." + "• Lietotne ir iestatīta." + "• Ir pieejama vismaz viena ierīce." + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml index de4ae1e92036a..e8d24cbe65d0a 100644 --- a/packages/SystemUI/res/values-mk/strings.xml +++ b/packages/SystemUI/res/values-mk/strings.xml @@ -125,8 +125,7 @@ "Гласовна помош" "Wallet" "Скенер на QR-кодови" - - + "Отклучено" "Уредот е заклучен" "Скенирање лице" "Испрати" @@ -169,8 +168,7 @@ "Не се препознава ликот" "Користи отпечаток" - - + "„Отклучувањето со лик“ е недостапно" "Bluetooth е поврзан." "Процентот на батеријата е непознат." "Поврзано со %s." @@ -181,13 +179,10 @@ "Авионски режим." "VPN е вклучена." "Батерија %d проценти." - - + "Батерија %1$d отсто, %2$s" "Полнење на батеријата, %d отсто." - - - - + "Батерија %d отсто, , полнењето е паузирано за заштита на батеријата." + "Батерија %1$d отсто, %2$s, полнењето е паузирано за заштита на батеријата." "Видете ги сите известувања" "Овозможен е телепринтер." "Ѕвонче на вибрации." @@ -502,6 +497,7 @@ "Имаше проблем при преземањето на картичките. Обидете се повторно подоцна" "Поставки за заклучен екран" "Скенер на QR-кодови" + "Се ажурира" "Работен профил" "Авионски режим" "Нема да го слушнете следниот аларм %1$s" @@ -995,4 +991,17 @@ "EEE, MMM d" "h:mm" "kk:mm" + "Отворете ја %1$s" + "За да ја додадете апликацијата %1$s како кратенка, треба да бидат исполнети следниве услови" + "• апликацијата е поставена" + "• најмалку една картичка е додадена во Wallet" + "• инсталирана е апликација за камера" + "• апликацијата е поставена" + "• достапен е најмалку еден уред" + "Откажи" + "Префрли сега" + "Отворете го телефонот за подобро селфи" + "Да се префрли на предниот екран за подобро селфи?" + "Користете ја задната камера за поширока фотографија со повисока резолуција." + "✱ Екранов ќе се исклучи" diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml index e92ebeae265c3..650aa77fa95a6 100644 --- a/packages/SystemUI/res/values-ml/strings.xml +++ b/packages/SystemUI/res/values-ml/strings.xml @@ -125,8 +125,7 @@ "വോയ്‌സ് സഹായം" "Wallet" "QR കോഡ് സ്കാനർ" - - + "അൺലോക്ക് ചെയ്തു" "ഉപകരണം ലോക്ക് ചെയ്തു" "മുഖം സ്കാൻ ചെയ്യുന്നു" "അയയ്ക്കുക" @@ -169,8 +168,7 @@ "മുഖം തിരിച്ചറിയാനാകുന്നില്ല" "പകരം ഫിംഗർപ്രിന്റ് ഉപയോഗിക്കൂ" - - + "ഫെയ്‌സ് അൺലോക്ക് ലഭ്യമല്ല" "ബ്ലൂടൂത്ത് കണക്‌റ്റുചെയ്തു." "ബാറ്ററി ശതമാനം അജ്ഞാതമാണ്." "%s എന്നതിലേക്ക് കണക്‌റ്റുചെയ്‌തു." @@ -181,13 +179,10 @@ "ഫ്ലൈറ്റ് മോഡ്." "VPN ഓണാണ്." "ബാറ്ററി %d ശതമാനം." - - + "ബാറ്ററി %1$d ശതമാനം, %2$s" "ബാറ്ററി ചാർജ് ചെയ്യുന്നു, %d%%." - - - - + "ബാറ്ററി ചാർജ് %d ശതമാനം, ബാറ്ററി സംരക്ഷിക്കുന്നതിന്, ചാർജ് ചെയ്യൽ താൽക്കാലികമായി നിർത്തി." + "ബാറ്ററി ചാർജ് %1$d ശതമാനം, %2$s, ബാറ്ററി സംരക്ഷിക്കുന്നതിന്, ചാർജ് ചെയ്യൽ താൽക്കാലികമായി നിർത്തി." "എല്ലാ അറിയിപ്പുകളും കാണുക" "TeleTypewriter പ്രവർത്തനക്ഷമമാണ്." "റിംഗർ വൈബ്രേറ്റ് ചെയ്യുന്നു." @@ -501,7 +496,8 @@ "ഉപയോഗിക്കാൻ അൺലോക്ക് ചെയ്യുക" "നിങ്ങളുടെ കാർഡുകൾ ലഭ്യമാക്കുന്നതിൽ ഒരു പ്രശ്‌നമുണ്ടായി, പിന്നീട് വീണ്ടും ശ്രമിക്കുക" "ലോക്ക് സ്ക്രീൻ ക്രമീകരണം" - + "QR കോഡ് സ്കാനർ" + "ഔദ്യോഗിക പ്രൊഫൈൽ" "ഫ്ലൈറ്റ് മോഡ്" @@ -996,4 +992,30 @@ "EEE, MMM d" "h:mm" "kk:mm" + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml index 005a04170ccc9..b2a7df80bf331 100644 --- a/packages/SystemUI/res/values-mn/strings.xml +++ b/packages/SystemUI/res/values-mn/strings.xml @@ -125,8 +125,7 @@ "Дуут туслах" "Wallet" "QR код сканнер" - - + "Түгжээг тайлсан" "Төхөөрөмжийг түгжсэн" "Скан хийх нүүр царай" "Илгээх" @@ -169,8 +168,7 @@ "Царайг танихгүй байна" "Оронд нь хурууны хээ ашиглах" - - + "Царайгаар түгжээ тайлах боломжгүй" "Bluetooth холбогдсон." "Батарейн хувь тодорхойгүй байна." "%s-тай холбогдсон." @@ -181,13 +179,10 @@ "Нислэгийн горим" "VPN асаалттай байна." "Батарей %d хувьтай." - - + "Батарей %1$d хувь, %2$s" "Батарейг цэнэглэж байна, %d%%." - - - - + "Батарей %d хувь, батарейг хамгаалахын тулд цэнэглэхийг түр зогсоосон." + "Батарей %1$d хувь, %2$s, батарейг хамгаалахын тулд цэнэглэхийг түр зогсоосон." "Бүх мэдэгдлийг харах" "TeleTypewriter идэвхтэй болов." "Хонхны чичиргээ." @@ -502,6 +497,7 @@ "Таны картыг авахад асуудал гарлаа. Дараа дахин оролдоно уу" "Түгжигдсэн дэлгэцийн тохиргоо" "QR код сканнер" + "Шинэчилж байна" "Ажлын профайл" "Нислэгийн горим" "%1$s-т та дараагийн сэрүүлгээ сонсохгүй" @@ -995,4 +991,23 @@ "MMM d EEE" "h:mm" "kk:mm" + "%1$s-г нээх" + "%1$s аппыг товчлолоор нэмэхийн тулд дараахыг баталгаажуулна уу" + "• Аппыг тохируулсан" + "• Дор хаяж нэг картыг Wallet-д нэмсэн" + "• Камер аппыг суулгах" + "• Аппыг тохируулсан" + "• Дор хаяж нэг төхөөрөмж боломжтой" + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml index 2810cb7317001..176f996dfe25e 100644 --- a/packages/SystemUI/res/values-mr/strings.xml +++ b/packages/SystemUI/res/values-mr/strings.xml @@ -125,8 +125,7 @@ "व्हॉइस सहाय्य" "वॉलेट" "QR कोड स्कॅनर" - - + "अनलॉक केले" "डिव्हाइस लॉक केले" "चेहरा स्कॅन करत आहे" "पाठवा" @@ -169,8 +168,7 @@ "चेहरा ओळखू शकत नाही" "त्याऐवजी फिंगरप्रिंट वापरा" - - + "फेस अनलॉक उपलब्ध नाही" "ब्लूटूथ कनेक्‍ट केले." "बॅटरीच्या चार्जिंगची टक्केवारी माहित नाही." "%s शी कनेक्‍ट केले." @@ -181,13 +179,10 @@ "विमान मोड." "VPN सुरू." "बॅटरी %d टक्के." - - + "बॅटरी %1$d टक्के आहे, %2$s" "बॅटरी चार्ज होत आहे, %d टक्के." - - - - + "बॅटरी %d टक्के आहे, बॅटरीच्या संंरक्षणासाठी चार्ज करणे थांबवले." + "बॅटरी %1$d टक्के आहे, %2$s, बॅटरीच्या संंरक्षणासाठी चार्ज करणे थांबवले." "सर्व सूचना पहा" "TeleTypewriter सक्षम केले." "रिंगर व्हायब्रेट." @@ -501,8 +496,8 @@ "वापरण्यासाठी अनलॉक करा" "तुमची कार्ड मिळवताना समस्या आली, कृपया नंतर पुन्हा प्रयत्न करा" "लॉक स्क्रीन सेटिंग्ज" - - + "QR कोड स्कॅनर" + "अपडेट करत आहे" "कार्य प्रोफाईल" "विमान मोड" "तुम्ही तुमचा %1$s वाजता होणारा पुढील अलार्म ऐकणार नाही" @@ -996,4 +991,23 @@ "EEE, MMM d" "h:mm" "kk:mm" + "%1$s उघडा" + "%1$s हे अ‍ॅप शॉर्टकट म्हणून जोडण्यासाठी, पुढील गोष्टींची खात्री करा" + "• अ‍ॅप सेट करणे" + "• Wallet मध्ये किमान एक कार्ड जोडणे" + "• कॅमेरा अ‍ॅप इंस्टॉल करणे" + "• अ‍ॅप सेट करणे" + "• किमान एक डिव्हाइस उपलब्ध करणे" + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml index 1d82ec09c4848..049da6da90049 100644 --- a/packages/SystemUI/res/values-ms/strings.xml +++ b/packages/SystemUI/res/values-ms/strings.xml @@ -125,8 +125,7 @@ "Bantuan Suara" "Wallet" "Pengimbas Kod QR" - - + "Tidak berkunci" "Peranti dikunci" "Mengimbas wajah" "Hantar" @@ -169,8 +168,7 @@ "Tak dapat mengecam wajah" "Gunakan cap jari" - - + "Buka Kunci Wajah tidak tersedia" "Bluetooth disambungkan." "Peratusan kuasa bateri tidak diketahui." "Disambungkan kepada %s." @@ -181,13 +179,10 @@ "Mod pesawat" "VPN dihidupkan." "Bateri %d peratus." - - + "Bateri %1$d peratus, %2$s" "Bateri mengecas, %d peratus." - - - - + "Bateri %d peratus, pengecasan dijeda demi perlindungan bateri." + "Bateri %1$d peratus, %2$s, pengecasan dijeda demi perlindungan bateri." "Lihat semua pemberitahuan" "Mesin Teletaip didayakan." "Pendering bergetar." @@ -502,6 +497,7 @@ "Terdapat masalah sewaktu mendapatkan kad anda. Sila cuba sebentar lagi" "Tetapan skrin kunci" "Pengimbas kod QR" + "Mengemaskinikan" "Profil kerja" "Mod pesawat" "Anda tidak akan mendengar penggera yang seterusnya %1$s" @@ -995,4 +991,23 @@ "EEE, d MMM" "h:mm" "kk:mm" + "Buka %1$s" + "Untuk menambahkan apl %1$s sebagai pintasan, pastikan" + "• Apl disediakan" + "• Sekurang-kurangnya satu kad telah ditambahkan pada Wallet" + "• Pasang apl kamera" + "• Apl disediakan" + "• Sekurang-kurangnya satu peranti tersedia" + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml index f79e32f8f7137..fc2137b8f2e6c 100644 --- a/packages/SystemUI/res/values-my/strings.xml +++ b/packages/SystemUI/res/values-my/strings.xml @@ -125,8 +125,7 @@ "အသံ အကူအညီ" "Wallet" "QR ကုဒ်ဖတ်စနစ်" - - + "လော့ခ်ဖွင့်ထားသည်" "စက်ပစ္စည်းကို လော့ခ်ချထားသည်" "မျက်နှာ စကင်ဖတ်နေသည်" "ပို့ရန်" @@ -169,8 +168,7 @@ "မျက်နှာကို မမှတ်မိပါ" "လက်ဗွေကို အစားထိုးသုံးပါ" - - + "မျက်နှာပြ လော့ခ်ဖွင့်ခြင်း မရနိုင်ပါ" "ဘလူးတုသ်ချိတ်ဆက်ထားမှု" "ဘက်ထရီရာခိုင်နှုန်းကို မသိပါ။" "%sသို့ ချိတ်ဆက်ထား" @@ -181,13 +179,10 @@ "လေယာဉ်ပျံမုဒ်" "VPN ကို ဖွင့်ထားသည်။" "ဘက်ထရီ %d ရာခိုင်နှုန်း။" - - + "ဘက်ထရီ %1$d ရာခိုင်နှုန်း။ %2$s" "ဘက်ထရီအားသွင်းနေသည်၊ %d %%။" - - - - + "ဘက်ထရီ %d ရာခိုင်နှုန်း။ ဘက်ထရီကာကွယ်ရန် အားသွင်းမှု ခဏရပ်ထားသည်။" + "ဘက်ထရီ %1$d ရာခိုင်နှုန်း။ %2$s။ ဘက်ထရီကာကွယ်ရန် အားသွင်းမှု ခဏရပ်ထားသည်။" "သတိပေးချက်များအားလုံးကို ကြည့်ရန်" "TeleTypewriter ရရှိသည်။" "တုန်ခါခြင်း ဖုန်းမြည်သံ" @@ -501,7 +496,8 @@ "သုံးရန် လော့ခ်ဖွင့်ပါ" "သင်၏ကတ်များ ရယူရာတွင် ပြဿနာရှိနေသည်၊ နောက်မှ ထပ်စမ်းကြည့်ပါ" "လော့ခ်မျက်နှာပြင် ဆက်တင်များ" - + "QR ကုဒ် စကင်ဖတ်စနစ်" + "အလုပ် ပရိုဖိုင်" "လေယာဉ်ပျံမုဒ်" @@ -996,4 +992,30 @@ "EEE၊ MMM d" "h:mm" "kk:mm" + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml index bbd5dc9d0f926..adfccb7967b13 100644 --- a/packages/SystemUI/res/values-nb/strings.xml +++ b/packages/SystemUI/res/values-nb/strings.xml @@ -125,8 +125,7 @@ "Talehjelp" "Wallet" "QR-kodeskanner" - - + "Ulåst" "Enheten er låst" "Skanning av ansikt" "Send" @@ -169,8 +168,7 @@ "Ansiktet gjenkjennes ikke" "Bruk fingeravtrykk" - - + "Ansiktslås er utilgjengelig" "Bluetooth er tilkoblet." "Batteriprosenten er ukjent." "Koblet til %s." @@ -181,13 +179,10 @@ "Flymodus." "VPN på." "Batteri – %d prosent." - - + "Batterinivået er %1$d prosent, %2$s" "Batteriet lades – %d prosent." - - - - + "Batterinivået er %d prosent. Lading er satt på pause for å beskytte batteriet." + "Batterinivået er %1$d prosent, %2$s. Lading er satt på pause for å beskytte batteriet." "Se alle varslene" "TeleTypewriter er aktivert." "Vibreringsmodus." @@ -501,8 +496,8 @@ "Lås opp for å bruke" "Det oppsto et problem med henting av kortene. Prøv på nytt senere" "Innstillinger for låseskjermen" - - + "QR-kodeskanner" + "Oppdaterer" "Work-profil" "Flymodus" "Du hører ikke neste innstilte alarm %1$s" @@ -996,4 +991,23 @@ "EEE d. MMM" "h:mm" "kk:mm" + "Åpne %1$s" + "For å legge til %1$s-appen som en snarvei må du sørge for at" + "• appen er konfigurert" + "• minst ett kort er lagt til i Wallet" + "• en kameraapp er installert" + "• appen er konfigurert" + "• minst én enhet er tilgjengelig" + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml index 3baf1de484aa8..fee1ffdb24269 100644 --- a/packages/SystemUI/res/values-ne/strings.xml +++ b/packages/SystemUI/res/values-ne/strings.xml @@ -125,8 +125,7 @@ "आवाज सहायता" "Wallet" "QR कोड स्क्यानर" - - + "अनलक गरिएको छ" "यन्त्र लक गरिएको छ" "अनुहार स्क्यान गर्दै" "पठाउनुहोस्" @@ -169,8 +168,7 @@ "अनुहार पहिचान गर्न सकिएन" "बरु फिंगरप्रिन्ट प्रयोग गर्नुहोस्" - - + "फेस अनलक उपलब्ध छैन" "ब्लुटुथ जडान भयो।" "ब्याट्रीमा कति प्रतिशत चार्ज छ भन्ने कुराको जानाकरी छैन।" "%s मा जडित।" @@ -181,13 +179,10 @@ "हवाइजहाज मोड।" "VPN सक्रिय छ।" "ब्याट्री %d प्रतिशत" - - + "ब्याट्री %1$d प्रतिशत, %2$s" "ब्याट्री चार्ज हुँदैछ, %d प्रतिशत भयो।" - - - - + "ब्याट्री %d प्रतिशत, ब्याट्री जोगाउन चार्ज गर्ने कार्य पज गरिएको छ।" + "ब्याट्री %1$d प्रतिशत, %2$s, ब्याट्री जोगाउन चार्ज गर्ने कार्य पज गरिएको छ।" "सबै सूचनाहरू हेर्नुहोस्" "टेलि टाइपराइटर सक्षम गरियो।" "बज्ने कम्पन हुन्छ।" @@ -501,7 +496,8 @@ "यो वालेट प्रयोग गर्न डिभाइस अनलक गर्नुहोस्" "तपाईंका कार्डहरू प्राप्त गर्ने क्रममा समस्या भयो, कृपया पछि फेरि प्रयास गर्नुहोस्" "लक स्क्रिनसम्बन्धी सेटिङ" - + "QR कोड स्क्यानर" + "कार्य प्रोफाइल" "हवाइजहाज मोड" @@ -996,4 +992,30 @@ "EEE, MMM d" "h:mm" "kk:mm" + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml index 84d5b6d680d1e..aa7f59e67f2ff 100644 --- a/packages/SystemUI/res/values-nl/strings.xml +++ b/packages/SystemUI/res/values-nl/strings.xml @@ -117,7 +117,7 @@ "Terug" "Startscherm" "Menu" - "Toegankelijkheid" + "Toe­gankelijk­heid" "Scherm draaien" "Overzicht" "Camera" @@ -125,8 +125,7 @@ "Spraakassistent" "Portemonnee" "QR-codescanner" - - + "Ontgrendeld" "Apparaat vergrendeld" "Gezicht scannen" "Verzenden" @@ -169,8 +168,7 @@ "Gezicht niet herkend" "Vingerafdruk gebruiken" - - + "Ontgrendelen via gezichtsherkenning niet beschikbaar" "Bluetooth-verbinding ingesteld." "Batterijpercentage onbekend." "Verbonden met %s." @@ -181,13 +179,10 @@ "Vliegtuigmodus." "VPN staat aan." "Batterij: %d procent." - - + "Batterij: %1$d procent, %2$s" "Batterij wordt opgeladen, %d%% procent." - - - - + "Batterij %d procent. Opladen is onderbroken om de batterij te beschermen." + "Batterij %1$d procent, %2$s. Opladen is onderbroken om de batterij te beschermen." "Alle meldingen bekijken" "TeleTypewriter staat aan." "Belsoftware trilt." @@ -471,7 +466,7 @@ "Melding" "Bluetooth" "Frequentie voor tweevoudige multitoon" - "Toegankelijkheid" + "Toe­gankelijk­heid" "Bellen" "Trillen" "Geluid staat uit" @@ -501,10 +496,10 @@ "Ontgrendelen om te gebruiken" "Er is een probleem opgetreden bij het ophalen van je kaarten. Probeer het later opnieuw." "Instellingen voor vergrendelscherm" - - + "QR-codescanner" + "Updaten" "Werkprofiel" - "Vliegtuigmodus" + "Vliegtuig­modus" "Je hoort je volgende wekker niet %1$s" "om %1$s" "op %1$s" @@ -996,4 +991,23 @@ "EEE d mmm" "u:mm" "kk:mm" + "%1$s openen" + "Zorg voor het volgende om de %1$s-app toe te voegen als snelkoppeling:" + "• De app is ingesteld" + "• Er is ten minste één kaart aan Wallet toegevoegd" + "• Er moet een camera-app zijn geïnstalleerd" + "• De app is ingesteld" + "• Er is ten minste één apparaat beschikbaar" + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml index 433170e24b567..1cda6deba4269 100644 --- a/packages/SystemUI/res/values-or/strings.xml +++ b/packages/SystemUI/res/values-or/strings.xml @@ -125,8 +125,7 @@ "ଭଏସ୍‌ ସହାୟକ" "ୱାଲେଟ୍" "QR କୋଡ ସ୍କାନର" - - + "ଅନଲକ କରାଯାଇଛି" "ଡିଭାଇସ୍ ଲକ୍ ହୋଇଯାଇଛି" "ଫେସ୍ ସ୍କାନିଙ୍ଗ କରାଯାଉଛି" "ପଠାନ୍ତୁ" @@ -169,8 +168,7 @@ "ଫେସ ଚିହ୍ନଟ ହୋଇପାରିବ ନାହିଁ" "ଟିପଚିହ୍ନ ବ୍ୟବହାର କରନ୍ତୁ" - - + "ଫେସ ଅନଲକ ଉପଲବ୍ଧ ନାହିଁ" "ବ୍ଲୁଟୂଥ୍‍‌ ସଂଯୋଗ କରାଯାଇଛି।" "ବ୍ୟାଟେରୀ ଶତକଡ଼ା ଅଜଣା ଅଟେ।" "%s ସହ ସଂଯୁକ୍ତ" @@ -181,13 +179,10 @@ "ଏରୋପ୍ଲେନ୍‍ ମୋଡ୍‌।" "VPN ଅନ୍‍।" "ବ୍ୟାଟେରୀ %d ଶତକଡ଼ା।" - - + "ବେଟେରୀ %1$d ଶତକଡ଼ା, %2$s" "ବ୍ୟାଟେରୀ ଚାର୍ଜ ହେଉଛି, %d ଶତକଡ଼ା।" - - - - + "ବେଟେରୀ %d ଶତକଡ଼ା, ବେଟେରୀର ସୁରକ୍ଷା ପାଇଁ ଚାର୍ଜିଂକୁ ବିରତ କରାଯାଇଛି।" + "ବେଟେରୀ %1$d ଶତକଡ଼ା, %2$s, ବେଟେରୀର ସୁରକ୍ଷା ପାଇଁ ଚାର୍ଜିଂକୁ ବିରତ କରାଯାଇଛି।" "ସମସ୍ତ ବିଜ୍ଞପ୍ତି ଦେଖନ୍ତୁ" "ଟେଲି-ଟାଇପରାଇଟର୍ ସକ୍ଷମ ଅଛି।" "ରିଙ୍ଗର୍‌ କମ୍ପନରେ ଅଛି।" @@ -502,6 +497,7 @@ "ଆପଣଙ୍କ କାର୍ଡଗୁଡ଼ିକ ପାଇବାରେ ଏକ ସମସ୍ୟା ହୋଇଥିଲା। ଦୟାକରି ପରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ" "ସ୍କ୍ରିନ୍ ଲକ୍ ସେଟିଂସ୍" "QR କୋଡ ସ୍କାନର" + "ଅପଡେଟ ହେଉଛି" "ୱର୍କ ପ୍ରୋଫାଇଲ୍‌" "ଏରୋପ୍ଲେନ୍‍ ମୋଡ୍" "%1$sବେଳେ ଆପଣ ନିଜର ପରବର୍ତ୍ତୀ ଆଲାର୍ମ ଶୁଣିପାରିବେ ନାହିଁ" @@ -530,7 +526,7 @@ "ସ୍ୱଚାଳିତ" "କୌଣସି ସାଉଣ୍ଡ କିମ୍ବା ଭାଇବ୍ରେସନ୍ ନାହିଁ" "କୌଣସି ସାଉଣ୍ଡ କିମ୍ବା ଭାଇବ୍ରେସନ୍ ନାହିଁ ଏବଂ ବାର୍ତ୍ତାଳାପ ବିଭାଗର ନିମ୍ନରେ ଦେଖାଯାଏ" - "ଫୋନ୍ ସେଟିଂସ୍ ଆଧାରରେ ରିଙ୍ଗ କିମ୍ବା ଭାଇବ୍ରେଟ୍ ହୋଇପାରେ" + "ଫୋନ ସେଟିଂସ ଆଧାରରେ ରିଙ୍ଗ କିମ୍ବା ଭାଇବ୍ରେଟ ହୋଇପାରେ" "ଫୋନ୍ ସେଟିଂସ୍ ଆଧାରରେ ରିଙ୍ଗ କିମ୍ବା ଭାଇବ୍ରେଟ୍ ହୋଇପାରେ। %1$sରୁ ବାର୍ତ୍ତାଳାପଗୁଡ଼ିକ ଡିଫଲ୍ଟ ଭାବରେ ବବଲ୍ ହୁଏ।" "ଏହି ବିଜ୍ଞପ୍ତି ପ୍ରାପ୍ତ ହେବା ସମୟରେ ସାଉଣ୍ଡ ହେବା ଉଚିତ ନା ଭାଇବ୍ରେସନ୍ ତାହା ସିଷ୍ଟମକୁ ସ୍ଥିର କରିବାକୁ ଦିଅନ୍ତୁ" "<b>ସ୍ଥିତି:</b> ଡିଫଲ୍ଟକୁ ପ୍ରମୋଟ୍ କରାଯାଇଛି" @@ -665,7 +661,7 @@ "ଏହି ଆଇକନ୍‍ ଦେଖାନ୍ତୁ ନାହିଁ" "କମ୍‍-ଅଗ୍ରାଧିକାର ବିଜ୍ଞପ୍ତି ଆଇକନ୍‍ ଦେଖାନ୍ତୁ" - "ଅନ୍ୟାନ୍ୟ" + "ଅନ୍ୟ" "ଟାଇଲ୍ କାଢ଼ି ଦିଅନ୍ତୁ" "ଶେଷରେ ଟାଇଲ୍ ଯୋଗ କରନ୍ତୁ" "ଟାଇଲ୍ ମୁଭ୍ କରନ୍ତୁ" @@ -995,4 +991,23 @@ "EEE, MMM d" "h:mm" "kk:mm" + "%1$s ଖୋଲନ୍ତୁ" + "ଏକ ସର୍ଟକଟ ଭାବେ %1$s ଆପ ଯୋଗ କରିବାକୁ, ଏହା ସୁନିଶ୍ଚିତ କରନ୍ତୁ" + "• ଆପ ସେଟ ଅପ କରାଯାଇଥିବା" + "• Walletରେ ଅତିକମରେ ଗୋଟିଏ କାର୍ଡ ଯୋଗ କରାଯାଇଥିବା" + "• ଏକ କେମେରା ଆପ ଇନଷ୍ଟଲ କରିବା" + "• ଆପ ସେଟ ଅପ କରାଯାଇଛି" + "• ଅତିକମରେ ଗୋଟିଏ ଡିଭାଇସ ଉପଲବ୍ଧ ଅଛି" + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml index ed4988f11dc72..15010ad2240db 100644 --- a/packages/SystemUI/res/values-pa/strings.xml +++ b/packages/SystemUI/res/values-pa/strings.xml @@ -125,8 +125,7 @@ "ਅਵਾਜ਼ੀ ਸਹਾਇਕ" "Wallet" "QR ਕੋਡ ਸਕੈਨਰ" - - + "ਅਣਲਾਕ ਹੈ" "ਡੀਵਾਈਸ ਲਾਕ ਹੈ" "ਚਿਹਰਾ ਸਕੈਨ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ" "ਭੇਜੋ" @@ -169,8 +168,7 @@ "ਚਿਹਰੇ ਦੀ ਪਛਾਣ ਨਹੀਂ ਹੋਈ" "ਇਸਦੀ ਬਜਾਏ ਫਿੰਗਰਪ੍ਰਿੰਟ ਵਰਤੋ" - - + "ਫ਼ੇਸ ਅਣਲਾਕ ਉਪਲਬਧ ਨਹੀਂ ਹੈ" "Bluetooth ਕਨੈਕਟ ਕੀਤੀ।" "ਬੈਟਰੀ ਪ੍ਰਤੀਸ਼ਤ ਅਗਿਆਤ ਹੈ।" "%s ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ।" @@ -181,13 +179,10 @@ "ਏਅਰਪਲੇਨ ਮੋਡ।" "VPN ਚਾਲੂ ਹੈ।" "ਬੈਟਰੀ %d ਪ੍ਰਤੀਸ਼ਤ ਹੈ।" - - + "ਬੈਟਰੀ %1$d ਫ਼ੀਸਦ, %2$s" "ਬੈਟਰੀ ਚਾਰਜ ਹੋ ਰਹੀ ਹੈ, %d ਪ੍ਰਤੀਸ਼ਤ ਹੋ ਗਈ।" - - - - + "ਬੈਟਰੀ %d ਫ਼ੀਸਦ, ਬੈਟਰੀ ਦੀ ਸੁਰੱਖਿਆ ਲਈ ਚਾਰਜਿੰਗ ਨੂੰ ਰੋਕਿਆ ਨੂੰ ਚਲਾਉਂਦੀ ਹੈ" + "ਬੈਟਰੀ %1$d ਫ਼ੀਸਦ, %2$s, ਬੈਟਰੀ ਦੀ ਸੁਰੱਖਿਆ ਲਈ ਚਾਰਜਿੰਗ ਨੂੰ ਰੋਕਿਆ ਗਿਆ।" "ਸਾਰੀਆਂ ਸੂਚਨਾਵਾਂ ਦੇਖੋ" "ਟੈਲੀ ਟਾਈਪਰਾਈਟਰ ਸਮਰਥਿਤ।" "ਰਿੰਗਰ ਥਰਥਰਾਹਟ।" @@ -501,8 +496,8 @@ "ਵਰਤਣ ਲਈ ਅਣਲਾਕ ਕਰੋ" "ਤੁਹਾਡੇ ਕਾਰਡ ਪ੍ਰਾਪਤ ਕਰਨ ਵਿੱਚ ਕੋਈ ਸਮੱਸਿਆ ਆਈ, ਕਿਰਪਾ ਕਰਕੇ ਬਾਅਦ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ" "ਲਾਕ ਸਕ੍ਰੀਨ ਸੈਟਿੰਗਾਂ" - - + "QR ਕੋਡ ਸਕੈਨਰ" + "ਅੱਪਡੇਟ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ" "ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ" "ਹਵਾਈ-ਜਹਾਜ਼ ਮੋਡ" "ਤੁਸੀਂ %1$s ਵਜੇ ਆਪਣਾ ਅਗਲਾ ਅਲਾਰਮ ਨਹੀਂ ਸੁਣੋਗੇ" @@ -996,4 +991,23 @@ "EEE, MMM d" "h:mm" "kk:mm" + "%1$s ਖੋਲ੍ਹੋ" + "%1$s ਐਪ ਨੂੰ ਸ਼ਾਰਟਕੱਟ ਵਜੋਂ ਸ਼ਾਮਲ ਕਰਨ ਲਈ, ਪੱਕਾ ਕਰੋ ਕਿ" + "• ਐਪ ਦਾ ਸੈੱਟਅੱਪ ਹੋ ਗਿਆ ਹੈ" + "• ਘੱਟੋ-ਘੱਟ ਇੱਕ ਕਾਰਡ ਨੂੰ Wallet ਵਿੱਚ ਸ਼ਾਮਲ ਕੀਤਾ ਗਿਆ ਹੈ" + "• ਕੈਮਰਾ ਐਪ ਸਥਾਪਤ ਕਰੋ" + "• ਐਪ ਦਾ ਸੈੱਟਅੱਪ ਹੋ ਗਿਆ ਹੈ" + "• ਘੱਟੋ-ਘੱਟ ਇੱਕ ਡੀਵਾਈਸ ਉਪਲਬਧ ਹੈ" + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml index 47b68b10be09b..39f7c30c42e2a 100644 --- a/packages/SystemUI/res/values-pl/strings.xml +++ b/packages/SystemUI/res/values-pl/strings.xml @@ -125,8 +125,7 @@ "Asystent głosowy" "Portfel" "Skaner kodów QR" - - + "Odblokowano" "Urządzenie zablokowane" "Skanowanie twarzy" "Wyślij" @@ -169,8 +168,7 @@ "Nie można rozpoznać twarzy" "Użyj odcisku palca" - - + "Rozpoznawanie twarzy niedostępne" "Bluetooth połączony." "Poziom naładowania baterii jest nieznany." "Połączono z %s." @@ -181,13 +179,10 @@ "Tryb samolotowy." "Sieć VPN włączona." "Bateria: %d procent." - - + "Bateria: %1$d procent, %2$s." "Ładuję baterię, %d procent." - - - - + "Bateria %d procent. Ładowanie zostało wstrzymane, aby utrzymać baterię w dobrym stanie." + "Bateria %1$d procent, %2$s. Ładowanie zostało wstrzymane, aby utrzymać baterię w dobrym stanie." "Zobacz wszystkie powiadomienia" "Dalekopis (TTY) włączony." "Dzwonek z wibracjami." @@ -501,8 +496,8 @@ "Odblokuj, aby użyć" "Podczas pobierania kart wystąpił problem. Spróbuj ponownie później." "Ustawienia ekranu blokady" - - + "Skaner kodów QR" + "Aktualizuję" "Profil służbowy" "Tryb samolotowy" "Nie usłyszysz swojego następnego alarmu %1$s" @@ -996,4 +991,23 @@ "EEE, d MMM" "h:mm" "kk:mm" + "Otwórz: %1$s" + "Aby dodać aplikację %1$s jako skrót, upewnij się, że spełnione zostały te warunki:" + "• Aplikacja została skonfigurowana." + "• Do Portfela została dodana co najmniej 1 karta." + "• Zainstalowano aplikację aparatu." + "• Aplikacja została skonfigurowana." + "• Dostępne jest co najmniej 1 urządzenie." + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml index 4ff823aee2d69..1630d08dce42a 100644 --- a/packages/SystemUI/res/values-pt-rBR/strings.xml +++ b/packages/SystemUI/res/values-pt-rBR/strings.xml @@ -125,8 +125,7 @@ "Assistência de voz" "Carteira" "Leitor de código QR" - - + "Desbloqueado" "Dispositivo bloqueado" "Verificando rosto" "Enviar" @@ -169,8 +168,7 @@ "Rosto não reconhecido" "Use a impressão digital" - - + "O Desbloqueio facial não está disponível" "Bluetooth conectado." "Porcentagem da bateria desconhecida." "Conectado a %s." @@ -181,13 +179,10 @@ "Modo avião." "VPN ativada." "Bateria em %d por cento." - - + "Bateria em %1$d de carga, %2$s" "Bateria carregando: %d%%." - - - - + "Bateria com %d de carga, o carregamento foi pausado para proteção da bateria." + "Bateria com %1$d de carga, %2$s, o carregamento foi pausado para proteção da bateria." "Ver todas as notificações" "TeleTYpewriter ativado." "Vibração da campainha." @@ -501,7 +496,8 @@ "Desbloquear para usar" "Ocorreu um problema ao carregar os cards. Tente novamente mais tarde" "Configurações de tela de bloqueio" - + "Leitor de código QR" + "Perfil de trabalho" "Modo avião" @@ -996,4 +992,30 @@ "EEE, d de MMM" "h:mm" "kk:mm" + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml index a50624e76c06c..22bb507090e48 100644 --- a/packages/SystemUI/res/values-pt-rPT/strings.xml +++ b/packages/SystemUI/res/values-pt-rPT/strings.xml @@ -168,8 +168,7 @@ "Imposs. reconhecer rosto" "Usar impressão digital" - - + "Desbloqueio facial indisponível" "Bluetooth ligado." "Percentagem da bateria desconhecida." "Ligado a %s." @@ -180,13 +179,10 @@ "Modo de avião" "VPN ativada." "Bateria a %d por cento." - - + "Bateria a %1$d por cento, %2$s" "Bateria a carregar (%d %%)." - - - - + "Bateria a %d por cento, o carregamento foi pausado para proteção da bateria." + "Bateria a %1$d por cento, %2$s, o carregamento foi pausado para proteção da bateria." "Ver todas as notificações" "Teletipo ativado." "Campainha em vibração." @@ -501,6 +497,7 @@ "Ocorreu um problema ao obter os seus cartões. Tente mais tarde." "Definições do ecrã de bloqueio" "Leitor de códigos QR" + "A atualizar" "Perfil de trabalho" "Modo de avião" "Não vai ouvir o próximo alarme às %1$s" @@ -994,4 +991,17 @@ "EEE, d de MMM" "h:mm" "kk:mm" + "Abrir %1$s" + "Para adicionar a app %1$s como um atalho, garanta" + "• A app está configurada" + "• Foi adicionado, pelo menos, um cartão à Carteira" + "• Instale uma app de câmara" + "• A app está configurada" + "• Está disponível, pelo menos, um dispositivo" + "Cancelar" + "Inverter agora" + "Desdobre o telemóvel para uma selfie melhor" + "Inverter para ecrã frontal para uma selfie melhor?" + "Use a câmara traseira para uma foto mais ampla com uma resolução superior." + "✱ Este ecrã vai ser desligado" diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml index 4ff823aee2d69..1630d08dce42a 100644 --- a/packages/SystemUI/res/values-pt/strings.xml +++ b/packages/SystemUI/res/values-pt/strings.xml @@ -125,8 +125,7 @@ "Assistência de voz" "Carteira" "Leitor de código QR" - - + "Desbloqueado" "Dispositivo bloqueado" "Verificando rosto" "Enviar" @@ -169,8 +168,7 @@ "Rosto não reconhecido" "Use a impressão digital" - - + "O Desbloqueio facial não está disponível" "Bluetooth conectado." "Porcentagem da bateria desconhecida." "Conectado a %s." @@ -181,13 +179,10 @@ "Modo avião." "VPN ativada." "Bateria em %d por cento." - - + "Bateria em %1$d de carga, %2$s" "Bateria carregando: %d%%." - - - - + "Bateria com %d de carga, o carregamento foi pausado para proteção da bateria." + "Bateria com %1$d de carga, %2$s, o carregamento foi pausado para proteção da bateria." "Ver todas as notificações" "TeleTYpewriter ativado." "Vibração da campainha." @@ -501,7 +496,8 @@ "Desbloquear para usar" "Ocorreu um problema ao carregar os cards. Tente novamente mais tarde" "Configurações de tela de bloqueio" - + "Leitor de código QR" + "Perfil de trabalho" "Modo avião" @@ -996,4 +992,30 @@ "EEE, d de MMM" "h:mm" "kk:mm" + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml index e281e88da8589..944af8f492836 100644 --- a/packages/SystemUI/res/values-ro/strings.xml +++ b/packages/SystemUI/res/values-ro/strings.xml @@ -125,8 +125,7 @@ "Asistent vocal" "Portofel" "Scanner de coduri QR" - - + "Descuiat" "Dispozitiv blocat" "Scanarea chipului" "Trimite" @@ -169,8 +168,7 @@ "Chip nerecunoscut" "Folosește amprenta" - - + "Deblocarea facială nu este disponibilă" "Conectat prin Bluetooth." "Procentajul bateriei este necunoscut." "Conectat la %s." @@ -181,13 +179,10 @@ "Mod Avion." "Rețea VPN activată" "Baterie: %d la sută." - - + "Baterie la %1$d , %2$s" "Bateria se încarcă, %d la sută." - - - - + "Baterie la %d ; încărcare întreruptă pentru protejarea bateriei." + "Baterie la %1$d ; %2$s, încărcare întreruptă pentru protejarea bateriei." "Vezi toate notificările" "TeleTypewriter activat." "Vibrare sonerie." @@ -502,6 +497,7 @@ "A apărut o problemă la preluarea cardurilor. Încearcă din nou mai târziu" "Setările ecranului de blocare" "Scanner de coduri QR" + "Se actualizează" "Profil de serviciu" "Mod Avion" "Nu vei auzi următoarea alarmă %1$s" @@ -995,4 +991,23 @@ "EE, z LLL" "h:mm" "kk:mm" + "Deschide %1$s" + "Pentru a adăuga aplicația %1$s drept comandă rapidă, asigură-te" + "• Aplicația este configurată" + "• Cel puțin un card a fost adăugat în Portofel" + "• Instalează o aplicație pentru camera foto" + "• Aplicația este configurată" + "• Este disponibil cel puțin un dispozitiv" + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml index b7f10f2943d27..20816c84839c9 100644 --- a/packages/SystemUI/res/values-ru/strings.xml +++ b/packages/SystemUI/res/values-ru/strings.xml @@ -125,8 +125,7 @@ "Аудиоподсказки" "Кошелек" "Сканер QR-кодов" - - + "Разблокировано" "Устройство заблокировано" "Сканирование лица" "Отправить" @@ -169,8 +168,7 @@ "Лицо не распознано." "Используйте отпечаток." - - + "Фейсконтроль недоступен" "Bluetooth-соединение установлено." "Уровень заряда батареи в процентах неизвестен." "%s: подключено." @@ -181,13 +179,10 @@ "Режим полета." "Режим VPN включен." "Заряд батареи в процентах: %d." - - + "Заряд батареи: %1$d. Его хватит %2$s." "Зарядка батареи. Текущий заряд: %d %%." - - - - + "Зарядка приостановлена на уровне %d. Это поможет продлить срок службы батареи." + "Заряд батареи: %1$d. Его хватит %2$s. Зарядка приостановлена, чтобы продлить срок службы батареи." "Показать все уведомления" "Телетайп включен." "Вибровызов." @@ -501,8 +496,8 @@ "Разблокировать для использования" "Не удалось получить информацию о картах. Повторите попытку позже." "Настройки заблокированного экрана" - - + "Сканер QR-кодов" + "Обновление" "Рабочий профиль" "Режим полета" "Следующий будильник: %1$s. Звук отключен." @@ -996,4 +991,23 @@ "d MMM EEEE" "h:mm" "kk:mm" + "Открыть \"%1$s\"" + "Для добавления ярлыка приложения \"%1$s\" должны выполняться следующие условия:" + "• Приложение установлено." + "• В Кошельке есть хотя бы одна карта." + "• Установлено приложение камеры." + "• Приложение установлено." + "• Доступно хотя бы одно устройство." + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml index f9a6b0b45ecb8..2446ce8a1da98 100644 --- a/packages/SystemUI/res/values-si/strings.xml +++ b/packages/SystemUI/res/values-si/strings.xml @@ -125,8 +125,7 @@ "හඬ සහාය" "Wallet" "QR කේත ස්කෑනරය" - - + "අගුළු හරින ලදි" "උපාංගය අගුලු දමා ඇත" "මුහුණ ස්කෑන් කිරීම" "යවන්න" @@ -169,8 +168,7 @@ "මුහුණ හඳුනා ගත නොහැක" "ඒ වෙනුවට ඇඟිලි සලකුණ භාවිත කරන්න" - - + "මුහුණෙන් අගුළු ඇරීම නැත" "බ්ලූටූත් සම්බන්ධිතයි." "බැටරි ප්‍රතිශතය නොදනී." "%s වෙත සම්බන්ධ කරන ලදි." @@ -181,13 +179,10 @@ "අහස්යානා ආකාරය." "VPN ක්‍රියාත්මකයි." "බැටරි ප්‍රතිශතය %d" - - + "බැටරි ප්‍රතිශතය %1$d, %2$s" "බැටරිය ආරෝපණය කරමින්, %d%%." - - - - + "බැටරිය සියයට %d, බැටරි ආරක්ෂණය සඳහා ආරෝපණය විරාම ගන්වා ඇත." + "බැටරිය සියයට %1$d, %2$s, බැටරි ආරක්ෂණය සඳහා ආරෝපණය විරාම ගන්වා ඇත." "සියලු දැනුම්දීම් බලන්න" "TeleTypewriter ක්‍රියාත්මකයි." "හඬ නඟනය කම්පනය වේ." @@ -501,8 +496,8 @@ "භාවිත කිරීමට අගුලු හරින්න" "ඔබගේ කාඩ්පත ලබා ගැනීමේ ගැටලුවක් විය, කරුණාකර පසුව නැවත උත්සාහ කරන්න" "අගුලු තිර සැකසීම්" - - + "QR කේත ස්කෑනරය" + "යාවත්කාලීන කිරීම" "කාර්යාල පැතිකඩ" "ගුවන්යානා ප්‍රකාරය" "ඔබට ඔබේ ඊළඟ එලාමය %1$s නොඇසෙනු ඇත" @@ -996,4 +991,23 @@ "EEE, MMM d" "h:mm" "kk:mm" + "%1$s විවෘත කරන්න" + "කෙටිමඟක් ලෙස %1$s එක් කිරීමට, තහවුරු කර ගන්න" + "• යෙදුම සකසා ඇත" + "• Wallet වෙත අවම වශයෙන් එක කාඩ්පතක් එක් කර ඇත" + "• කැමරා යෙදුමක් ස්ථාපන කරන්න" + "• යෙදුම සකසා ඇත" + "• අවම වශයෙන් එක උපාංගයක් ලැබේ" + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml index 51f0c7da28e6f..39125800f064d 100644 --- a/packages/SystemUI/res/values-sk/strings.xml +++ b/packages/SystemUI/res/values-sk/strings.xml @@ -125,8 +125,7 @@ "Hlasový asistent" "Peňaženka" "Skener QR kódov" - - + "Odomknuté" "Zariadenie je uzamknuté" "Skenovanie tváre" "Odoslať" @@ -169,8 +168,7 @@ "Tvár sa nedá rozpoznať" "Používať radšej odtlačok" - - + "Odomknutie tvárou nie je k dispozícii" "Bluetooth pripojené." "Percento batérie nie je známe." "Pripojené k zariadeniu %s." @@ -181,13 +179,10 @@ "Režim v lietadle." "VPN je zapnuté." "Batéria %d percent." - - + "Batéria má %1$d percent, %2$s" "Nabíja sa batéria, %d %%." - - - - + "Batéria má %d percent, z dôvodu jej ochrany bolo nabíjanie pozastavené." + "Batéria má %1$d percent, %2$s, z dôvodu jej ochrany bolo nabíjanie pozastavené." "Zobraziť všetky upozornenia" "Rozhranie TeleTypewriter je povolené." "Vibračné zvonenie." @@ -501,8 +496,8 @@ "Odomknúť a použiť" "Pri načítavaní kariet sa vyskytol problém. Skúste to neskôr." "Nastavenia uzamknutej obrazovky" - - + "Skener QR kódov" + "Aktualizuje sa" "Pracovný profil" "Režim v lietadle" "Váš budík o %1$s sa nespustí" @@ -531,7 +526,7 @@ "Automaticky" "Žiadny zvuk ani vibrácie" "Žiadny zvuk ani vibrácie a zobrazuje sa nižšie v sekcii konverzácií" - "Zvoní či vibruje podľa nastavení telefónu" + "Môže zvoniť či vibrovať podľa nastavení telefónu" "Môže zvoniť alebo vibrovať podľa nastavení telefónu. Predvolene sa zobrazia konverzácie z bubliny %1$s." "Nechajte systém určiť, či má toto upozornenie vydávať zvuk alebo vibrovať" "<b>Stav:</b> Preradené vyššie do kategórie Predvolené" @@ -996,4 +991,23 @@ "EEE, d. MMM" "h:mm" "kk:mm" + "Otvoriť %1$s" + "Ak chcete aplikáciu %1$s pridať ako odkaz, uistite sa, že" + "• Aplikácia je nastavená" + "• Do Peňaženky bola pridaná minimálne jedna karta" + "• Nainštalujte si aplikáciu kamery" + "• Aplikácia je nastavená" + "• K dispozícii je minimálne jedno zariadenie" + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml index 9e2a4bb84e54c..c084215d4ca6a 100644 --- a/packages/SystemUI/res/values-sl/strings.xml +++ b/packages/SystemUI/res/values-sl/strings.xml @@ -125,8 +125,7 @@ "Glasovni pomočnik" "Google Denarnica" "Optični bralnik kod QR" - - + "Odklenjeno" "Naprava je zaklenjena." "Optično branje obraza" "Pošlji" @@ -169,8 +168,7 @@ "Obraz ni bil prepoznan." "Uporabite prstni odtis." - - + "Odklepanje z obrazom ni na voljo." "Povezava Bluetooth vzpostavljena." "Neznan odstotek napolnjenosti baterije." "Povezava vzpostavljena z: %s." @@ -181,13 +179,10 @@ "Način za letalo." "Omrežje VPN je vklopljeno." "Baterija %d odstotkov." - - + "Baterija je napolnjena na %1$d – %2$s." "Baterija se polni, %d odstotkov." - - - - + "Baterija je napolnjena na %d – zaradi zaščite baterije je polnjenje začasno zaustavljeno." + "Baterija je napolnjena na %1$d – %2$s je zaradi zaščite baterije polnjenje začasno zaustavljeno." "Prikaži vsa obvestila" "TeleTypewriter omogočen." "Zvonjenje z vibriranjem." @@ -501,8 +496,8 @@ "Odklenite za uporabo" "Pri pridobivanju kartic je prišlo do težave. Poskusite znova pozneje." "Nastavitve zaklepanja zaslona" - - + "Optični bralnik kod QR" + "Posodabljanje" "Profil za Android Work" "Način za letalo" "Naslednjega alarma ob %1$s ne boste slišali" @@ -996,4 +991,23 @@ "EEE, d. MMM" "h:mm" "kk:mm" + "Odpri aplikacijo %1$s" + "Če želite aplikacijo %1$s dodati kot bližnjico, zagotovite naslednje:" + "• Aplikacija mora biti nastavljena." + "• Vsaj ena kartica mora biti dodana v Denarnico." + "• Namestite fotografsko aplikacijo." + "• Aplikacija mora biti nastavljena." + "• Na voljo mora biti vsaj ena naprava." + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml index 25475633c2f20..768037c281d36 100644 --- a/packages/SystemUI/res/values-sq/strings.xml +++ b/packages/SystemUI/res/values-sq/strings.xml @@ -125,8 +125,7 @@ "Ndihma zanore" "Portofoli" "Skaneri i kodeve QR" - - + "Shkyçur" "Pajisja është e kyçur" "Po skanon fytyrën" "Dërgo" @@ -169,8 +168,7 @@ "Fytyra nuk mund të njihet" "Përdor më mirë gjurmën e gishtit" - - + "\"Shkyçja me fytyrë\" nuk ofrohet" "Pajisja është lidhur me \"bluetooth\"." "Përqindja e baterisë e panjohur." "Lidhur me %s" @@ -181,13 +179,10 @@ "modaliteti i aeroplanit" "VPN-ja është aktive." "Bateria ka edhe %d për qind." - - + "Bateria ka edhe %1$d për qind, %2$s" "Bateria po karikohet, %d%%." - - - - + "Bateria në %d për qind. Karikimi u vendos në pauzë për të mbrojtur baterinë." + "Bateria në %1$d për qind. %2$s. Karikimi u vendos në pauzë për të mbrojtur baterinë." "Shiko të gjitha njoftimet" "Teletajpi është i aktivizuar." "Zile me dridhje." @@ -501,8 +496,8 @@ "Shkyçe për ta përdorur" "Pati një problem me marrjen e kartave të tua. Provo përsëri më vonë" "Cilësimet e ekranit të kyçjes" - - + "Skaneri i kodeve QR" + "Po përditësohet" "Profili i punës" "Modaliteti i aeroplanit" "Nuk do ta dëgjosh alarmin e radhës në %1$s" @@ -996,4 +991,23 @@ "EEE, MMM d" "h:mm" "kk:mm" + "Hap \"%1$s\"" + "Për të shtuar aplikacionin \"%1$s\" si një shkurtore, sigurohu që" + "• Aplikacioni është konfiguruar" + "• Të paktën një kartë të jetë shtuar në \"Portofol\"" + "• Të instalosh një aplikacion të kamerës" + "• Aplikacioni është konfiguruar" + "• Ofrohet të paktën një pajisje" + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml index fb17123fc3b60..34e3a940be72a 100644 --- a/packages/SystemUI/res/values-sr/strings.xml +++ b/packages/SystemUI/res/values-sr/strings.xml @@ -125,8 +125,7 @@ "Гласовна помоћ" "Новчаник" "Скенер QR кода" - - + "Откључано" "Уређај је закључан" "Скенирање лица" "Пошаљи" @@ -169,8 +168,7 @@ "Лице није препознато" "Користите отисак прста" - - + "Откључавање лицем није доступно" "Bluetooth је прикључен." "Проценат напуњености батерије није познат." "Повезани сте са %s." @@ -181,13 +179,10 @@ "Режим рада у авиону." "VPN је укључен." "Батерија је на %d посто." - - + "Батерија је на %1$d посто, %2$s" "Батерија се пуни, %d посто." - - - - + "Батерија је на %d посто, пуњење је паузирано да би се заштитила батерија." + "Батерија је на %1$d посто, %2$s, пуњење је паузирано да би се заштитила батерија." "Погледајте сва обавештења" "TeleTypewriter је омогућен." "Вибрација звона." @@ -501,8 +496,8 @@ "Откључај ради коришћења" "Дошло је до проблема при преузимању картица. Пробајте поново касније" "Подешавања закључаног екрана" - - + "Скенер QR кода" + "Ажурира се" "Пословни профил" "Режим рада у авиону" "Нећете чути следећи аларм у %1$s" @@ -996,4 +991,23 @@ "ДДД, д. МММ" "с:мин" "ч:мин" + "Отворите: %1$s" + "Да бисте додали апликацију %1$s као пречицу, уверите се:" + "• да је апликација подешена" + "• да је у Новчаник додата барем једна картица" + "• да сте инсталирали апликацију за камеру" + "• да је апликација подешена" + "• да је доступан барем један уређај" + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml index 6e74ea2bfeaea..322ea0a682e85 100644 --- a/packages/SystemUI/res/values-sv/strings.xml +++ b/packages/SystemUI/res/values-sv/strings.xml @@ -125,8 +125,7 @@ "Röstassistent" "Wallet" "QR-skanner" - - + "Upplåst" "Enheten är låst" "Registrerar ansikte" "Skicka" @@ -169,8 +168,7 @@ "Ansiktet kändes inte igen" "Använd fingeravtryck" - - + "Ansiktslås är otillgängligt" "Bluetooth ansluten." "Okänd batterinivå." "Ansluten till %s." @@ -181,13 +179,10 @@ "Flygplansläge" "VPN har aktiverats." "Batteri %d procent." - - + "Batterinivån är %1$d procent, %2$s." "Batteriet laddas, %d procent." - - - - + "Batterinivån är %d procent. Laddningen har pausats för att skydda batteriet." + "Batterinivån är %1$d procent, %2$s. Laddningen har pausats för att skydda batteriet." "Visa alla aviseringar" "TeleTypewriter aktiverad." "Vibrerande ringsignal." @@ -501,8 +496,8 @@ "Lås upp för att använda" "Det gick inte att hämta dina kort. Försök igen senare." "Inställningar för låsskärm" - - + "QR-skanner" + "Uppdaterar" "Jobbprofil" "Flygplansläge" "Nästa alarm, kl. %1$s, kommer inte att höras" @@ -996,4 +991,23 @@ "EEE, d MMM" "h.mm" "kk.mm" + "Öppna %1$s" + "Om du vill lägga till %1$s-appen som en genväg ser du till att" + "• appen har konfigurerats" + "• minst ett kort har lagts till i Wallet" + "• installera en kameraapp" + "• appen har konfigurerats" + "• minst en enhet är tillgänglig" + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml index e8a7caff02a3a..5e822a0e2b1ce 100644 --- a/packages/SystemUI/res/values-sw/strings.xml +++ b/packages/SystemUI/res/values-sw/strings.xml @@ -125,8 +125,7 @@ "Mapendekezo ya Sauti" "Pochi" "Kichanganuzi cha Msimbo wa QR" - - + "Imefunguliwa" "Kifaa kimefungwa" "Inachanganua uso" "Tuma" @@ -169,8 +168,7 @@ "Imeshindwa kutambua uso" "Badala yake, tumia alama ya kidole" - - + "Kipengele cha Kufungua kwa Uso hakipatikani" "Bluetooth imeunganishwa." "Asilimia ya betri haijulikani." "Imeunganishwa kwenye %s." @@ -181,13 +179,10 @@ "Hali ya ndegeni." "VPN imewashwa." "Asilimia %d ya betri" - - + "Betri ina asilimia %1$d, hadi %2$s" "Betri inachaji, asilimia %d." - - - - + "Betri ina asilimia %d, imesitisha kuchaji ili kulinda betri." + "Betri ina asilimia %1$d, hadi %2$s, imesitisha kuchaji ili kulinda betri." "Angalia arifa zote" "Kichapishaji cha Tele kimewezeshwa." "Mtetemo wa mlio" @@ -501,7 +496,8 @@ "Fungua ili utumie" "Hitilafu imetokea wakati wa kuleta kadi zako, tafadhali jaribu tena baadaye" "Mipangilio ya kufunga skrini" - + "Kichanganuzi cha msimbo wa QR" + "Wasifu wa kazini" "Hali ya ndegeni" @@ -996,4 +992,30 @@ "EEE, d MMM" "saa:dk" "kk:dk" + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml index 41e1f3f96f70c..9f54b7ef36ef7 100644 --- a/packages/SystemUI/res/values-ta/strings.xml +++ b/packages/SystemUI/res/values-ta/strings.xml @@ -125,8 +125,7 @@ "குரல் உதவி" "Wallet" "QR குறியீடு ஸ்கேனர்" - - + "அன்லாக் செய்யப்பட்டுள்ளது" "சாதனம் பூட்டப்பட்டுள்ளது" "முகத்தை ஸ்கேன் செய்கிறது" "அனுப்பு" @@ -169,8 +168,7 @@ "முகத்தை கண்டறிய இயலவில்லை" "கைரேகையை உபயோகிக்கவும்" - - + "முகம் காட்டித் திறத்தல் அம்சம் கிடைக்கவில்லை" "புளூடூத் இணைக்கப்பட்டது." "பேட்டரி சதவீதம் தெரியவில்லை." "%sக்கு இணைக்கப்பட்டது." @@ -181,13 +179,10 @@ "விமானப் பயன்முறை." "VPN இயக்கத்தில் உள்ளது." "பேட்டரி சக்தி %d சதவிகிதம் உள்ளது." - - + "பேட்டரி %1$d உள்ளது (%2$s வரை இயங்கும்)" "பேட்டரி சார்ஜ் ஆகிறது, %d சதவீதம் உள்ளது." - - - - + "பேட்டரி %d உள்ளது, பேட்டரி பாதுகாப்பிற்காகச் சார்ஜிங் இடைநிறுத்தப்பட்டுள்ளது." + "பேட்டரி %1$d உள்ளது (%2$s வரை இயங்கும்), பேட்டரி பாதுகாப்பிற்காகச் சார்ஜிங் இடைநிறுத்தப்பட்டுள்ளது." "எல்லா அறிவிப்புகளையும் காட்டும்" "TeleTypewriter இயக்கப்பட்டது." "ரிங்கர் அதிர்வு." @@ -501,7 +496,8 @@ "பயன்படுத்துவதற்கு அன்லாக் செய்க" "உங்கள் கார்டுகளின் விவரங்களைப் பெறுவதில் சிக்கல் ஏற்பட்டது, பிறகு முயலவும்" "பூட்டுத் திரை அமைப்புகள்" - + "QR குறியீடு ஸ்கேனர்" + "பணிக் கணக்கு" "விமானப் பயன்முறை" @@ -996,4 +992,30 @@ "EEE, MMM d" "h:mm" "kk:mm" + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml index 9ad0277c6c558..fa438331c8d3b 100644 --- a/packages/SystemUI/res/values-te/strings.xml +++ b/packages/SystemUI/res/values-te/strings.xml @@ -125,8 +125,7 @@ "వాయిస్ అసిస్టెంట్" "Wallet" "QR కోడ్ స్కానర్" - - + "అన్‌లాక్ చేయబడింది" "పరికరం లాక్ చేయబడింది" "ముఖాన్ని స్కాన్ చేస్తోంది" "పంపు" @@ -169,8 +168,7 @@ "ముఖం గుర్తించడం కుదరలేదు" "బదులుగా వేలిముద్రను ఉపయోగించండి" - - + "ఫేస్ అన్‌లాక్ అందుబాటులో లేదు" "బ్లూటూత్ కనెక్ట్ చేయబడింది." "బ్యాటరీ శాతం తెలియదు." "%sకి కనెక్ట్ చేయబడింది." @@ -181,13 +179,10 @@ "ఎయిర్‌ప్లేన్ మోడ్." "VPNలో." "బ్యాటరీ %d శాతం." - - + "బ్యాటరీ %1$d శాతం, %2$s ఉంటుంది" "బ్యాటరీ ఛార్జ్ అవుతోంది, %d శాతం వద్ద ఉంది." - - - - + "బ్యాటరీ %d శాతం ఉంది, బ్యాటరీ ప్రొటెక్షన్ కోసం ఛార్జింగ్ పాజ్ చేయబడింది." + "బ్యాటరీ %1$d శాతం, %2$s ఉంటుంది, బ్యాటరీ ప్రొటెక్షన్ కోసం ఛార్జింగ్ పాజ్ చేయబడింది." "అన్ని నోటిఫికేషన్‌లను చూడండి" "టెలిటైప్‌రైటర్ ప్రారంభించబడింది." "రింగర్ వైబ్రేట్‌లో ఉంది." @@ -501,8 +496,8 @@ "ఉపయోగించడానికి అన్‌లాక్ చేయండి" "మీ కార్డ్‌లను పొందడంలో సమస్య ఉంది, దయచేసి తర్వాత మళ్లీ ట్రై చేయండి" "లాక్ స్క్రీన్ సెట్టింగ్‌లు" - - + "QR కోడ్ స్కానర్" + "అప్‌డేట్ చేస్తోంది" "ఆఫీస్ ప్రొఫైల్‌" "ఎయిర్‌ప్లేన్ మోడ్" "మీరు %1$s సెట్ చేసిన మీ తర్వాత అలారం మీకు వినిపించదు" @@ -996,4 +991,17 @@ "EEE, MMM d" "h:mm" "kk:mm" + "%1$s‌ను తెరవండి" + "%1$s యాప్‌ను షార్ట్‌కట్‌గా జోడించడానికి, వీటిని నిర్ధారించుకోండి" + "• యాప్ సెటప్ చేయబడి ఉందని" + "• Walletకు కనీసం ఒక కార్డ్ అయినా జోడించబడి ఉందని" + "• కెమెరా యాప్ ఇన్‌స్టాల్ చేసి ఉందని" + "• యాప్ సెటప్ చేయబడి ఉందని" + "• కనీసం ఒక పరికరమైనా అందుబాటులో ఉందని" + "రద్దు చేయండి" + "ఇప్పుడే తిప్పండి" + "మెరుగైన సెల్ఫీ కోసం ఫోన్‌ను అన్‌ఫోల్డ్ చేయండి" + "మంచి సెల్ఫీ కోసం ముందు వైపు డిస్‌ప్లేకు తిప్పాలా?" + "అధిక రిజల్యూషన్‌తో పెద్ద ఫోటో కోసం వెనుక వైపున ఉన్న కెమెరాను ఉపయోగించండి." + "✱ ఈ స్క్రీన్ ఆఫ్ అవుతుంది" diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml index f4116ad443195..17575100d330b 100644 --- a/packages/SystemUI/res/values-th/strings.xml +++ b/packages/SystemUI/res/values-th/strings.xml @@ -168,8 +168,7 @@ "ไม่รู้จักใบหน้า" "ใช้ลายนิ้วมือแทน" - - + "การปลดล็อกด้วยใบหน้าไม่พร้อมใช้งาน" "เชื่อมต่อบลูทูธแล้ว" "ไม่ทราบเปอร์เซ็นต์แบตเตอรี่" "เชื่อมต่อกับ %s แล้ว" @@ -180,13 +179,10 @@ "โหมดบนเครื่องบิน" "VPN เปิดอยู่" "แบตเตอรี่ %d เปอร์เซ็นต์" - - + "แบตเตอรี่ %1$d เปอร์เซ็นต์ (%2$s)" "กำลังชาร์จแบตเตอรี่ %d เปอร์เซ็นต์" - - - - + "แบตเตอรี่ %d เปอร์เซ็นต์ หยุดชาร์จชั่วคราวเพื่อยืดอายุแบตเตอรี่" + "แบตเตอรี่ %1$d เปอร์เซ็นต์ (%2$s) หยุดชาร์จชั่วคราวเพื่อยืดอายุแบตเตอรี่" "ดูการแจ้งเตือนทั้งหมด" "เปิดใช้งาน TeleTypewriter อยู่" "เสียงเรียกเข้าแบบสั่น" @@ -501,6 +497,7 @@ "เกิดปัญหาในการดึงข้อมูลบัตรของคุณ โปรดลองอีกครั้งในภายหลัง" "การตั้งค่าหน้าจอล็อก" "เครื่องมือสแกนคิวอาร์โค้ด" + "กำลังอัปเดต" "โปรไฟล์งาน" "โหมดบนเครื่องบิน" "คุณจะไม่ได้ยินเสียงปลุกครั้งถัดไปในเวลา %1$s" @@ -994,4 +991,17 @@ "EEE d MMM" "HH:mm" "kk:mm" + "เปิด %1$s" + "หากต้องการเพิ่มแอป %1$s เป็นทางลัด โปรดตรวจสอบดังต่อไปนี้" + "• แอปได้รับการตั้งค่าแล้ว" + "• มีการเพิ่มบัตรลงใน Wallet อย่างน้อย 1 รายการ" + "• ติดตั้งแอปกล้อง" + "• แอปได้รับการตั้งค่าแล้ว" + "• มีอุปกรณ์พร้อมใช้งานอย่างน้อย 1 รายการ" + "ยกเลิก" + "พลิกเลย" + "กางโทรศัพท์เพื่อเซลฟีที่ดียิ่งขึ้น" + "พลิกเป็นหน้าจอด้านหน้าเพื่อภาพเซลฟีที่ดีขึ้นไหม" + "ใช้กล้องหลังเพื่อถ่ายภาพกว้างขึ้นด้วยความละเอียดสูงขึ้น" + "✱ หน้าจอนี้จะปิดไป" diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml index 468c8a400de75..43768c6d0a878 100644 --- a/packages/SystemUI/res/values-tl/strings.xml +++ b/packages/SystemUI/res/values-tl/strings.xml @@ -125,8 +125,7 @@ "Voice Assist" "Wallet" "Scanner ng QR Code" - - + "Naka-unlock" "Naka-lock ang device" "Sina-scan ang mukha" "Ipadala" @@ -169,8 +168,7 @@ "Hindi makilala ang mukha" "Gumamit ng fingerprint" - - + "Hindi available ang Pag-unlock Gamit ang Mukha" "Nakakonekta ang Bluetooth." "Hindi alam ang porsyento ng baterya." "Nakakonekta sa %s." @@ -181,13 +179,10 @@ "Mode na eroplano." "Naka-on ang VPN." "Baterya %d (na) porsyento." - - + "Nasa %1$d (na) porsyento ang baterya, %2$s." "Nagcha-charge ang baterya, %d (na) porsyento." - - - - + "Nasa %d (na) porsyento ang baterya, na-pause ang pag-charge para protektahan ang baterya." + "Nasa %1$d (na) porsyento ang baterya, %2$s, na-pause ang pag-charge para protektahan ang baterya." "Tingnan ang lahat ng notification" "Pinapagana ang TeleTypewriter." "Pag-vibrate ng ringer." @@ -502,6 +497,7 @@ "Nagkaproblema sa pagkuha ng iyong mga card, pakisubukan ulit sa ibang pagkakataon" "Mga setting ng lock screen" "Scanner ng QR code" + "Ina-update" "Profile sa trabaho" "Airplane mode" "Hindi mo maririnig ang iyong susunod na alarm ng %1$s" @@ -995,4 +991,23 @@ "EEE, MMM d" "h:mm" "kk:mm" + "Buksan ang %1$s" + "Para idagdag ang %1$s app bilang shortcut, siguraduhing" + "• Na-set up ang app" + "• May kahit isang card na idinagdag sa Wallet" + "• Mag-install ng camera app" + "• Na-set up ang app" + "• May kahit isang device na available" + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml index 7c126e5f1125e..a140cf5fe09c4 100644 --- a/packages/SystemUI/res/values-tr/strings.xml +++ b/packages/SystemUI/res/values-tr/strings.xml @@ -125,8 +125,7 @@ "Sesli Yardım" "Cüzdan" "QR kodu tarayıcı" - - + "Kilitli değil" "Cihaz kilitlendi" "Yüz taranıyor" "Gönder" @@ -169,8 +168,7 @@ "Yüz tanınamadı" "Bunun yerine parmak izi kullanın" - - + "Yüz Tanıma Kilidi kullanılamıyor" "Bluetooth bağlandı." "Pil yüzdesi bilinmiyor." "%s ile bağlı." @@ -181,13 +179,10 @@ "Uçak modu." "VPN açık." "Pil yüzdesi: %d" - - + "Pil yüzde %1$d, %2$s" "Pil şarj oluyor, yüzde %d." - - - - + "Pil yüzde %d dolu. Şarj işlemi, pili korumak için duraklatıldı." + "Pil yüzde %1$d dolu. Pilin %2$s bitmemesi bekleniyor. Şarj işlemi, pili korumak için duraklatıldı." "Tüm bildirimleri göster" "TeleTypewriter etkin." "Telefon zili titreşim." @@ -501,8 +496,8 @@ "Kullanmak için kilidi aç" "Kartlarınız alınırken bir sorun oluştu. Lütfen daha sonra tekrar deneyin" "Kilit ekranı ayarları" - - + "QR kodu tarayıcı" + "Güncelleniyor" "İş profili" "Uçak modu" "%1$s olarak ayarlanmış bir sonraki alarmınızı duymayacaksınız" @@ -996,4 +991,23 @@ "d MMM, EEE" "h:mm" "kk:dd" + "%1$s uygulamasını aç" + "%1$s uygulamasını kısayol olarak ekleyebilmeniz için gerekenler" + "• Uygulama kurulmuş olmalıdır" + "• Cüzdan\'a en az bir kart eklenmelidir" + "• Kamera uygulaması yüklenmelidir" + "• Uygulama kurulmuş olmalıdır" + "• En az bir cihaz mevcut olmalıdır" + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml index 1c32bb1d7711b..2c3f9fcc67cd7 100644 --- a/packages/SystemUI/res/values-uk/strings.xml +++ b/packages/SystemUI/res/values-uk/strings.xml @@ -125,8 +125,7 @@ "Голосові підказки" "Гаманець" "Сканер QR-коду" - - + "Розблоковано" "Пристрій заблоковано" "Сканування обличчя" "Надіслати" @@ -169,8 +168,7 @@ "Обличчя не розпізнано" "Скористайтеся відбитком" - - + "Фейсконтроль недоступний" "Bluetooth під’єднано." "Відсоток заряду акумулятора невідомий." "Підключено до %s." @@ -181,13 +179,10 @@ "Режим польоту." "Мережу VPN увімкнено." "Заряд акумулятора у відсотках: %d." - - + "Заряд акумулятора: %1$d, вистачить %2$s" "Акумулятор заряджається, поточний заряд %d відсотків." - - - - + "Заряд акумулятора: %d%%. Для захисту акумулятора заряджання призупинено." + "Заряд акумулятора: %1$d%%, вистачить %2$s. Для захисту акумулятора заряджання призупинено." "Переглянути всі сповіщення" "Телетайп увімкнено." "Дзвінок на вібросигналі." @@ -501,7 +496,8 @@ "Розблокувати, щоб використовувати" "Не вдалось отримати ваші картки. Повторіть спробу пізніше." "Параметри блокування екрана" - + "Сканер QR-коду" + "Робочий профіль" "Режим польоту" @@ -996,4 +992,30 @@ "EEE, d MMM" "h:mm" "kk:mm" + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml index b78c50ec03e0b..18de240d761f2 100644 --- a/packages/SystemUI/res/values-ur/strings.xml +++ b/packages/SystemUI/res/values-ur/strings.xml @@ -125,8 +125,7 @@ "صوتی معاون" "والٹ" "‏QR کوڈ اسکینر" - - + "غیر مقفل ہے" "آلہ مقفل کر دیا گیا" "اسکیننگ چہرہ" "بھیجیں" @@ -169,8 +168,7 @@ "چہرے کی پہچان نہیں ہو سکی" "اس کے بجائے فنگر پرنٹ استعمال کریں" - - + "فیس اَنلاک غیر دستیاب ہے" "بلوٹوتھ مربوط ہے۔" "بیٹری کی فیصد نامعلوم ہے۔" "%s سے منسلک ہیں۔" @@ -181,13 +179,10 @@ "ہوائی جہاز وضع۔" "‏VPN آن ہے۔" "بیٹری %d فیصد۔" - - + "بیٹری %1$d فیصد ہے، %2$s تک چلے گی" "بیٹری چارج ہو رہی ہے، اس وقت %d فیصد ہے۔" - - - - + "بیٹری %d فیصد پے، بیٹری کے تحفظ کے لیے چارجنگ موقوف ہو گئی ہے۔" + "بیٹری %1$d فیصد پے، %2$s تک چلے گی، بیٹری کے تحفظ کے لیے چارجنگ موقوف ہو گئی ہے۔" "تمام اطلاعات دیکھیں" "ٹیلی ٹائپ رائٹر فعال ہے۔" "رنگر وائبریٹ۔" @@ -501,8 +496,8 @@ "استعمال کرنے کے لیے غیر مقفل کریں" "آپ کے کارڈز حاصل کرنے میں ایک مسئلہ درپیش تھا، براہ کرم بعد میں دوبارہ کوشش کریں" "مقفل اسکرین کی ترتیبات" - - + "‏QR کوڈ اسکینر" + "اپ ڈیٹ ہو رہا ہے" "دفتری پروفائل" "ہوائی جہاز وضع" "آپ کو %1$s بجے اپنا اگلا الارم سنائی نہیں دے گا" @@ -996,4 +991,23 @@ "EEE, MMM d" "h:mm" "kk:mm" + "%1$s کھولیں" + "%1$s ایپ کو شارٹ کٹ کے طور پر شامل کرنے کے لیے درج ذیل کو یقینی بنائیں" + "• ایپ سیٹ اپ ہو گئی ہے" + "• والٹ میں کم از کم ایک کارڈ شامل کیا گیا ہے" + "• کیمرا ایپ انسٹال کریں" + "• ایپ سیٹ اپ ہو گئی ہے" + "• کم از کم ایک آلہ دستیاب ہے" + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml index 3b34ac5545dd8..55f10c28294ed 100644 --- a/packages/SystemUI/res/values-uz/strings.xml +++ b/packages/SystemUI/res/values-uz/strings.xml @@ -125,8 +125,7 @@ "Ovozli yordam" "Wallet" "QR kod skaneri" - - + "Qulfi ochilgan" "Qurilma qulflandi" "Yuzni skanerlash" "Yuborish" @@ -169,8 +168,7 @@ "Yuz aniqlanmadi" "Barmoq izi orqali urining" - - + "Yuz bilan ochilmaydi." "Bluetooth ulandi." "Batareya quvvati foizi nomaʼlum." "Ulangan: %s." @@ -181,13 +179,10 @@ "Parvoz rejimi" "VPN yoniq." "Batareya %d foiz." - - + "Batareya %1$d foiz, %2$s yetadi." "Batareya quvvat olmoqda, %d foiz." - - - - + "Batareya %d foiz, batareya himoyasi uchun quvvatlash toʻxtatildi." + "Batareya %1$d foiz, %2$s yetadi, batareya himoyasi uchun quvvatlash toʻxtatildi." "Barcha bildirishnomalarni ko‘rish" "TeleTypewriter yoqildi." "Vibratsiyali qo‘ng‘iroq" @@ -502,6 +497,7 @@ "Bildirgilarni yuklashda xatolik yuz berdi, keyinroq qaytadan urining" "Qulflangan ekran sozlamalari" "QR kod skaneri" + "Yangilanmoqda" "Ish profili" "Parvoz rejimi" "Keyingi signal (%1$s) chalinmaydi" @@ -995,4 +991,23 @@ "EEE, MMM d" "s:dd" "kk:mm" + "Ochish: %1$s" + "%1$s ilovasini yorliq sifatida qoʻshish uchun" + "• Ilova sozlangan" + "• Kamida bitta kartochka Wallet xizmatiga qoʻshilgan" + "• Kamera ilovasini oʻrnating" + "• Ilova sozlangan" + "• Kamida bitta qurilma mavjud" + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml index ea86c1ee60445..a4d82accdcaca 100644 --- a/packages/SystemUI/res/values-vi/strings.xml +++ b/packages/SystemUI/res/values-vi/strings.xml @@ -125,8 +125,7 @@ "Trợ lý thoại" "Ví" "Trình quét mã QR" - - + "Đã mở khoá" "Đã khóa thiết bị" "Quét tìm khuôn mặt" "Gửi" @@ -169,8 +168,7 @@ "Không nhận ra khuôn mặt" "Hãy dùng vân tay" - - + "Không dùng được tính năng Mở khoá bằng khuôn mặt" "Đã kết nối bluetooth." "Tỷ lệ phần trăm pin không xác định." "Đã kết nối với %s." @@ -181,13 +179,10 @@ "Chế độ trên máy bay." "VPN đang bật." "%d phần trăm pin." - - + "%1$d phần trăm pin, %2$s" "Đang sạc pin, %d%%." - - - - + "%d phần trăm pin, đã tạm dừng sạc để bảo vệ pin." + "%1$d phần trăm pin, %2$s, đã tạm dừng sạc để bảo vệ pin." "Xem tất cả thông báo" "Đã bật TeleTypewriter." "Chuông rung." @@ -501,8 +496,8 @@ "Mở khóa để sử dụng" "Đã xảy ra sự cố khi tải thẻ của bạn. Vui lòng thử lại sau" "Cài đặt màn hình khóa" - - + "Trình quét mã QR" + "Đang cập nhật" "Hồ sơ công việc" "Chế độ máy bay" "Bạn sẽ không nghe thấy báo thức tiếp theo lúc %1$s của mình" @@ -996,4 +991,23 @@ "EEE, MMM d" "h:mm" "kk:mm" + "Mở %1$s" + "Để tạo lối tắt cho ứng dụng %1$s, hãy đảm bảo" + "• Ứng dụng được thiết lập" + "• Thêm ít nhất một thẻ vào Wallet" + "• Cài đặt một ứng dụng máy ảnh" + "• Ứng dụng được thiết lập" + "• Có ít nhất một thiết bị đang hoạt động" + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml index ffe4f5f68f177..76c7b9a193fe0 100644 --- a/packages/SystemUI/res/values-zh-rCN/strings.xml +++ b/packages/SystemUI/res/values-zh-rCN/strings.xml @@ -125,8 +125,7 @@ "语音助理" "钱包" "二维码扫描器" - - + "已解锁" "设备已锁定" "正在扫描面孔" "发送" @@ -169,8 +168,7 @@ "人脸识别失败" "改用指纹" - - + "无法使用人脸解锁功能" "蓝牙已连接。" "电池电量百分比未知。" "已连接到%s。" @@ -181,13 +179,10 @@ "飞行模式。" "VPN 已开启。" "电池电量为百分之 %d。" - - - "正在充电,已完成 %d%%。" - - - - + "电池电量为百分之 %1$d,估计还可用 %2$s" + "正在充电,已完成百分之 %d。" + "电池电量为百分之 %d。为保护电池,系统已暂停充电。" + "电池电量为百分之 %1$d,估计还可用 %2$s。为保护电池,系统已暂停充电。" "查看所有通知" "电传打字机已启用。" "振铃器振动。" @@ -501,8 +496,8 @@ "解锁设备即可使用" "获取您的卡片时出现问题,请稍后重试" "锁屏设置" - - + "二维码扫描器" + "正在更新" "工作资料" "飞行模式" "您在%1$s将不会听到下次闹钟响铃" @@ -996,4 +991,23 @@ "EEE, MMM d" "h:mm" "kk:mm" + "打开%1$s" + "若要将%1$s应用添加为快捷方式,请确保:" + "• 应用已设置完毕" + "• 至少已将一张银行卡添加到钱包" + "• 安装相机应用" + "• 应用已设置完毕" + "• 至少有一台设备可用" + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml index 9a5cbd2751768..a1e2194d34f9e 100644 --- a/packages/SystemUI/res/values-zh-rHK/strings.xml +++ b/packages/SystemUI/res/values-zh-rHK/strings.xml @@ -125,8 +125,7 @@ "語音助手" "錢包" "QR 碼掃瞄器" - - + "已解鎖" "裝置已上鎖" "掃瞄緊面孔" "傳送" @@ -169,8 +168,7 @@ "無法辨識面孔" "請改用指紋" - - + "無法使用面孔解鎖" "藍牙連線已建立。" "電量百分比不明。" "已連線至%s。" @@ -181,13 +179,10 @@ "飛航模式。" "開咗 VPN。" "電池電量為百分之 %d。" - - + "目前電池電量為 %1$d,剩餘使用時間為 %2$s" "正在充電:%d%%。" - - - - + "目前電池電量為 %d。為保護電池,系統已暫停充電。" + "目前電池電量為 %1$d,剩餘使用時間為 %2$s。為保護電池,系統已暫停充電。" "睇所有通知" "TeleTypewriter (TTY) 已啟用。" "鈴聲震動。" @@ -501,8 +496,8 @@ "解鎖即可使用" "擷取資訊卡時發生問題,請稍後再試。" "上鎖畫面設定" - - + "QR 碼掃瞄器" + "正在更新" "工作設定檔" "飛行模式" "您不會%1$s聽到鬧鐘" @@ -996,4 +991,17 @@ "MMM d EEE" "h:mm" "kk:mm" + "開啟「%1$s」" + "如要新增「%1$s」應用程式為快速鍵,請確保:" + "• 應用程式已完成設定" + "• 已新增至少一張卡至「錢包」" + "• 安裝相機應用程式" + "• 應用程式已完成設定" + "• 至少一部裝置可用" + "取消" + "立即翻轉" + "打開手機,即可拍攝更出色的自拍" + "要翻轉至前方螢幕拍攝更出色的自拍嗎?" + "使用後置鏡頭,拍攝更廣角、解像度更高的相片。" + "✱ 此螢幕將關閉" diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml index 9a31504399c50..6de9cba002c52 100644 --- a/packages/SystemUI/res/values-zh-rTW/strings.xml +++ b/packages/SystemUI/res/values-zh-rTW/strings.xml @@ -125,8 +125,7 @@ "語音小幫手" "錢包" "QR code 掃描器" - - + "已解鎖" "裝置已鎖定" "掃描臉孔" "傳送" @@ -169,8 +168,7 @@ "無法辨識臉孔" "請改用指紋" - - + "無法使用人臉解鎖功能" "藍牙連線已建立。" "電池電量不明。" "已連線至%s。" @@ -181,13 +179,10 @@ "飛行模式。" "VPN 已開啟。" "電池電量為百分之 %d。" - - + "目前電池電量為 %1$d,預估續航時間為 %2$s" "充電中,已完成 %d%%。" - - - - + "目前電池電量為 %d,系統為保護電池已暫停充電。" + "目前電池電量為 %1$d,預估續航時間為 %2$s,系統為保護電池已暫停充電。" "查看所有通知" "TeleTypewriter (TTY) 已啟用。" "鈴聲震動。" @@ -501,8 +496,8 @@ "解鎖即可使用" "擷取卡片時發生問題,請稍後再試" "螢幕鎖定設定" - - + "QR code 掃描器" + "更新中" "工作資料夾" "飛航模式" "你不會聽到下一個%1$s 的鬧鐘" @@ -996,4 +991,23 @@ "MMM d EEE" "h:mm" "kk:mm" + "開啟「%1$s」" + "如要將「%1$s」應用程式新增為捷徑,必須滿足以下條件" + "• 完成應用程式設定" + "• 錢包中至少要有一張卡片" + "• 安裝相機應用程式" + "• 完成應用程式設定" + "• 至少要有一部可用裝置" + + + + + + + + + + + + diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml index 36f94ae21d566..9b7a173878765 100644 --- a/packages/SystemUI/res/values-zu/strings.xml +++ b/packages/SystemUI/res/values-zu/strings.xml @@ -125,8 +125,7 @@ "Isisekeli sezwi" "I-wallet" "Iskena sekhodi ye-QR" - - + "Ivuliwe" "Idivayisi ikhiyiwe" "Ukuskena ubuso" "Thumela" @@ -169,8 +168,7 @@ "Ayikwazi ukubona ubuso" "Kunalokho sebenzisa isigxivizo somunwe" - - + "Ukuvula ngobuso akutholakali" "Bluetooth ixhunyiwe" "Iphesenti lebhethri alaziwa." "Xhuma ku-%s." @@ -181,13 +179,10 @@ "Imodi yendiza." "I-VPN ivuliwe." "Iphesenti %d lebhethri" - - + "Iphesenti elingu-%1$d lebhethri, %2$s" "Ibhethri liyashaja, %d %%" - - - - + "Iphesenti elingu-%d, ukushaja kumiswe okwesikhashana ukuvikela ibhethri." + "Iphesenti elingu-%1$d, %2$s, ukushaja kumiswe okwesikhashana ukuvikela ibhethri." "Bona zonke izaziso" "i-TeleTypewriter inikwe amandla" "Ukudlidliza kweringa." @@ -501,8 +496,8 @@ "Vula ukuze usebenzise" "Kube khona inkinga yokuthola amakhadi akho, sicela uzame futhi ngemuva kwesikhathi" "Amasethingi okukhiya isikrini" - - + "Iskena sekhodi ye-QR" + "Iyabuyekeza" "Iphrofayela yomsebenzi" "Imodi yendiza" "Ngeke uzwe i-alamu yakho elandelayo ngo-%1$s" @@ -996,4 +991,23 @@ "EEE, MMM d" "h:mm" "kk:mm" + "Vula i-%1$s" + "Ukwengeza i-app ye-%1$s njengesinqamuleli, qinisekisa" + "• I-app isethiwe" + "• Okungenani ikhadi elilodwa lengeziwe ku-Wallet" + "• Faka i-app yekhamera" + "• I-app isethiwe" + "• Okungenani idivayisi eyodwa iyatholakala" + + + + + + + + + + + + From 091126fc7aa7c2936ccdd9c9c15549a73ee84884 Mon Sep 17 00:00:00 2001 From: Ats Jenk Date: Thu, 1 Dec 2022 10:03:34 -0800 Subject: [PATCH 29/38] Only collapse stack on shade state change Fixes an issue with bubble not being expanded when notification was set to be expanded from lock screen. Setting a notification to bubble from the notification action will add it as a new entry in BubbleData. And that bubble will be set to auto-expand. When a device is locked, BubbleController receives a status bar state change with isShade=false. When a device is unlocked, BubbleController can receive duplicate status bar state changes with isShade=false and will finally receive an update with isShade=true. The isShade=true indicates device is unlocked. Ensure that multiple duplicate status bar state changes to false do not try to re-collapse the stack. As this would clear the expanded state for bubbles that were updated while device was locked. Bug: 260652751 Test: atest BubblesTest Test: manual: 1. have a notification that is not a bubble 2. have pattern lock set and lock device 3. mark notification to be a bubble from lock screen 4. unlock device 5. observe bubble is added and expanded 6. lock device and unlock device again 7. observe stack is now collapsed Change-Id: Ie0fdbbb3cb95c0720a00e7e25deaeb438cc51df3 --- .../wm/shell/bubbles/BubbleController.java | 7 +++- .../row/NotificationTestHelper.java | 22 ++++++++++--- .../android/systemui/wmshell/BubblesTest.java | 32 ++++++++++++++++++- 3 files changed, 54 insertions(+), 7 deletions(-) diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java index bec6844ae8631..dd8afff0df2cf 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java @@ -475,8 +475,13 @@ public class BubbleController implements ConfigurationChangeListener { @VisibleForTesting public void onStatusBarStateChanged(boolean isShade) { + boolean didChange = mIsStatusBarShade != isShade; + if (DEBUG_BUBBLE_CONTROLLER) { + Log.d(TAG, "onStatusBarStateChanged isShade=" + isShade + " didChange=" + didChange); + } mIsStatusBarShade = isShade; - if (!mIsStatusBarShade) { + if (!mIsStatusBarShade && didChange) { + // Only collapse stack on change collapseStack(); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java index 5fd9448b129d0..fb31bef909e06 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java @@ -301,7 +301,8 @@ public class NotificationTestHelper { public ExpandableNotificationRow createBubble() throws Exception { Notification n = createNotification(false /* isGroupSummary */, - null /* groupKey */, makeBubbleMetadata(null)); + null /* groupKey */, + makeBubbleMetadata(null /* deleteIntent */, false /* autoExpand */)); n.flags |= FLAG_BUBBLE; ExpandableNotificationRow row = generateRow(n, PKG, UID, USER_HANDLE, mDefaultInflationFlags, IMPORTANCE_HIGH); @@ -334,7 +335,8 @@ public class NotificationTestHelper { public ExpandableNotificationRow createBubbleInGroup() throws Exception { Notification n = createNotification(false /* isGroupSummary */, - GROUP_KEY /* groupKey */, makeBubbleMetadata(null)); + GROUP_KEY /* groupKey */, + makeBubbleMetadata(null /* deleteIntent */, false /* autoExpand */)); n.flags |= FLAG_BUBBLE; ExpandableNotificationRow row = generateRow(n, PKG, UID, USER_HANDLE, mDefaultInflationFlags, IMPORTANCE_HIGH); @@ -350,7 +352,7 @@ public class NotificationTestHelper { * @param deleteIntent the intent to assign to {@link BubbleMetadata#deleteIntent} */ public NotificationEntry createBubble(@Nullable PendingIntent deleteIntent) { - return createBubble(makeBubbleMetadata(deleteIntent), USER_HANDLE); + return createBubble(makeBubbleMetadata(deleteIntent, false /* autoExpand */), USER_HANDLE); } /** @@ -359,7 +361,16 @@ public class NotificationTestHelper { * @param handle the user to associate with this bubble. */ public NotificationEntry createBubble(UserHandle handle) { - return createBubble(makeBubbleMetadata(null), handle); + return createBubble(makeBubbleMetadata(null /* deleteIntent */, false /* autoExpand */), + handle); + } + + /** + * Returns an {@link NotificationEntry} that should be shown as a auto-expanded bubble. + */ + public NotificationEntry createAutoExpandedBubble() { + return createBubble(makeBubbleMetadata(null /* deleteIntent */, true /* autoExpand */), + USER_HANDLE); } /** @@ -567,7 +578,7 @@ public class NotificationTestHelper { assertTrue(countDownLatch.await(500, TimeUnit.MILLISECONDS)); } - private BubbleMetadata makeBubbleMetadata(PendingIntent deleteIntent) { + private BubbleMetadata makeBubbleMetadata(PendingIntent deleteIntent, boolean autoExpand) { Intent target = new Intent(mContext, BubblesTestActivity.class); PendingIntent bubbleIntent = PendingIntent.getActivity(mContext, 0, target, PendingIntent.FLAG_MUTABLE); @@ -576,6 +587,7 @@ public class NotificationTestHelper { Icon.createWithResource(mContext, R.drawable.android)) .setDeleteIntent(deleteIntent) .setDesiredHeight(314) + .setAutoExpandBubble(autoExpand) .build(); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java index d42f757e16bdb..b9dfc27483b83 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/wmshell/BubblesTest.java @@ -1423,13 +1423,43 @@ public class BubblesTest extends SysuiTestCase { assertStackCollapsed(); // Post status bar state change update with the same value mBubbleController.onStatusBarStateChanged(false); - // Stack should remain collapsedb + // Stack should remain collapsed assertStackCollapsed(); // Post status bar state change which should trigger bubble to expand mBubbleController.onStatusBarStateChanged(true); assertStackExpanded(); } + /** + * Test to verify behavior for the following scenario: + *
    + *
  1. device is locked with keyguard on, status bar shade state updates to + * false
  2. + *
  3. notification entry is marked to be a bubble and it is set to auto-expand
  4. + *
  5. device unlock starts, status bar shade state receives another update to + * false
  6. + *
  7. device is unlocked and status bar shade state is set to true
  8. + *
  9. bubble should be expanded
  10. + *
+ */ + @Test + public void testOnStatusBarStateChanged_newAutoExpandedBubbleRemainsExpanded() { + // Set device as locked + mBubbleController.onStatusBarStateChanged(false); + + // Create a auto-expanded bubble + NotificationEntry entry = mNotificationTestHelper.createAutoExpandedBubble(); + mEntryListener.onEntryAdded(entry); + + // When unlocking, we may receive duplicate updates with shade=false, ensure they don't + // clear the expanded state + mBubbleController.onStatusBarStateChanged(false); + mBubbleController.onStatusBarStateChanged(true); + + // After unlocking, stack should be expanded + assertStackExpanded(); + } + @Test public void testSetShouldAutoExpand_notifiesFlagChanged() { mBubbleController.updateBubble(mBubbleEntry); From a4aed0261fb392d52eb0080c532220fc4ddfb54d Mon Sep 17 00:00:00 2001 From: Mady Mellor Date: Thu, 1 Dec 2022 11:26:44 -0800 Subject: [PATCH 30/38] Ensure the manage menu is closed when the stack collapses Bug: 255908995 Test: manual - expand the bubble stack, open the manage menu, turn off the screen - turn on the screen and unlock => verify bubbles are collapsed Change-Id: I9ae1ff43a4c64ce46e4ad8fcbefc93e79c9d7afe --- .../Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java | 1 + 1 file changed, 1 insertion(+) diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java index 609ee084f23f1..2b7600cbfe530 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java @@ -1956,6 +1956,7 @@ public class BubbleStackView extends FrameLayout if (wasExpanded) { stopMonitoringSwipeUpGesture(); animateCollapse(); + showManageMenu(false); logBubbleEvent(mExpandedBubble, FrameworkStatsLog.BUBBLE_UICHANGED__ACTION__COLLAPSED); } else { animateExpansion(); From 8cdd2cd068751ccfaf2145033ef461dc8d291960 Mon Sep 17 00:00:00 2001 From: Merissa Tan Date: Wed, 30 Nov 2022 13:28:29 -0800 Subject: [PATCH 31/38] Set caption to full width in WindowDecoration if no width is defined. This CL sets the caption width to match the task bounds width if no fixed width is defined. Bug: None Test: atest WMShellUnitTests:WindowDecorationTests Change-Id: I033d0564f21974f5fdc982fba823ae42bdd9f37c --- .../shell/windowdecor/WindowDecoration.java | 4 +- .../windowdecor/WindowDecorationTests.java | 63 +++++++++++++++++-- 2 files changed, 61 insertions(+), 6 deletions(-) diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java index 7ecb3f3f63559..92154968855f4 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java @@ -251,7 +251,9 @@ public abstract class WindowDecoration } final int captionHeight = loadDimensionPixelSize(resources, params.mCaptionHeightId); - final int captionWidth = loadDimensionPixelSize(resources, params.mCaptionWidthId); + final int captionWidth = params.mCaptionWidthId == Resources.ID_NULL + ? taskBounds.width() + : loadDimensionPixelSize(resources, params.mCaptionWidthId); startT.setPosition( mCaptionContainerSurface, diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java index 15181b1549f50..dd9ab9899e130 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java @@ -113,6 +113,12 @@ public class WindowDecorationTests extends ShellTestCase { mMockSurfaceControlFinishT = createMockSurfaceControlTransaction(); mMockSurfaceControlAddWindowT = createMockSurfaceControlTransaction(); + mRelayoutParams.mLayoutResId = 0; + mRelayoutParams.mCaptionHeightId = R.dimen.test_freeform_decor_caption_height; + // Caption should have fixed width except in testLayoutResultCalculation_fullWidthCaption() + mRelayoutParams.mCaptionWidthId = R.dimen.test_freeform_decor_caption_width; + mRelayoutParams.mShadowRadiusId = R.dimen.test_window_decor_shadow_radius; + doReturn(mMockSurfaceControlViewHost).when(mMockSurfaceControlViewHostFactory) .create(any(), any(), any()); } @@ -435,6 +441,58 @@ public class WindowDecorationTests extends ShellTestCase { assertThat(additionalWindow.mWindowSurface).isNull(); } + @Test + public void testLayoutResultCalculation_fullWidthCaption() { + final Display defaultDisplay = mock(Display.class); + doReturn(defaultDisplay).when(mMockDisplayController) + .getDisplay(Display.DEFAULT_DISPLAY); + + final SurfaceControl decorContainerSurface = mock(SurfaceControl.class); + final SurfaceControl.Builder decorContainerSurfaceBuilder = + createMockSurfaceControlBuilder(decorContainerSurface); + mMockSurfaceControlBuilders.add(decorContainerSurfaceBuilder); + final SurfaceControl taskBackgroundSurface = mock(SurfaceControl.class); + final SurfaceControl.Builder taskBackgroundSurfaceBuilder = + createMockSurfaceControlBuilder(taskBackgroundSurface); + mMockSurfaceControlBuilders.add(taskBackgroundSurfaceBuilder); + final SurfaceControl captionContainerSurface = mock(SurfaceControl.class); + final SurfaceControl.Builder captionContainerSurfaceBuilder = + createMockSurfaceControlBuilder(captionContainerSurface); + mMockSurfaceControlBuilders.add(captionContainerSurfaceBuilder); + + final SurfaceControl.Transaction t = mock(SurfaceControl.Transaction.class); + mMockSurfaceControlTransactions.add(t); + final ActivityManager.TaskDescription.Builder taskDescriptionBuilder = + new ActivityManager.TaskDescription.Builder() + .setBackgroundColor(Color.YELLOW); + final ActivityManager.RunningTaskInfo taskInfo = new TestRunningTaskInfoBuilder() + .setDisplayId(Display.DEFAULT_DISPLAY) + .setTaskDescriptionBuilder(taskDescriptionBuilder) + .setBounds(TASK_BOUNDS) + .setPositionInParent(TASK_POSITION_IN_PARENT.x, TASK_POSITION_IN_PARENT.y) + .setVisible(true) + .build(); + taskInfo.isFocused = true; + taskInfo.configuration.densityDpi = DisplayMetrics.DENSITY_DEFAULT * 2; + mRelayoutParams.setOutsets( + R.dimen.test_window_decor_left_outset, + R.dimen.test_window_decor_top_outset, + R.dimen.test_window_decor_right_outset, + R.dimen.test_window_decor_bottom_outset); + final SurfaceControl taskSurface = mock(SurfaceControl.class); + final TestWindowDecoration windowDecor = createWindowDecoration(taskInfo, taskSurface); + + mRelayoutParams.mCaptionWidthId = Resources.ID_NULL; + windowDecor.relayout(taskInfo); + + verify(captionContainerSurfaceBuilder).setParent(decorContainerSurface); + verify(captionContainerSurfaceBuilder).setContainerLayer(); + verify(mMockSurfaceControlStartT).setPosition(captionContainerSurface, 20, 40); + // Width of the captionContainerSurface should match the width of TASK_BOUNDS + verify(mMockSurfaceControlStartT).setWindowCrop(captionContainerSurface, 300, 64); + verify(mMockSurfaceControlStartT).show(captionContainerSurface); + } + private TestWindowDecoration createWindowDecoration( ActivityManager.RunningTaskInfo taskInfo, SurfaceControl testSurface) { return new TestWindowDecoration(InstrumentationRegistry.getInstrumentation().getContext(), @@ -490,11 +548,6 @@ public class WindowDecorationTests extends ShellTestCase { @Override void relayout(ActivityManager.RunningTaskInfo taskInfo) { - mRelayoutParams.mLayoutResId = 0; - mRelayoutParams.mCaptionHeightId = R.dimen.test_freeform_decor_caption_height; - mRelayoutParams.mCaptionWidthId = R.dimen.test_freeform_decor_caption_width; - mRelayoutParams.mShadowRadiusId = R.dimen.test_window_decor_shadow_radius; - relayout(mRelayoutParams, mMockSurfaceControlStartT, mMockSurfaceControlFinishT, mMockWindowContainerTransaction, mMockView, mRelayoutResult); } From dd5a3ff6e06e765f1582179e5dfcd29396a81698 Mon Sep 17 00:00:00 2001 From: Raphael Kim Date: Fri, 14 Oct 2022 10:43:35 -0700 Subject: [PATCH 32/38] Ignore scheduled onDeviceGone call on simulated device if it is already no longer present. Bug: 259286481 Bug: 253637009 Test: atest CtsCompanionDeviceManagerCoreTestCases atest CtsCompanionDeviceManagerUiAutomationTestCases Change-Id: Ia7f5eabde8879ff4f6bc5b5cc19455bbd4164ac9 Merged-In: Ia7f5eabde8879ff4f6bc5b5cc19455bbd4164ac9 (cherry picked from commit bfbf0e4b3b32f8e672a306d19bd83072c6ee0bee) --- .../companion/presence/CompanionDevicePresenceMonitor.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/services/companion/java/com/android/server/companion/presence/CompanionDevicePresenceMonitor.java b/services/companion/java/com/android/server/companion/presence/CompanionDevicePresenceMonitor.java index 0e4870af99307..a1e734dead777 100644 --- a/services/companion/java/com/android/server/companion/presence/CompanionDevicePresenceMonitor.java +++ b/services/companion/java/com/android/server/companion/presence/CompanionDevicePresenceMonitor.java @@ -363,7 +363,9 @@ public class CompanionDevicePresenceMonitor implements AssociationStore.OnChange @Override public void handleMessage(@NonNull Message msg) { final int associationId = msg.what; - onDeviceGone(mSimulated, associationId, /* sourceLoggingTag */ "simulated"); + if (mSimulated.contains(associationId)) { + onDeviceGone(mSimulated, associationId, /* sourceLoggingTag */ "simulated"); + } } } } From 46917e533615c8cf66754b96885155e847ed2ef2 Mon Sep 17 00:00:00 2001 From: Peter Kalauskas Date: Mon, 21 Nov 2022 16:53:34 -0800 Subject: [PATCH 33/38] TraceUtils updates, new helper for runnables Modify TraceUtils' traceSection to use traceBegin instead of beginSection because beginSection will crash at run-time if the string is longer than 127 chars. Also, guard against StringBuilder GC garbage while tracing. Test: manual Bug: 257075630 Change-Id: I74cb5687a206f5d7ab8eb570cf24715d7e671df1 --- .../com/android/systemui/util/TraceUtils.kt | 25 +++++++++++++------ 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/util/TraceUtils.kt b/packages/SystemUI/src/com/android/systemui/util/TraceUtils.kt index 5b16ae999aa30..b311318fb111f 100644 --- a/packages/SystemUI/src/com/android/systemui/util/TraceUtils.kt +++ b/packages/SystemUI/src/com/android/systemui/util/TraceUtils.kt @@ -22,11 +22,22 @@ import android.os.Trace * Run a block within a [Trace] section. * Calls [Trace.beginSection] before and [Trace.endSection] after the passed block. */ -inline fun traceSection(tag: String, block: () -> T): T { - Trace.beginSection(tag) - try { - return block() - } finally { - Trace.endSection() +inline fun traceSection(tag: String, block: () -> T): T = + if (Trace.isTagEnabled(Trace.TRACE_TAG_APP)) { + Trace.traceBegin(Trace.TRACE_TAG_APP, tag) + try { + block() + } finally { + Trace.traceEnd(Trace.TRACE_TAG_APP) + } + } else { + block() + } + +class TraceUtils { + companion object { + inline fun traceRunnable(tag: String, crossinline block: () -> Unit): Runnable { + return Runnable { traceSection(tag) { block() } } + } } -} \ No newline at end of file +} From ab2c6aa021e9ea7ada1b606ec76b8a24335453cb Mon Sep 17 00:00:00 2001 From: Peter Kalauskas Date: Tue, 22 Nov 2022 12:57:40 -0800 Subject: [PATCH 34/38] Guard against possible exception when tracing Trace.beginSection() throws an IllegalArgumentException if section name is longer than 127 chars. Therefore, it shouldn't be used anytime a string name is generated at runtime. Instead, replace with equivalent call to Trace.traceBegin(). Also, guard against StringBuilder GC garbage while tracing. Test: manual Bug: 257075630 Change-Id: Ia3477dc98b7d87f6fcd0c4f2e0aaad976f2203a2 --- .../systemui/media/controls/ui/MediaControlPanel.java | 10 +++++++--- .../collection/listbuilder/pluggable/Pluggable.java | 4 +++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java index 21e64e28ff197..827ac789073ac 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java +++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/MediaControlPanel.java @@ -458,7 +458,9 @@ public class MediaControlPanel { if (mMediaViewHolder == null) { return; } - Trace.beginSection("MediaControlPanel#bindPlayer<" + key + ">"); + if (Trace.isEnabled()) { + Trace.traceBegin(Trace.TRACE_TAG_APP, "MediaControlPanel#bindPlayer<" + key + ">"); + } mKey = key; mMediaData = data; MediaSession.Token token = data.getToken(); @@ -1179,8 +1181,10 @@ public class MediaControlPanel { return; } - Trace.beginSection( - "MediaControlPanel#bindRecommendation<" + data.getPackageName() + ">"); + if (Trace.isEnabled()) { + Trace.traceBegin(Trace.TRACE_TAG_APP, + "MediaControlPanel#bindRecommendation<" + data.getPackageName() + ">"); + } mRecommendationData = data; mSmartspaceId = SmallHash.hash(data.getTargetId()); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/Pluggable.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/Pluggable.java index 966ab4c61b504..afdadeb74e234 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/Pluggable.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/Pluggable.java @@ -51,7 +51,9 @@ public abstract class Pluggable { */ public final void invalidateList(@Nullable String reason) { if (mListener != null) { - Trace.beginSection("Pluggable<" + mName + ">.invalidateList"); + if (Trace.isEnabled()) { + Trace.traceBegin(Trace.TRACE_TAG_APP, "Pluggable<" + mName + ">.invalidateList"); + } mListener.onPluggableInvalidated((This) this, reason); Trace.endSection(); } From 76d2b200ae4bb21dac04a0e874ee9831ae4a8ac9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Ciche=C5=84ski?= Date: Wed, 30 Nov 2022 01:16:34 +0000 Subject: [PATCH 35/38] Don't move PiP towards a corner after user manually moved it. With keep clear areas flag on, PiP will gravitate towards one of the bottom corners of the screen if possible. However, once a user moves PiP manually, it will only continue to avoid occluding keep clear areas, but no longer move downwards. This also happens if user resized the window. This can be disabled by turning the newly introduced sysprop flag. Bug: 258529269 Test: manually Change-Id: Ieaa292c54762d5cd005bcdf7eab48d6082e5c3a9 --- .../android/wm/shell/pip/PipBoundsState.java | 15 ++++++ .../pip/phone/PhonePipKeepClearAlgorithm.java | 48 +++++++++++-------- .../wm/shell/pip/phone/PipTouchHandler.java | 2 + 3 files changed, 46 insertions(+), 19 deletions(-) diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java index 17d7f5d0d5673..5376ae372de21 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipBoundsState.java @@ -97,6 +97,8 @@ public class PipBoundsState { private int mShelfHeight; /** Whether the user has resized the PIP manually. */ private boolean mHasUserResizedPip; + /** Whether the user has moved the PIP manually. */ + private boolean mHasUserMovedPip; /** * Areas defined by currently visible apps that they prefer to keep clear from overlays such as * the PiP. Restricted areas may only move the PiP a limited amount from its anchor position. @@ -279,6 +281,7 @@ public class PipBoundsState { if (changed) { clearReentryState(); setHasUserResizedPip(false); + setHasUserMovedPip(false); } } @@ -442,6 +445,16 @@ public class PipBoundsState { mHasUserResizedPip = hasUserResizedPip; } + /** Returns whether the user has moved the PIP. */ + public boolean hasUserMovedPip() { + return mHasUserMovedPip; + } + + /** Set whether the user has moved the PIP. */ + public void setHasUserMovedPip(boolean hasUserMovedPip) { + mHasUserMovedPip = hasUserMovedPip; + } + /** * Registers a callback when the minimal size of PIP that is set by the app changes. */ @@ -577,6 +590,8 @@ public class PipBoundsState { pw.println(innerPrefix + "mImeHeight=" + mImeHeight); pw.println(innerPrefix + "mIsShelfShowing=" + mIsShelfShowing); pw.println(innerPrefix + "mShelfHeight=" + mShelfHeight); + pw.println(innerPrefix + "mHasUserMovedPip=" + mHasUserMovedPip); + pw.println(innerPrefix + "mHasUserResizedPip=" + mHasUserResizedPip); if (mPipReentryState == null) { pw.println(innerPrefix + "mPipReentryState=null"); } else { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipKeepClearAlgorithm.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipKeepClearAlgorithm.java index 84071e08d4721..690505e03fce8 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipKeepClearAlgorithm.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PhonePipKeepClearAlgorithm.java @@ -19,6 +19,7 @@ package com.android.wm.shell.pip.phone; import android.content.Context; import android.content.res.Resources; import android.graphics.Rect; +import android.os.SystemProperties; import android.util.ArraySet; import android.view.Gravity; @@ -34,6 +35,10 @@ import java.util.Set; */ public class PhonePipKeepClearAlgorithm implements PipKeepClearAlgorithm { + private boolean mKeepClearAreaGravityEnabled = + SystemProperties.getBoolean( + "persist.wm.debug.enable_pip_keep_clear_algorithm_gravity", false); + protected int mKeepClearAreasPadding; public PhonePipKeepClearAlgorithm(Context context) { @@ -53,31 +58,36 @@ public class PhonePipKeepClearAlgorithm implements PipKeepClearAlgorithm { Rect startingBounds = pipBoundsState.getBounds().isEmpty() ? pipBoundsAlgorithm.getEntryDestinationBoundsIgnoringKeepClearAreas() : pipBoundsState.getBounds(); - float snapFraction = pipBoundsAlgorithm.getSnapFraction(startingBounds); - int verticalGravity = Gravity.BOTTOM; - int horizontalGravity; - if (snapFraction >= 0.5f && snapFraction < 2.5f) { - horizontalGravity = Gravity.RIGHT; - } else { - horizontalGravity = Gravity.LEFT; - } - // push the bounds based on the gravity Rect insets = new Rect(); pipBoundsAlgorithm.getInsetBounds(insets); if (pipBoundsState.isImeShowing()) { insets.bottom -= pipBoundsState.getImeHeight(); } - Rect pushedBounds = new Rect(startingBounds); - if (verticalGravity == Gravity.BOTTOM) { - pushedBounds.offsetTo(pushedBounds.left, - insets.bottom - pushedBounds.height()); + Rect pipBounds = new Rect(startingBounds); + + // move PiP towards corner if user hasn't moved it manually or the flag is on + if (mKeepClearAreaGravityEnabled + || (!pipBoundsState.hasUserMovedPip() && !pipBoundsState.hasUserResizedPip())) { + float snapFraction = pipBoundsAlgorithm.getSnapFraction(startingBounds); + int verticalGravity = Gravity.BOTTOM; + int horizontalGravity; + if (snapFraction >= 0.5f && snapFraction < 2.5f) { + horizontalGravity = Gravity.RIGHT; + } else { + horizontalGravity = Gravity.LEFT; + } + if (verticalGravity == Gravity.BOTTOM) { + pipBounds.offsetTo(pipBounds.left, + insets.bottom - pipBounds.height()); + } + if (horizontalGravity == Gravity.RIGHT) { + pipBounds.offsetTo(insets.right - pipBounds.width(), pipBounds.top); + } else { + pipBounds.offsetTo(insets.left, pipBounds.top); + } } - if (horizontalGravity == Gravity.RIGHT) { - pushedBounds.offsetTo(insets.right - pushedBounds.width(), pushedBounds.top); - } else { - pushedBounds.offsetTo(insets.left, pushedBounds.top); - } - return findUnoccludedPosition(pushedBounds, pipBoundsState.getRestrictedKeepClearAreas(), + + return findUnoccludedPosition(pipBounds, pipBoundsState.getRestrictedKeepClearAreas(), pipBoundsState.getUnrestrictedKeepClearAreas(), insets); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java index a9a97beb91804..83bc7c0e6e7d9 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java @@ -875,6 +875,8 @@ public class PipTouchHandler { } if (touchState.isDragging()) { + mPipBoundsState.setHasUserMovedPip(true); + // Move the pinned stack freely final PointF lastDelta = touchState.getLastTouchDelta(); float lastX = mStartPosition.x + mDelta.x; From 8b5178beac7013fae4ffa1cb37ab2aa5a443ff3f Mon Sep 17 00:00:00 2001 From: Aaron Liu Date: Thu, 1 Dec 2022 18:48:18 -0800 Subject: [PATCH 36/38] Fix fatal exception in FakeBroadcastReceiver. It seems like an exception is thrown because ArraySet is not thread-safe. Use a synchronized hash set for the receivers. Fixes: 261099639 Test: atest KeyguardQuickAffordanceProviderTest Change-Id: I39c43bb2d5dbdc6705b5dec4b362d75189c136d9 --- .../com/android/systemui/broadcast/FakeBroadcastDispatcher.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/broadcast/FakeBroadcastDispatcher.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/broadcast/FakeBroadcastDispatcher.kt index 52e0c982cae0c..ad086ff9c664c 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/broadcast/FakeBroadcastDispatcher.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/broadcast/FakeBroadcastDispatcher.kt @@ -22,12 +22,12 @@ import android.content.IntentFilter import android.os.Handler import android.os.Looper import android.os.UserHandle -import android.util.ArraySet import android.util.Log import com.android.systemui.SysuiTestableContext import com.android.systemui.broadcast.logging.BroadcastDispatcherLogger import com.android.systemui.dump.DumpManager import com.android.systemui.settings.UserTracker +import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.Executor class FakeBroadcastDispatcher( @@ -50,7 +50,7 @@ class FakeBroadcastDispatcher( PendingRemovalStore(logger) ) { - val registeredReceivers = ArraySet() + val registeredReceivers: MutableSet = ConcurrentHashMap.newKeySet() override fun registerReceiverWithHandler( receiver: BroadcastReceiver, From 5587e154c9c19a54ff114a89b21eb28707c6debd Mon Sep 17 00:00:00 2001 From: Alejandro Nijamkin Date: Fri, 2 Dec 2022 07:04:57 -0800 Subject: [PATCH 37/38] Adds icon support to fake quick affordance client. This is needed for tests in ag/20601630 Bug: 254858701 Test: N/A - this is testing Change-Id: Ibe86233511078f7c2d32cd8abb8ba97afedbcb79 --- .../FakeKeyguardQuickAffordanceProviderClient.kt | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/packages/SystemUI/customization/src/com/android/systemui/shared/quickaffordance/data/content/FakeKeyguardQuickAffordanceProviderClient.kt b/packages/SystemUI/customization/src/com/android/systemui/shared/quickaffordance/data/content/FakeKeyguardQuickAffordanceProviderClient.kt index f490c5459d467..cb1a5f958ed6d 100644 --- a/packages/SystemUI/customization/src/com/android/systemui/shared/quickaffordance/data/content/FakeKeyguardQuickAffordanceProviderClient.kt +++ b/packages/SystemUI/customization/src/com/android/systemui/shared/quickaffordance/data/content/FakeKeyguardQuickAffordanceProviderClient.kt @@ -42,17 +42,17 @@ class FakeKeyguardQuickAffordanceProviderClient( KeyguardQuickAffordanceProviderClient.Affordance( id = AFFORDANCE_1, name = AFFORDANCE_1, - iconResourceId = 0, + iconResourceId = 1, ), KeyguardQuickAffordanceProviderClient.Affordance( id = AFFORDANCE_2, name = AFFORDANCE_2, - iconResourceId = 0, + iconResourceId = 2, ), KeyguardQuickAffordanceProviderClient.Affordance( id = AFFORDANCE_3, name = AFFORDANCE_3, - iconResourceId = 0, + iconResourceId = 3, ), ), flags: List = @@ -131,7 +131,12 @@ class FakeKeyguardQuickAffordanceProviderClient( } override suspend fun getAffordanceIcon(iconResourceId: Int, tintColor: Int): Drawable { - return BitmapDrawable() + return when (iconResourceId) { + 1 -> ICON_1 + 2 -> ICON_2 + 3 -> ICON_3 + else -> BitmapDrawable() + } } fun setFlag( @@ -186,5 +191,8 @@ class FakeKeyguardQuickAffordanceProviderClient( const val AFFORDANCE_1 = "affordance_1" const val AFFORDANCE_2 = "affordance_2" const val AFFORDANCE_3 = "affordance_3" + val ICON_1 = BitmapDrawable() + val ICON_2 = BitmapDrawable() + val ICON_3 = BitmapDrawable() } } From d6cd8d5c02fbd086feff9119bb5eb6083dd68db5 Mon Sep 17 00:00:00 2001 From: Beverly Date: Fri, 2 Dec 2022 16:14:10 +0000 Subject: [PATCH 38/38] Update FP listening right after POWER_PRESSED err Instead of delaying 500ms Test: atest KeyguardUpdateMonitorTest Test: Attempt to authenticate with SideFPS right after pressing the power button => observe FP can authenticate Fixes: 259172472 Change-Id: I7f07c549628a21a92ddfac0d0679d0f054ad1dda --- .../com/android/keyguard/KeyguardUpdateMonitor.java | 10 +++++++--- .../keyguard/logging/KeyguardUpdateMonitorLogger.kt | 5 +++-- .../android/keyguard/KeyguardUpdateMonitorTest.java | 11 +++++++++-- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index bba4e2c6a9ff1..b46a3e788851c 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -955,12 +955,16 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab setFingerprintRunningState(BIOMETRIC_STATE_STOPPED); } - if (msgId == FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE - || msgId == FingerprintManager.BIOMETRIC_ERROR_POWER_PRESSED) { - mLogger.logRetryAfterFpError(msgId, errString); + if (msgId == FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE) { + mLogger.logRetryAfterFpErrorWithDelay(msgId, errString, HAL_ERROR_RETRY_TIMEOUT); mHandler.postDelayed(mRetryFingerprintAuthentication, HAL_ERROR_RETRY_TIMEOUT); } + if (msgId == FingerprintManager.BIOMETRIC_ERROR_POWER_PRESSED) { + mLogger.logRetryAfterFpErrorWithDelay(msgId, errString, 0); + updateFingerprintListeningState(BIOMETRIC_ACTION_START); + } + boolean lockedOutStateChanged = false; if (msgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT) { lockedOutStateChanged = !mFingerprintLockedOutPermanent; diff --git a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt index 1f6441a470929..b66ae286171ae 100644 --- a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt +++ b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt @@ -225,12 +225,13 @@ class KeyguardUpdateMonitorLogger @Inject constructor( { "Retrying face after HW unavailable, attempt $int1" }) } - fun logRetryAfterFpError(msgId: Int, errString: String?) { + fun logRetryAfterFpErrorWithDelay(msgId: Int, errString: String?, delay: Int) { logBuffer.log(TAG, DEBUG, { int1 = msgId + int2 = delay str1 = "$errString" }, { - "Fingerprint retrying auth due to($int1) -> $str1" + "Fingerprint retrying auth after $int2 ms due to($int1) -> $str1" }) } diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java index 1cce472b7c735..50abac2d6871a 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java @@ -779,6 +779,15 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean()); } + @Test + public void testFingerprintPowerPressed_restartsFingerprintListeningStateImmediately() { + mKeyguardUpdateMonitor.mFingerprintAuthenticationCallback + .onAuthenticationError(FingerprintManager.BIOMETRIC_ERROR_POWER_PRESSED, ""); + + verify(mFingerprintManager).authenticate(any(), any(), any(), any(), anyInt(), anyInt(), + anyInt()); + } + @Test public void testOnFaceAuthenticated_skipsFaceWhenAuthenticated() { // test whether face will be skipped if authenticated, so the value of isStrongBiometric @@ -919,8 +928,6 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean()); verify(mFingerprintManager).authenticate(any(), any(), any(), any(), anyInt(), anyInt(), anyInt()); -// resetFaceManager(); -// resetFingerprintManager(); when(mFingerprintManager.getLockoutModeForUser(eq(FINGERPRINT_SENSOR_ID), eq(newUser))) .thenReturn(fingerprintLockoutMode);