diff options
828 files changed, 20591 insertions, 8466 deletions
diff --git a/core/api/test-current.txt b/core/api/test-current.txt index 2b09e6bad873..d18a9c7da5a1 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -287,6 +287,7 @@ package android.app { method @RequiresPermission(android.Manifest.permission.WRITE_DREAM_STATE) public void setDreamOverlay(@Nullable android.content.ComponentName); method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setScreensaverEnabled(boolean); method @RequiresPermission(android.Manifest.permission.WRITE_DREAM_STATE) public void setSystemDreamComponent(@Nullable android.content.ComponentName); + method @RequiresPermission(android.Manifest.permission.WRITE_DREAM_STATE) public void startDream(@Nullable android.content.ComponentName); method @RequiresPermission(android.Manifest.permission.WRITE_DREAM_STATE) public void startDream(); method @RequiresPermission(android.Manifest.permission.WRITE_DREAM_STATE) public void stopDream(); } @@ -3360,17 +3361,11 @@ package android.window { ctor public TaskFragmentOrganizer(@NonNull java.util.concurrent.Executor); method @NonNull public java.util.concurrent.Executor getExecutor(); method @NonNull public android.window.TaskFragmentOrganizerToken getOrganizerToken(); - method public void onActivityReparentedToTask(@NonNull android.window.WindowContainerTransaction, int, @NonNull android.content.Intent, @NonNull android.os.IBinder); method @Deprecated public void onTaskFragmentAppeared(@NonNull android.window.TaskFragmentInfo); - method public void onTaskFragmentAppeared(@NonNull android.window.WindowContainerTransaction, @NonNull android.window.TaskFragmentInfo); method @Deprecated public void onTaskFragmentError(@NonNull android.os.IBinder, @NonNull Throwable); - method public void onTaskFragmentError(@NonNull android.window.WindowContainerTransaction, @NonNull android.os.IBinder, @Nullable android.window.TaskFragmentInfo, int, @NonNull Throwable); method @Deprecated public void onTaskFragmentInfoChanged(@NonNull android.window.TaskFragmentInfo); - method public void onTaskFragmentInfoChanged(@NonNull android.window.WindowContainerTransaction, @NonNull android.window.TaskFragmentInfo); method @Deprecated public void onTaskFragmentParentInfoChanged(@NonNull android.os.IBinder, @NonNull android.content.res.Configuration); - method public void onTaskFragmentParentInfoChanged(@NonNull android.window.WindowContainerTransaction, int, @NonNull android.content.res.Configuration); method @Deprecated public void onTaskFragmentVanished(@NonNull android.window.TaskFragmentInfo); - method public void onTaskFragmentVanished(@NonNull android.window.WindowContainerTransaction, @NonNull android.window.TaskFragmentInfo); method @CallSuper public void registerOrganizer(); method @CallSuper public void unregisterOrganizer(); } diff --git a/core/java/android/accessibilityservice/InputMethod.java b/core/java/android/accessibilityservice/InputMethod.java index 1585f99759cd..93888ef5ba6f 100644 --- a/core/java/android/accessibilityservice/InputMethod.java +++ b/core/java/android/accessibilityservice/InputMethod.java @@ -517,7 +517,8 @@ public class InputMethod { @Override public void invalidateInput(EditorInfo editorInfo, IRemoteAccessibilityInputConnection connection, int sessionId) { - if (!mStartedInputConnection.isSameConnection(connection)) { + if (!mEnabled || mStartedInputConnection == null + || !mStartedInputConnection.isSameConnection(connection)) { // This is not an error, and can be safely ignored. return; } diff --git a/core/java/android/app/ActivityTransitionState.java b/core/java/android/app/ActivityTransitionState.java index 877e7d3b3bf7..6f4bb456c478 100644 --- a/core/java/android/app/ActivityTransitionState.java +++ b/core/java/android/app/ActivityTransitionState.java @@ -145,7 +145,10 @@ class ActivityTransitionState { * that it is preserved through activty destroy and restore. */ private ArrayList<String> getPendingExitNames() { - if (mPendingExitNames == null && mEnterTransitionCoordinator != null) { + if (mPendingExitNames == null + && mEnterTransitionCoordinator != null + && !mEnterTransitionCoordinator.isReturning() + ) { mPendingExitNames = mEnterTransitionCoordinator.getPendingExitSharedElementNames(); } return mPendingExitNames; @@ -202,6 +205,7 @@ class ActivityTransitionState { restoreExitedViews(); activity.getWindow().getDecorView().setVisibility(View.VISIBLE); } + getPendingExitNames(); // Set mPendingExitNames before resetting mEnterTransitionCoordinator mEnterTransitionCoordinator = new EnterTransitionCoordinator(activity, resultReceiver, sharedElementNames, mEnterActivityOptions.isReturning(), mEnterActivityOptions.isCrossTask()); @@ -250,6 +254,7 @@ class ActivityTransitionState { public void onStop(Activity activity) { restoreExitedViews(); if (mEnterTransitionCoordinator != null) { + getPendingExitNames(); // Set mPendingExitNames before clearing mEnterTransitionCoordinator.stop(); mEnterTransitionCoordinator = null; } @@ -275,6 +280,7 @@ class ActivityTransitionState { restoreReenteringViews(); } else if (mEnterTransitionCoordinator.isReturning()) { mEnterTransitionCoordinator.runAfterTransitionsComplete(() -> { + getPendingExitNames(); // Set mPendingExitNames before clearing mEnterTransitionCoordinator = null; }); } @@ -374,6 +380,7 @@ class ActivityTransitionState { } public void startExitOutTransition(Activity activity, Bundle options) { + getPendingExitNames(); // Set mPendingExitNames before clearing mEnterTransitionCoordinator mEnterTransitionCoordinator = null; if (!activity.getWindow().hasFeature(Window.FEATURE_ACTIVITY_TRANSITIONS) || mExitTransitionCoordinators == null) { diff --git a/core/java/android/app/DreamManager.java b/core/java/android/app/DreamManager.java index 7c8b0fd499e3..3bb66581d502 100644 --- a/core/java/android/app/DreamManager.java +++ b/core/java/android/app/DreamManager.java @@ -87,6 +87,25 @@ public class DreamManager { /** * Starts dreaming. * + * This API is equivalent to {@link DreamManager#startDream()} but with a nullable component + * name to be compatible with TM CTS tests. + * + * <p>This is only used for testing the dream service APIs. + * + * @see DreamManager#startDream() + * + * @hide + */ + @TestApi + @UserHandleAware + @RequiresPermission(android.Manifest.permission.WRITE_DREAM_STATE) + public void startDream(@Nullable ComponentName name) { + startDream(); + } + + /** + * Starts dreaming. + * * The system dream component, if set by {@link DreamManager#setSystemDreamComponent}, will be * started. * Otherwise, starts the active dream set by {@link DreamManager#setActiveDream}. diff --git a/core/java/android/app/NotificationChannelGroup.java b/core/java/android/app/NotificationChannelGroup.java index 2b245aae915f..5c29eb35fcee 100644 --- a/core/java/android/app/NotificationChannelGroup.java +++ b/core/java/android/app/NotificationChannelGroup.java @@ -95,8 +95,11 @@ public final class NotificationChannelGroup implements Parcelable { } else { mId = null; } - mName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); - mName = getTrimmedString(mName.toString()); + if (in.readByte() != 0) { + mName = getTrimmedString(in.readString()); + } else { + mName = ""; + } if (in.readByte() != 0) { mDescription = getTrimmedString(in.readString()); } else { @@ -122,7 +125,12 @@ public final class NotificationChannelGroup implements Parcelable { } else { dest.writeByte((byte) 0); } - TextUtils.writeToParcel(mName.toString(), dest, flags); + if (mName != null) { + dest.writeByte((byte) 1); + dest.writeString(mName.toString()); + } else { + dest.writeByte((byte) 0); + } if (mDescription != null) { dest.writeByte((byte) 1); dest.writeString(mDescription); diff --git a/core/java/android/app/PropertyInvalidatedCache.java b/core/java/android/app/PropertyInvalidatedCache.java index 13934e592d40..a51b9d3956df 100644 --- a/core/java/android/app/PropertyInvalidatedCache.java +++ b/core/java/android/app/PropertyInvalidatedCache.java @@ -391,7 +391,12 @@ public class PropertyInvalidatedCache<Query, Result> { private static final boolean DEBUG = false; private static final boolean VERIFY = false; - // Per-Cache performance counters. As some cache instances are declared static, + /** + * The object-private lock. + */ + private final Object mLock = new Object(); + + // Per-Cache performance counters. @GuardedBy("mLock") private long mHits = 0; @@ -410,25 +415,19 @@ public class PropertyInvalidatedCache<Query, Result> { @GuardedBy("mLock") private long mClears = 0; - // Most invalidation is done in a static context, so the counters need to be accessible. - @GuardedBy("sCorkLock") - private static final HashMap<String, Long> sInvalidates = new HashMap<>(); - /** - * Record the number of invalidate or cork calls that were nops because - * the cache was already corked. This is static because invalidation is - * done in a static context. + * Protect objects that support corking. mLock and sGlobalLock must never be taken while this + * is held. */ - @GuardedBy("sCorkLock") - private static final HashMap<String, Long> sCorkedInvalidates = new HashMap<>(); + private static final Object sCorkLock = new Object(); /** - * If sEnabled is false then all cache operations are stubbed out. Set - * it to false inside test processes. + * Record the number of invalidate or cork calls that were nops because the cache was already + * corked. This is static because invalidation is done in a static context. Entries are + * indexed by the cache property. */ - private static boolean sEnabled = true; - - private static final Object sCorkLock = new Object(); + @GuardedBy("sCorkLock") + private static final HashMap<String, Long> sCorkedInvalidates = new HashMap<>(); /** * A map of cache keys that we've "corked". (The values are counts.) When a cache key is @@ -440,21 +439,39 @@ public class PropertyInvalidatedCache<Query, Result> { private static final HashMap<String, Integer> sCorks = new HashMap<>(); /** + * A lock for the global list of caches and cache keys. This must never be taken inside mLock + * or sCorkLock. + */ + private static final Object sGlobalLock = new Object(); + + /** * A map of cache keys that have been disabled in the local process. When a key is * disabled locally, existing caches are disabled and the key is saved in this map. * Future cache instances that use the same key will be disabled in their constructor. */ - @GuardedBy("sCorkLock") + @GuardedBy("sGlobalLock") private static final HashSet<String> sDisabledKeys = new HashSet<>(); /** * Weakly references all cache objects in the current process, allowing us to iterate over * them all for purposes like issuing debug dumps and reacting to memory pressure. */ - @GuardedBy("sCorkLock") + @GuardedBy("sGlobalLock") private static final WeakHashMap<PropertyInvalidatedCache, Void> sCaches = new WeakHashMap<>(); - private final Object mLock = new Object(); + /** + * Counts of the number of times a cache key was invalidated. Invalidation occurs in a static + * context with no cache object available, so this is a static map. Entries are indexed by + * the cache property. + */ + @GuardedBy("sGlobalLock") + private static final HashMap<String, Long> sInvalidates = new HashMap<>(); + + /** + * If sEnabled is false then all cache operations are stubbed out. Set + * it to false inside test processes. + */ + private static boolean sEnabled = true; /** * Name of the property that holds the unique value that we use to invalidate the cache. @@ -595,14 +612,17 @@ public class PropertyInvalidatedCache<Query, Result> { }; } - // Register the map in the global list. If the cache is disabled globally, disable it - // now. + /** + * Register the map in the global list. If the cache is disabled globally, disable it + * now. This method is only ever called from the constructor, which means no other thread has + * access to the object yet. It can safely be modified outside any lock. + */ private void registerCache() { - synchronized (sCorkLock) { - sCaches.put(this, null); + synchronized (sGlobalLock) { if (sDisabledKeys.contains(mCacheName)) { disableInstance(); } + sCaches.put(this, null); } } @@ -797,8 +817,9 @@ public class PropertyInvalidatedCache<Query, Result> { } /** - * Disable the use of this cache in this process. This method is using during - * testing. To disable a cache in normal code, use disableLocal(). + * Disable the use of this cache in this process. This method is using internally and during + * testing. To disable a cache in normal code, use disableLocal(). A disabled cache cannot + * be re-enabled. * @hide */ @TestApi @@ -811,17 +832,23 @@ public class PropertyInvalidatedCache<Query, Result> { /** * Disable the local use of all caches with the same name. All currently registered caches - * using the key will be disabled now, and all future cache instances that use the key will be - * disabled in their constructor. + * with the name will be disabled now, and all future cache instances that use the name will + * be disabled in their constructor. */ private static final void disableLocal(@NonNull String name) { - synchronized (sCorkLock) { - sDisabledKeys.add(name); + synchronized (sGlobalLock) { + if (sDisabledKeys.contains(name)) { + // The key is already in recorded so there is no further work to be done. + return; + } for (PropertyInvalidatedCache cache : sCaches.keySet()) { if (name.equals(cache.mCacheName)) { cache.disableInstance(); } } + // Record the disabled key after the iteration. If an exception occurs during the + // iteration above, and the code is retried, the function should not exit early. + sDisabledKeys.add(name); } } @@ -834,7 +861,7 @@ public class PropertyInvalidatedCache<Query, Result> { */ @TestApi public final void forgetDisableLocal() { - synchronized (sCorkLock) { + synchronized (sGlobalLock) { sDisabledKeys.remove(mCacheName); } } @@ -851,9 +878,9 @@ public class PropertyInvalidatedCache<Query, Result> { } /** - * Disable this cache in the current process, and all other caches that use the same - * name. This does not affect caches that have a different name but use the same - * property. + * Disable this cache in the current process, and all other present and future caches that use + * the same name. This does not affect caches that have a different name but use the same + * property. Once disabled, a cache cannot be reenabled. * @hide */ @TestApi @@ -1381,10 +1408,9 @@ public class PropertyInvalidatedCache<Query, Result> { /** * Returns a list of caches alive at the current time. */ + @GuardedBy("sGlobalLock") private static @NonNull ArrayList<PropertyInvalidatedCache> getActiveCaches() { - synchronized (sCorkLock) { - return new ArrayList<PropertyInvalidatedCache>(sCaches.keySet()); - } + return new ArrayList<PropertyInvalidatedCache>(sCaches.keySet()); } /** @@ -1540,7 +1566,7 @@ public class PropertyInvalidatedCache<Query, Result> { boolean detail = anyDetailed(args); ArrayList<PropertyInvalidatedCache> activeCaches; - synchronized (sCorkLock) { + synchronized (sGlobalLock) { activeCaches = getActiveCaches(); if (!detail) { dumpCorkInfo(pw); diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java index a90f6d625c51..f224f8a189f1 100644 --- a/core/java/android/content/pm/PackageManager.java +++ b/core/java/android/content/pm/PackageManager.java @@ -8065,7 +8065,7 @@ public abstract class PackageManager { } PackageParser.Package pkg = parser.parsePackage(apkFile, 0, false); - if ((flagsBits & GET_SIGNATURES) != 0) { + if ((flagsBits & GET_SIGNATURES) != 0 || (flagsBits & GET_SIGNING_CERTIFICATES) != 0) { PackageParser.collectCertificates(pkg, false /* skipVerify */); } return PackageParser.generatePackageInfo(pkg, null, (int) flagsBits, 0, 0, null, diff --git a/core/java/android/ddm/DdmHandleViewDebug.java b/core/java/android/ddm/DdmHandleViewDebug.java index 6b0f78f2c1c3..0f66fcbdbec9 100644 --- a/core/java/android/ddm/DdmHandleViewDebug.java +++ b/core/java/android/ddm/DdmHandleViewDebug.java @@ -16,12 +16,16 @@ package android.ddm; +import static com.android.internal.util.Preconditions.checkArgument; + import android.util.Log; import android.view.View; import android.view.ViewDebug; import android.view.ViewRootImpl; import android.view.WindowManagerGlobal; +import com.android.internal.annotations.VisibleForTesting; + import org.apache.harmony.dalvik.ddmc.Chunk; import org.apache.harmony.dalvik.ddmc.ChunkHandler; import org.apache.harmony.dalvik.ddmc.DdmServer; @@ -34,6 +38,7 @@ import java.io.OutputStreamWriter; import java.lang.reflect.Method; import java.nio.BufferUnderflowException; import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; /** * Handle various requests related to profiling / debugging of the view system. @@ -123,14 +128,15 @@ public class DdmHandleViewDebug extends DdmHandle { } if (type == CHUNK_VURT) { - if (op == VURT_DUMP_HIERARCHY) + if (op == VURT_DUMP_HIERARCHY) { return dumpHierarchy(rootView, in); - else if (op == VURT_CAPTURE_LAYERS) + } else if (op == VURT_CAPTURE_LAYERS) { return captureLayers(rootView); - else if (op == VURT_DUMP_THEME) + } else if (op == VURT_DUMP_THEME) { return dumpTheme(rootView); - else + } else { return createFailChunk(ERR_INVALID_OP, "Unknown view root operation: " + op); + } } final View targetView = getTargetView(rootView, in); @@ -207,9 +213,9 @@ public class DdmHandleViewDebug extends DdmHandle { /** * Returns the view hierarchy and/or view properties starting at the provided view. * Based on the input options, the return data may include: - * - just the view hierarchy - * - view hierarchy & the properties for each of the views - * - just the view properties for a specific view. + * - just the view hierarchy + * - view hierarchy & the properties for each of the views + * - just the view properties for a specific view. * TODO: Currently this only returns views starting at the root, need to fix so that * it can return properties of any view. */ @@ -220,7 +226,7 @@ public class DdmHandleViewDebug extends DdmHandle { long start = System.currentTimeMillis(); - ByteArrayOutputStream b = new ByteArrayOutputStream(2*1024*1024); + ByteArrayOutputStream b = new ByteArrayOutputStream(2 * 1024 * 1024); try { if (v2) { ViewDebug.dumpv2(rootView, b); @@ -304,17 +310,47 @@ public class DdmHandleViewDebug extends DdmHandle { * Invokes provided method on the view. * The method name and its arguments are passed in as inputs via the byte buffer. * The buffer contains:<ol> - * <li> len(method name) </li> - * <li> method name </li> - * <li> # of args </li> - * <li> arguments: Each argument comprises of a type specifier followed by the actual argument. - * The type specifier is a single character as used in JNI: - * (Z - boolean, B - byte, C - char, S - short, I - int, J - long, - * F - float, D - double). <p> - * The type specifier is followed by the actual value of argument. - * Booleans are encoded via bytes with 0 indicating false.</li> + * <li> len(method name) </li> + * <li> method name (encoded as UTF-16 2-byte characters) </li> + * <li> # of args </li> + * <li> arguments: Each argument comprises of a type specifier followed by the actual argument. + * The type specifier is one character modelled after JNI signatures: + * <ul> + * <li>[ - array<br> + * This is followed by a second character according to this spec, indicating the + * array type, then the array length as an Int, followed by a repeated encoding + * of the actual data. + * WARNING: Only <b>byte[]</b> is supported currently. + * </li> + * <li>Z - boolean<br> + * Booleans are encoded via bytes with 0 indicating false</li> + * <li>B - byte</li> + * <li>C - char</li> + * <li>S - short</li> + * <li>I - int</li> + * <li>J - long</li> + * <li>F - float</li> + * <li>D - double</li> + * <li>V - void<br> + * NOT followed by a value. Only used for return types</li> + * <li>R - String (not a real JNI type, but added for convenience)<br> + * Strings are encoded as an unsigned short of the number of <b>bytes</b>, + * followed by the actual UTF-8 encoded bytes. + * WARNING: This is the same encoding as produced by + * ViewHierarchyEncoder#writeString. However, note that this encoding is + * different to what DdmHandle#getString() expects, which is used in other places + * in this class. + * WARNING: Since the length is the number of UTF-8 encoded bytes, Strings can + * contain up to 64k ASCII characters, yet depending on the actual data, the true + * maximum might be as little as 21844 unicode characters. + * <b>null</b> String objects are encoded as an empty string + * </li> + * </ul> + * </li> * </ol> * Methods that take no arguments need only specify the method name. + * + * The return value is encoded the same way as a single parameter (type + value) */ private Chunk invokeViewMethod(final View rootView, final View targetView, ByteBuffer in) { int l = in.getInt(); @@ -327,54 +363,17 @@ public class DdmHandleViewDebug extends DdmHandle { args = new Object[0]; } else { int nArgs = in.getInt(); - argTypes = new Class<?>[nArgs]; args = new Object[nArgs]; - for (int i = 0; i < nArgs; i++) { - char c = in.getChar(); - switch (c) { - case 'Z': - argTypes[i] = boolean.class; - args[i] = in.get() == 0 ? false : true; - break; - case 'B': - argTypes[i] = byte.class; - args[i] = in.get(); - break; - case 'C': - argTypes[i] = char.class; - args[i] = in.getChar(); - break; - case 'S': - argTypes[i] = short.class; - args[i] = in.getShort(); - break; - case 'I': - argTypes[i] = int.class; - args[i] = in.getInt(); - break; - case 'J': - argTypes[i] = long.class; - args[i] = in.getLong(); - break; - case 'F': - argTypes[i] = float.class; - args[i] = in.getFloat(); - break; - case 'D': - argTypes[i] = double.class; - args[i] = in.getDouble(); - break; - default: - Log.e(TAG, "arg " + i + ", unrecognized type: " + c); - return createFailChunk(ERR_INVALID_PARAM, - "Unsupported parameter type (" + c + ") to invoke view method."); - } + try { + deserializeMethodParameters(args, argTypes, in); + } catch (ViewMethodInvocationSerializationException e) { + return createFailChunk(ERR_INVALID_PARAM, e.getMessage()); } } - Method method = null; + Method method; try { method = targetView.getClass().getMethod(methodName, argTypes); } catch (NoSuchMethodException e) { @@ -384,7 +383,10 @@ public class DdmHandleViewDebug extends DdmHandle { } try { - ViewDebug.invokeViewMethod(targetView, method, args); + Object result = ViewDebug.invokeViewMethod(targetView, method, args); + Class<?> returnType = method.getReturnType(); + byte[] returnValue = serializeReturnValue(returnType, returnType.cast(result)); + return new Chunk(CHUNK_VUOP, returnValue, 0, returnValue.length); } catch (Exception e) { Log.e(TAG, "Exception while invoking method: " + e.getCause().getMessage()); String msg = e.getCause().getMessage(); @@ -393,8 +395,6 @@ public class DdmHandleViewDebug extends DdmHandle { } return createFailChunk(ERR_EXCEPTION, msg); } - - return null; } private Chunk setLayoutParameter(final View rootView, final View targetView, ByteBuffer in) { @@ -406,7 +406,7 @@ public class DdmHandleViewDebug extends DdmHandle { } catch (Exception e) { Log.e(TAG, "Exception setting layout parameter: " + e); return createFailChunk(ERR_EXCEPTION, "Error accessing field " - + param + ":" + e.getMessage()); + + param + ":" + e.getMessage()); } return null; @@ -431,4 +431,175 @@ public class DdmHandleViewDebug extends DdmHandle { byte[] data = b.toByteArray(); return new Chunk(CHUNK_VUOP, data, 0, data.length); } + + /** + * Deserializes parameters according to the VUOP_INVOKE_VIEW_METHOD protocol the {@code in} + * buffer. + * + * The length of {@code args} determines how many arguments are read. The {@code argTypes} must + * be the same length, and will be set to the argument types of the data read. + * + * @hide + */ + @VisibleForTesting + public static void deserializeMethodParameters( + Object[] args, Class<?>[] argTypes, ByteBuffer in) throws + ViewMethodInvocationSerializationException { + checkArgument(args.length == argTypes.length); + + for (int i = 0; i < args.length; i++) { + char typeSignature = in.getChar(); + boolean isArray = typeSignature == SIG_ARRAY; + if (isArray) { + char arrayType = in.getChar(); + if (arrayType != SIG_BYTE) { + // This implementation only supports byte-arrays for now. + throw new ViewMethodInvocationSerializationException( + "Unsupported array parameter type (" + typeSignature + + ") to invoke view method @argument " + i); + } + + int arrayLength = in.getInt(); + if (arrayLength > in.remaining()) { + // The sender did not actually sent the specified amount of bytes. This + // avoids a malformed packet to trigger an out-of-memory error. + throw new BufferUnderflowException(); + } + + byte[] byteArray = new byte[arrayLength]; + in.get(byteArray); + + argTypes[i] = byte[].class; + args[i] = byteArray; + } else { + switch (typeSignature) { + case SIG_BOOLEAN: + argTypes[i] = boolean.class; + args[i] = in.get() != 0; + break; + case SIG_BYTE: + argTypes[i] = byte.class; + args[i] = in.get(); + break; + case SIG_CHAR: + argTypes[i] = char.class; + args[i] = in.getChar(); + break; + case SIG_SHORT: + argTypes[i] = short.class; + args[i] = in.getShort(); + break; + case SIG_INT: + argTypes[i] = int.class; + args[i] = in.getInt(); + break; + case SIG_LONG: + argTypes[i] = long.class; + args[i] = in.getLong(); + break; + case SIG_FLOAT: + argTypes[i] = float.class; + args[i] = in.getFloat(); + break; + case SIG_DOUBLE: + argTypes[i] = double.class; + args[i] = in.getDouble(); + break; + case SIG_STRING: { + argTypes[i] = String.class; + int stringUtf8ByteCount = Short.toUnsignedInt(in.getShort()); + byte[] rawStringBuffer = new byte[stringUtf8ByteCount]; + in.get(rawStringBuffer); + args[i] = new String(rawStringBuffer, StandardCharsets.UTF_8); + break; + } + default: + Log.e(TAG, "arg " + i + ", unrecognized type: " + typeSignature); + throw new ViewMethodInvocationSerializationException( + "Unsupported parameter type (" + typeSignature + + ") to invoke view method."); + } + } + + } + } + + /** + * Serializes {@code value} to the wire protocol of VUOP_INVOKE_VIEW_METHOD. + * @hide + */ + @VisibleForTesting + public static byte[] serializeReturnValue(Class<?> type, Object value) + throws ViewMethodInvocationSerializationException, IOException { + ByteArrayOutputStream byteOutStream = new ByteArrayOutputStream(1024); + DataOutputStream dos = new DataOutputStream(byteOutStream); + + if (type.isArray()) { + if (!type.equals(byte[].class)) { + // Only byte arrays are supported currently. + throw new ViewMethodInvocationSerializationException( + "Unsupported array return type (" + type + ")"); + } + byte[] byteArray = (byte[]) value; + dos.writeChar(SIG_ARRAY); + dos.writeChar(SIG_BYTE); + dos.writeInt(byteArray.length); + dos.write(byteArray); + } else if (boolean.class.equals(type)) { + dos.writeChar(SIG_BOOLEAN); + dos.write((boolean) value ? 1 : 0); + } else if (byte.class.equals(type)) { + dos.writeChar(SIG_BYTE); + dos.writeByte((byte) value); + } else if (char.class.equals(type)) { + dos.writeChar(SIG_CHAR); + dos.writeChar((char) value); + } else if (short.class.equals(type)) { + dos.writeChar(SIG_SHORT); + dos.writeShort((short) value); + } else if (int.class.equals(type)) { + dos.writeChar(SIG_INT); + dos.writeInt((int) value); + } else if (long.class.equals(type)) { + dos.writeChar(SIG_LONG); + dos.writeLong((long) value); + } else if (double.class.equals(type)) { + dos.writeChar(SIG_DOUBLE); + dos.writeDouble((double) value); + } else if (float.class.equals(type)) { + dos.writeChar(SIG_FLOAT); + dos.writeFloat((float) value); + } else if (String.class.equals(type)) { + dos.writeChar(SIG_STRING); + dos.writeUTF(value != null ? (String) value : ""); + } else { + dos.writeChar(SIG_VOID); + } + + return byteOutStream.toByteArray(); + } + + // Prefixes for simple primitives. These match the JNI definitions. + private static final char SIG_ARRAY = '['; + private static final char SIG_BOOLEAN = 'Z'; + private static final char SIG_BYTE = 'B'; + private static final char SIG_SHORT = 'S'; + private static final char SIG_CHAR = 'C'; + private static final char SIG_INT = 'I'; + private static final char SIG_LONG = 'J'; + private static final char SIG_FLOAT = 'F'; + private static final char SIG_DOUBLE = 'D'; + private static final char SIG_VOID = 'V'; + // Prefixes for some commonly used objects + private static final char SIG_STRING = 'R'; + + /** + * @hide + */ + @VisibleForTesting + public static class ViewMethodInvocationSerializationException extends Exception { + ViewMethodInvocationSerializationException(String message) { + super(message); + } + } } diff --git a/core/java/android/ddm/OWNERS b/core/java/android/ddm/OWNERS new file mode 100644 index 000000000000..369025bd21f4 --- /dev/null +++ b/core/java/android/ddm/OWNERS @@ -0,0 +1 @@ +per-file DdmHandleViewDebug.java = michschn@google.com diff --git a/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java b/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java index 98f571b80949..c59d7571ee6d 100644 --- a/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java +++ b/core/java/android/hardware/biometrics/BiometricFingerprintConstants.java @@ -217,7 +217,8 @@ public interface BiometricFingerprintConstants { FINGERPRINT_ACQUIRED_START, FINGERPRINT_ACQUIRED_UNKNOWN, FINGERPRINT_ACQUIRED_IMMOBILE, - FINGERPRINT_ACQUIRED_TOO_BRIGHT}) + FINGERPRINT_ACQUIRED_TOO_BRIGHT, + FINGERPRINT_ACQUIRED_POWER_PRESSED}) @Retention(RetentionPolicy.SOURCE) @interface FingerprintAcquired {} @@ -302,6 +303,13 @@ public interface BiometricFingerprintConstants { int FINGERPRINT_ACQUIRED_TOO_BRIGHT = 10; /** + * For sensors that have the power button co-located with their sensor, this event will + * be sent during enrollment. + * @hide + */ + int FINGERPRINT_ACQUIRED_POWER_PRESSED = 11; + + /** * @hide */ int FINGERPRINT_ACQUIRED_VENDOR_BASE = 1000; diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java index 72d812269374..0fd164de8ffb 100644 --- a/core/java/android/hardware/fingerprint/FingerprintManager.java +++ b/core/java/android/hardware/fingerprint/FingerprintManager.java @@ -1538,6 +1538,9 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing case FINGERPRINT_ACQUIRED_TOO_BRIGHT: return context.getString( com.android.internal.R.string.fingerprint_acquired_too_bright); + case FINGERPRINT_ACQUIRED_POWER_PRESSED: + return context.getString( + com.android.internal.R.string.fingerprint_acquired_power_press); case FINGERPRINT_ACQUIRED_VENDOR: { String[] msgArray = context.getResources().getStringArray( com.android.internal.R.array.fingerprint_acquired_vendor); diff --git a/core/java/android/os/PackageTagsList.java b/core/java/android/os/PackageTagsList.java index 4a81dc6f592e..df99074a851f 100644 --- a/core/java/android/os/PackageTagsList.java +++ b/core/java/android/os/PackageTagsList.java @@ -26,6 +26,7 @@ import android.util.ArraySet; import com.android.internal.annotations.Immutable; import java.io.PrintWriter; +import java.util.ArrayList; import java.util.Collection; import java.util.Map; import java.util.Objects; @@ -140,6 +141,17 @@ public final class PackageTagsList implements Parcelable { return true; } + /** + * Returns a list of packages. + * + * @deprecated Do not use. + * @hide + */ + @Deprecated + public @NonNull Collection<String> getPackages() { + return new ArrayList<>(mPackageTags.keySet()); + } + public static final @NonNull Parcelable.Creator<PackageTagsList> CREATOR = new Parcelable.Creator<PackageTagsList>() { @SuppressWarnings("unchecked") @@ -217,7 +229,7 @@ public final class PackageTagsList implements Parcelable { if (j > 0) { pw.print(", "); } - if (attributionTag.startsWith(packageName)) { + if (attributionTag != null && attributionTag.startsWith(packageName)) { pw.print(attributionTag.substring(packageName.length())); } else { pw.print(attributionTag); diff --git a/core/java/android/os/VibrationEffect.java b/core/java/android/os/VibrationEffect.java index ec1c57d675c1..f7d4be3960f8 100644 --- a/core/java/android/os/VibrationEffect.java +++ b/core/java/android/os/VibrationEffect.java @@ -830,29 +830,8 @@ public abstract class VibrationEffect implements Parcelable { * .addPrimitive(VibrationEffect.Composition.PRIMITIVE_TICK, 1.0f, 100) * .compose();}</pre> * - * <p>Composition elements can also be {@link VibrationEffect} instances, including other - * compositions, and off durations, which are periods of time when the vibrator will be - * turned off. Here is an example of a composition that "warms up" with a light tap, - * a stronger double tap, then repeats a vibration pattern indefinitely: - * - * <pre> - * {@code VibrationEffect repeatingEffect = VibrationEffect.startComposition() - * .addPrimitive(VibrationEffect.Composition.PRIMITIVE_LOW_TICK) - * .addOffDuration(Duration.ofMillis(10)) - * .addEffect(VibrationEffect.createPredefined(VibrationEffect.EFFECT_DOUBLE_CLICK)) - * .addOffDuration(Duration.ofMillis(50)) - * .addEffect(VibrationEffect.createWaveform(pattern, repeatIndex)) - * .compose();}</pre> - * * <p>When choosing to play a composed effect, you should check that individual components are - * supported by the device by using the appropriate vibrator method: - * - * <ul> - * <li>Primitive support can be checked using {@link Vibrator#arePrimitivesSupported}. - * <li>Effect support can be checked using {@link Vibrator#areEffectsSupported}. - * <li>Amplitude control for one-shot and waveforms with amplitude values can be checked - * using {@link Vibrator#hasAmplitudeControl}. - * </ul> + * supported by the device by using {@link Vibrator#arePrimitivesSupported}. * * @see VibrationEffect#startComposition() */ @@ -1021,9 +1000,6 @@ public abstract class VibrationEffect implements Parcelable { * * @param primitiveId The primitive to add * @return This {@link Composition} object to enable adding multiple elements in one chain. - * - * @throws UnreachableAfterRepeatingIndefinitelyException if the composition is currently - * ending with a repeating effect. */ @NonNull public Composition addPrimitive(@PrimitiveType int primitiveId) { @@ -1038,9 +1014,6 @@ public abstract class VibrationEffect implements Parcelable { * @param primitiveId The primitive to add * @param scale The scale to apply to the intensity of the primitive. * @return This {@link Composition} object to enable adding multiple elements in one chain. - * - * @throws UnreachableAfterRepeatingIndefinitelyException if the composition is currently - * ending with a repeating effect. */ @NonNull public Composition addPrimitive(@PrimitiveType int primitiveId, @@ -1056,9 +1029,6 @@ public abstract class VibrationEffect implements Parcelable { * @param delay The amount of time in milliseconds to wait before playing this primitive, * starting at the time the previous element in this composition is finished. * @return This {@link Composition} object to enable adding multiple elements in one chain. - * - * @throws UnreachableAfterRepeatingIndefinitelyException if the composition is currently - * ending with a repeating effect. */ @NonNull public Composition addPrimitive(@PrimitiveType int primitiveId, diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 1fcdd608c5a2..b964e1c326a4 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -6660,6 +6660,26 @@ public final class Settings { public static final String BLUETOOTH_ADDR_VALID = "bluetooth_addr_valid"; /** + * This is used by LocalBluetoothLeBroadcast to store the broadcast program info. + * @hide + */ + public static final String BLUETOOTH_LE_BROADCAST_PROGRAM_INFO = + "bluetooth_le_broadcast_program_info"; + + /** + * This is used by LocalBluetoothLeBroadcast to store the broadcast code. + * @hide + */ + public static final String BLUETOOTH_LE_BROADCAST_CODE = "bluetooth_le_broadcast_code"; + + /** + * This is used by LocalBluetoothLeBroadcast to store the app source name. + * @hide + */ + public static final String BLUETOOTH_LE_BROADCAST_APP_SOURCE_NAME = + "bluetooth_le_broadcast_app_source_name"; + + /** * Setting to indicate that on device captions are enabled. * * @hide diff --git a/core/java/android/service/notification/Condition.java b/core/java/android/service/notification/Condition.java index 267b2ff818a6..4d33bfd1e94a 100644 --- a/core/java/android/service/notification/Condition.java +++ b/core/java/android/service/notification/Condition.java @@ -91,6 +91,12 @@ public final class Condition implements Parcelable { public final int icon; /** + * The maximum string length for any string contained in this condition. + * @hide + */ + public static final int MAX_STRING_LENGTH = 1000; + + /** * An object representing the current state of a {@link android.app.AutomaticZenRule}. * @param id the {@link android.app.AutomaticZenRule#getConditionId()} of the zen rule * @param summary a user visible description of the rule state. @@ -104,16 +110,19 @@ public final class Condition implements Parcelable { if (id == null) throw new IllegalArgumentException("id is required"); if (summary == null) throw new IllegalArgumentException("summary is required"); if (!isValidState(state)) throw new IllegalArgumentException("state is invalid: " + state); - this.id = id; - this.summary = summary; - this.line1 = line1; - this.line2 = line2; + this.id = getTrimmedUri(id); + this.summary = getTrimmedString(summary); + this.line1 = getTrimmedString(line1); + this.line2 = getTrimmedString(line2); this.icon = icon; this.state = state; this.flags = flags; } public Condition(Parcel source) { + // This constructor passes all fields directly into the constructor that takes all the + // fields as arguments; that constructor will trim each of the input strings to + // max length if necessary. this((Uri)source.readParcelable(Condition.class.getClassLoader(), android.net.Uri.class), source.readString(), source.readString(), @@ -240,4 +249,25 @@ public final class Condition implements Parcelable { return new Condition[size]; } }; + + /** + * Returns a truncated copy of the string if the string is longer than MAX_STRING_LENGTH. + */ + private static String getTrimmedString(String input) { + if (input != null && input.length() > MAX_STRING_LENGTH) { + return input.substring(0, MAX_STRING_LENGTH); + } + return input; + } + + /** + * Returns a truncated copy of the Uri by trimming the string representation to the maximum + * string length. + */ + private static Uri getTrimmedUri(Uri input) { + if (input != null && input.toString().length() > MAX_STRING_LENGTH) { + return Uri.parse(getTrimmedString(input.toString())); + } + return input; + } } diff --git a/core/java/android/service/trust/TrustAgentService.java b/core/java/android/service/trust/TrustAgentService.java index 559313a30dfa..41345e0154ee 100644 --- a/core/java/android/service/trust/TrustAgentService.java +++ b/core/java/android/service/trust/TrustAgentService.java @@ -141,7 +141,9 @@ public class TrustAgentService extends Service { * * Without this flag, the message passed to {@code grantTrust} is only used for debugging * purposes. With the flag, it may be displayed to the user as the reason why the device is - * unlocked. + * unlocked. If this flag isn't set OR the message is set to null, the device will display + * its own default message for trust granted. If the TrustAgent intentionally doesn't want to + * show any message, then it can set this flag AND set the message to an empty string. */ public static final int FLAG_GRANT_TRUST_DISPLAY_MESSAGE = 1 << 3; diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java index 14cfe6a6efab..01749c0bebb9 100644 --- a/core/java/android/service/wallpaper/WallpaperService.java +++ b/core/java/android/service/wallpaper/WallpaperService.java @@ -519,7 +519,7 @@ public abstract class WallpaperService extends Service { * {@link #addLocalColorsAreas(List)} * {@link #removeLocalColorsAreas(List)} * When local colors change, call {@link #notifyLocalColorsChanged(List, List)} - * See {@link com.android.systemui.ImageWallpaper} for an example + * See {@link com.android.systemui.wallpapers.ImageWallpaper} for an example * @hide */ public boolean supportsLocalColorExtraction() { diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index ba6ba63e4ed0..b0d465769deb 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -12709,7 +12709,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, if (mViewTranslationCallback != null) { mViewTranslationCallback.onClearTranslation(this); } - clearViewTranslationCallback(); clearViewTranslationResponse(); if (hasTranslationTransientState()) { setHasTransientState(false); diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index ec6b4acd6aff..e4caa385bc9b 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -3064,7 +3064,8 @@ public final class ViewRootImpl implements ViewParent, // WindowManagerService has reported back a frame from a configuration not yet // handled by the client. In this case, we need to accept the configuration so we // do not lay out and draw with the wrong configuration. - if (!mPendingMergedConfiguration.equals(mLastReportedMergedConfiguration)) { + if (mRelayoutRequested + && !mPendingMergedConfiguration.equals(mLastReportedMergedConfiguration)) { if (DEBUG_CONFIGURATION) Log.v(mTag, "Visible with new config: " + mPendingMergedConfiguration.getMergedConfiguration()); performConfigurationChange(new MergedConfiguration(mPendingMergedConfiguration), @@ -8085,7 +8086,8 @@ public final class ViewRootImpl implements ViewParent, final int measuredWidth = mView.getMeasuredWidth(); final int measuredHeight = mView.getMeasuredHeight(); final boolean relayoutAsync; - if (LOCAL_LAYOUT && !mFirst && viewVisibility == mViewVisibility + if (LOCAL_LAYOUT + && (mViewFrameInfo.flags & FrameInfo.FLAG_WINDOW_VISIBILITY_CHANGED) == 0 && mWindowAttributes.type != TYPE_APPLICATION_STARTING && mSyncSeqId <= mLastSyncSeqId && winConfigFromAm.diff(winConfigFromWm, false /* compareUndefined */) == 0) { diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java index 2195b83933a5..218ca58dee54 100644 --- a/core/java/android/view/WindowManager.java +++ b/core/java/android/view/WindowManager.java @@ -285,12 +285,18 @@ public interface WindowManager extends ViewManager { int TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER = 21; /** - * Keyguard is being occluded. + * Keyguard is being occluded by non-Dream. * @hide */ int TRANSIT_OLD_KEYGUARD_OCCLUDE = 22; /** + * Keyguard is being occluded by Dream. + * @hide + */ + int TRANSIT_OLD_KEYGUARD_OCCLUDE_BY_DREAM = 33; + + /** * Keyguard is being unoccluded. * @hide */ diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java index 285a40779b90..fadad99f0885 100644 --- a/core/java/android/widget/Editor.java +++ b/core/java/android/widget/Editor.java @@ -709,7 +709,7 @@ public class Editor { } getPositionListener().addSubscriber(mCursorAnchorInfoNotifier, true); - resumeBlink(); + makeBlink(); } void onDetachedFromWindow() { @@ -1685,17 +1685,12 @@ public class Editor { void onWindowFocusChanged(boolean hasWindowFocus) { if (hasWindowFocus) { - if (mBlink != null) { - mBlink.uncancel(); - makeBlink(); - } + resumeBlink(); if (mTextView.hasSelection() && !extractedTextModeWillBeStarted()) { refreshTextActionMode(); } } else { - if (mBlink != null) { - mBlink.cancel(); - } + suspendBlink(); if (mInputContentType != null) { mInputContentType.enterDown = false; } @@ -2851,7 +2846,8 @@ public class Editor { * @return True when the TextView isFocused and has a valid zero-length selection (cursor). */ private boolean shouldBlink() { - if (!isCursorVisible() || !mTextView.isFocused()) return false; + if (!isCursorVisible() || !mTextView.isFocused() + || mTextView.getWindowVisibility() != mTextView.VISIBLE) return false; final int start = mTextView.getSelectionStart(); if (start < 0) return false; @@ -2873,6 +2869,17 @@ public class Editor { } } + /** + * + * @return whether the Blink runnable is blinking or not, if null return false. + * @hide + */ + @VisibleForTesting + public boolean isBlinking() { + if (mBlink == null) return false; + return !mBlink.mCancelled; + } + private class Blink implements Runnable { private boolean mCancelled; diff --git a/core/java/android/window/TaskFragmentOrganizer.java b/core/java/android/window/TaskFragmentOrganizer.java index 649785a80f43..648541bf62c7 100644 --- a/core/java/android/window/TaskFragmentOrganizer.java +++ b/core/java/android/window/TaskFragmentOrganizer.java @@ -35,7 +35,6 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.TestApi; import android.app.WindowConfiguration; -import android.content.Intent; import android.content.res.Configuration; import android.os.Bundle; import android.os.IBinder; @@ -203,7 +202,7 @@ public class TaskFragmentOrganizer extends WindowOrganizer { * Routes to {@link ITaskFragmentOrganizerController#applyTransaction} instead of * {@link IWindowOrganizerController#applyTransaction} for the different transition options. * - * @see #applyTransaction(WindowContainerTransaction, int, boolean, boolean) + * @see #applyTransaction(WindowContainerTransaction, int, boolean) */ @Override public void applyTransaction(@NonNull WindowContainerTransaction wct) { @@ -285,72 +284,30 @@ public class TaskFragmentOrganizer extends WindowOrganizer { * Called when a TaskFragment is created and organized by this organizer. * * @param taskFragmentInfo Info of the TaskFragment that is created. - * @deprecated Use {@link #onTaskFragmentAppeared(WindowContainerTransaction, TaskFragmentInfo)} - * instead. + * @deprecated Use {@link #onTransactionReady(TaskFragmentTransaction)} instead. */ @Deprecated public void onTaskFragmentAppeared(@NonNull TaskFragmentInfo taskFragmentInfo) {} /** - * Called when a TaskFragment is created and organized by this organizer. - * - * @param wct The {@link WindowContainerTransaction} to make any changes with if needed. No - * need to call {@link #applyTransaction} as it will be applied by the caller. - * @param taskFragmentInfo Info of the TaskFragment that is created. - */ - public void onTaskFragmentAppeared(@NonNull WindowContainerTransaction wct, - @NonNull TaskFragmentInfo taskFragmentInfo) { - // TODO(b/240519866): doing so to keep CTS compatibility. Remove in the next release. - onTaskFragmentAppeared(taskFragmentInfo); - } - - /** * Called when the status of an organized TaskFragment is changed. * * @param taskFragmentInfo Info of the TaskFragment that is changed. - * @deprecated Use {@link #onTaskFragmentInfoChanged(WindowContainerTransaction, - * TaskFragmentInfo)} instead. + * @deprecated Use {@link #onTransactionReady(TaskFragmentTransaction)} instead. */ @Deprecated public void onTaskFragmentInfoChanged(@NonNull TaskFragmentInfo taskFragmentInfo) {} /** - * Called when the status of an organized TaskFragment is changed. - * - * @param wct The {@link WindowContainerTransaction} to make any changes with if needed. No - * need to call {@link #applyTransaction} as it will be applied by the caller. - * @param taskFragmentInfo Info of the TaskFragment that is changed. - */ - public void onTaskFragmentInfoChanged(@NonNull WindowContainerTransaction wct, - @NonNull TaskFragmentInfo taskFragmentInfo) { - // TODO(b/240519866): doing so to keep CTS compatibility. Remove in the next release. - onTaskFragmentInfoChanged(taskFragmentInfo); - } - - /** * Called when an organized TaskFragment is removed. * * @param taskFragmentInfo Info of the TaskFragment that is removed. - * @deprecated Use {@link #onTaskFragmentVanished(WindowContainerTransaction, - * TaskFragmentInfo)} instead. + * @deprecated Use {@link #onTransactionReady(TaskFragmentTransaction)} instead. */ @Deprecated public void onTaskFragmentVanished(@NonNull TaskFragmentInfo taskFragmentInfo) {} /** - * Called when an organized TaskFragment is removed. - * - * @param wct The {@link WindowContainerTransaction} to make any changes with if needed. No - * need to call {@link #applyTransaction} as it will be applied by the caller. - * @param taskFragmentInfo Info of the TaskFragment that is removed. - */ - public void onTaskFragmentVanished(@NonNull WindowContainerTransaction wct, - @NonNull TaskFragmentInfo taskFragmentInfo) { - // TODO(b/240519866): doing so to keep CTS compatibility. Remove in the next release. - onTaskFragmentVanished(taskFragmentInfo); - } - - /** * Called when the parent leaf Task of organized TaskFragments is changed. * When the leaf Task is changed, the organizer may want to update the TaskFragments in one * transaction. @@ -361,94 +318,26 @@ public class TaskFragmentOrganizer extends WindowOrganizer { * * @param fragmentToken The parent Task this TaskFragment is changed. * @param parentConfig Config of the parent Task. - * @deprecated Use {@link #onTaskFragmentParentInfoChanged(WindowContainerTransaction, int, - * Configuration)} instead. + * @deprecated Use {@link #onTransactionReady(TaskFragmentTransaction)} instead. */ @Deprecated public void onTaskFragmentParentInfoChanged( @NonNull IBinder fragmentToken, @NonNull Configuration parentConfig) {} /** - * Called when the parent leaf Task of organized TaskFragments is changed. - * When the leaf Task is changed, the organizer may want to update the TaskFragments in one - * transaction. - * - * For case like screen size change, it will trigger onTaskFragmentParentInfoChanged with new - * Task bounds, but may not trigger onTaskFragmentInfoChanged because there can be an override - * bounds. - * - * @param wct The {@link WindowContainerTransaction} to make any changes with if needed. No - * need to call {@link #applyTransaction} as it will be applied by the caller. - * @param taskId Id of the parent Task that is changed. - * @param parentConfig Config of the parent Task. - */ - public void onTaskFragmentParentInfoChanged(@NonNull WindowContainerTransaction wct, int taskId, - @NonNull Configuration parentConfig) { - // TODO(b/240519866): doing so to keep CTS compatibility. Remove in the next release. - final List<IBinder> tokens = mTaskIdToFragmentTokens.get(taskId); - if (tokens == null || tokens.isEmpty()) { - return; - } - for (int i = tokens.size() - 1; i >= 0; i--) { - onTaskFragmentParentInfoChanged(tokens.get(i), parentConfig); - } - } - - /** * Called when the {@link WindowContainerTransaction} created with * {@link WindowContainerTransaction#setErrorCallbackToken(IBinder)} failed on the server side. * * @param errorCallbackToken token set in * {@link WindowContainerTransaction#setErrorCallbackToken(IBinder)} * @param exception exception from the server side. - * @deprecated Use {@link #onTaskFragmentError(WindowContainerTransaction, IBinder, - * TaskFragmentInfo, int, Throwable)} instead. + * @deprecated Use {@link #onTransactionReady(TaskFragmentTransaction)} instead. */ @Deprecated public void onTaskFragmentError( @NonNull IBinder errorCallbackToken, @NonNull Throwable exception) {} /** - * Called when the {@link WindowContainerTransaction} created with - * {@link WindowContainerTransaction#setErrorCallbackToken(IBinder)} failed on the server side. - * - * @param wct The {@link WindowContainerTransaction} to make any changes with if needed. No - * need to call {@link #applyTransaction} as it will be applied by the caller. - * @param errorCallbackToken token set in - * {@link WindowContainerTransaction#setErrorCallbackToken(IBinder)} - * @param taskFragmentInfo The {@link TaskFragmentInfo}. This could be {@code null} if no - * TaskFragment created. - * @param opType The {@link WindowContainerTransaction.HierarchyOp} of the failed - * transaction operation. - * @param exception exception from the server side. - */ - public void onTaskFragmentError(@NonNull WindowContainerTransaction wct, - @NonNull IBinder errorCallbackToken, @Nullable TaskFragmentInfo taskFragmentInfo, - int opType, @NonNull Throwable exception) { - // Doing so to keep compatibility. This will be removed in the next release. - onTaskFragmentError(errorCallbackToken, exception); - } - - /** - * Called when an Activity is reparented to the Task with organized TaskFragment. For example, - * when an Activity enters and then exits Picture-in-picture, it will be reparented back to its - * original Task. In this case, we need to notify the organizer so that it can check if the - * Activity matches any split rule. - * - * @param wct The {@link WindowContainerTransaction} to make any changes with if needed. No - * need to call {@link #applyTransaction} as it will be applied by the caller. - * @param taskId The Task that the activity is reparented to. - * @param activityIntent The intent that the activity is original launched with. - * @param activityToken If the activity belongs to the same process as the organizer, this - * will be the actual activity token; if the activity belongs to a - * different process, the server will generate a temporary token that - * the organizer can use to reparent the activity through - * {@link WindowContainerTransaction} if needed. - */ - public void onActivityReparentedToTask(@NonNull WindowContainerTransaction wct, - int taskId, @NonNull Intent activityIntent, @NonNull IBinder activityToken) {} - - /** * Called when the transaction is ready so that the organizer can update the TaskFragments based * on the changes in transaction. * @hide @@ -463,23 +352,18 @@ public class TaskFragmentOrganizer extends WindowOrganizer { final int taskId = change.getTaskId(); switch (change.getType()) { case TYPE_TASK_FRAGMENT_APPEARED: - // TODO(b/240519866): doing so to keep CTS compatibility. Remove in the next - // release. if (!mTaskIdToFragmentTokens.contains(taskId)) { mTaskIdToFragmentTokens.put(taskId, new ArrayList<>()); } mTaskIdToFragmentTokens.get(taskId).add(change.getTaskFragmentToken()); onTaskFragmentParentInfoChanged(change.getTaskFragmentToken(), mTaskIdToConfigurations.get(taskId)); - - onTaskFragmentAppeared(wct, change.getTaskFragmentInfo()); + onTaskFragmentAppeared(change.getTaskFragmentInfo()); break; case TYPE_TASK_FRAGMENT_INFO_CHANGED: - onTaskFragmentInfoChanged(wct, change.getTaskFragmentInfo()); + onTaskFragmentInfoChanged(change.getTaskFragmentInfo()); break; case TYPE_TASK_FRAGMENT_VANISHED: - // TODO(b/240519866): doing so to keep CTS compatibility. Remove in the next - // release. if (mTaskIdToFragmentTokens.contains(taskId)) { final List<IBinder> tokens = mTaskIdToFragmentTokens.get(taskId); tokens.remove(change.getTaskFragmentToken()); @@ -488,33 +372,30 @@ public class TaskFragmentOrganizer extends WindowOrganizer { mTaskIdToConfigurations.remove(taskId); } } - - onTaskFragmentVanished(wct, change.getTaskFragmentInfo()); + onTaskFragmentVanished(change.getTaskFragmentInfo()); break; case TYPE_TASK_FRAGMENT_PARENT_INFO_CHANGED: - // TODO(b/240519866): doing so to keep CTS compatibility. Remove in the next - // release. - mTaskIdToConfigurations.put(taskId, change.getTaskConfiguration()); - - onTaskFragmentParentInfoChanged(wct, taskId, change.getTaskConfiguration()); + final Configuration parentConfig = change.getTaskConfiguration(); + mTaskIdToConfigurations.put(taskId, parentConfig); + final List<IBinder> tokens = mTaskIdToFragmentTokens.get(taskId); + if (tokens == null || tokens.isEmpty()) { + break; + } + for (int i = tokens.size() - 1; i >= 0; i--) { + onTaskFragmentParentInfoChanged(tokens.get(i), parentConfig); + } break; case TYPE_TASK_FRAGMENT_ERROR: final Bundle errorBundle = change.getErrorBundle(); onTaskFragmentError( - wct, change.getErrorCallbackToken(), - errorBundle.getParcelable( - KEY_ERROR_CALLBACK_TASK_FRAGMENT_INFO, TaskFragmentInfo.class), - errorBundle.getInt(KEY_ERROR_CALLBACK_OP_TYPE), errorBundle.getSerializable(KEY_ERROR_CALLBACK_THROWABLE, java.lang.Throwable.class)); break; case TYPE_ACTIVITY_REPARENTED_TO_TASK: - onActivityReparentedToTask( - wct, - change.getTaskId(), - change.getActivityIntent(), - change.getActivityToken()); + // This is for CTS compat: + // There is no TestApi for CTS to handle this type of change, but we don't want + // it to throw exception as default. This has been updated in next release. break; default: throw new IllegalArgumentException( diff --git a/core/java/android/window/TaskFragmentTransaction.java b/core/java/android/window/TaskFragmentTransaction.java index 84a5fea9f57f..413c0dd77ed6 100644 --- a/core/java/android/window/TaskFragmentTransaction.java +++ b/core/java/android/window/TaskFragmentTransaction.java @@ -21,6 +21,7 @@ import static java.util.Objects.requireNonNull; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.SuppressLint; import android.content.Intent; import android.content.res.Configuration; import android.os.Binder; @@ -63,6 +64,7 @@ public final class TaskFragmentTransaction implements Parcelable { dest.writeTypedList(mChanges); } + @NonNull public IBinder getTransactionToken() { return mTransactionToken; } @@ -105,6 +107,7 @@ public final class TaskFragmentTransaction implements Parcelable { return 0; } + @NonNull public static final Creator<TaskFragmentTransaction> CREATOR = new Creator<>() { @Override public TaskFragmentTransaction createFromParcel(Parcel in) { @@ -218,24 +221,28 @@ public final class TaskFragmentTransaction implements Parcelable { } /** The change is related to the TaskFragment created with this unique token. */ + @NonNull public Change setTaskFragmentToken(@NonNull IBinder taskFragmentToken) { mTaskFragmentToken = requireNonNull(taskFragmentToken); return this; } /** Info of the embedded TaskFragment. */ + @NonNull public Change setTaskFragmentInfo(@NonNull TaskFragmentInfo info) { mTaskFragmentInfo = requireNonNull(info); return this; } /** Task id the parent Task. */ + @NonNull public Change setTaskId(int taskId) { mTaskId = taskId; return this; } /** Configuration of the parent Task. */ + @NonNull public Change setTaskConfiguration(@NonNull Configuration configuration) { mTaskConfiguration = requireNonNull(configuration); return this; @@ -246,6 +253,7 @@ public final class TaskFragmentTransaction implements Parcelable { * from the {@link TaskFragmentOrganizer}, it may come with an error callback token to * report back. */ + @NonNull public Change setErrorCallbackToken(@Nullable IBinder errorCallbackToken) { mErrorCallbackToken = errorCallbackToken; return this; @@ -255,6 +263,7 @@ public final class TaskFragmentTransaction implements Parcelable { * Bundle with necessary info about the failure operation of * {@link #TYPE_TASK_FRAGMENT_ERROR}. */ + @NonNull public Change setErrorBundle(@NonNull Bundle errorBundle) { mErrorBundle = requireNonNull(errorBundle); return this; @@ -264,6 +273,7 @@ public final class TaskFragmentTransaction implements Parcelable { * Intent of the activity that is reparented to the Task for * {@link #TYPE_ACTIVITY_REPARENTED_TO_TASK}. */ + @NonNull public Change setActivityIntent(@NonNull Intent intent) { mActivityIntent = requireNonNull(intent); return this; @@ -276,6 +286,7 @@ public final class TaskFragmentTransaction implements Parcelable { * a temporary token that the organizer can use to reparent the activity through * {@link WindowContainerTransaction} if needed. */ + @NonNull public Change setActivityToken(@NonNull IBinder activityToken) { mActivityToken = requireNonNull(activityToken); return this; @@ -310,11 +321,12 @@ public final class TaskFragmentTransaction implements Parcelable { return mErrorCallbackToken; } - @Nullable + @NonNull public Bundle getErrorBundle() { - return mErrorBundle; + return mErrorBundle != null ? mErrorBundle : Bundle.EMPTY; } + @SuppressLint("IntentBuilderName") // This is not creating new Intent. @Nullable public Intent getActivityIntent() { return mActivityIntent; @@ -335,6 +347,7 @@ public final class TaskFragmentTransaction implements Parcelable { return 0; } + @NonNull public static final Creator<Change> CREATOR = new Creator<>() { @Override public Change createFromParcel(Parcel in) { diff --git a/core/java/android/window/TransitionInfo.java b/core/java/android/window/TransitionInfo.java index 8ca763e81757..33ea2e4af473 100644 --- a/core/java/android/window/TransitionInfo.java +++ b/core/java/android/window/TransitionInfo.java @@ -110,11 +110,11 @@ public final class TransitionInfo implements Parcelable { /** The container is an input-method window. */ public static final int FLAG_IS_INPUT_METHOD = 1 << 8; - /** The container is ActivityEmbedding embedded. */ - public static final int FLAG_IS_EMBEDDED = 1 << 9; + /** The container is in a Task with embedded activity. */ + public static final int FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY = 1 << 9; - /** The first unused bit. This can be used by remotes to attach custom flags to this change. */ - public static final int FLAG_FIRST_CUSTOM = 1 << 10; + /** The container fills its parent Task before and after the transition. */ + public static final int FLAG_FILLS_TASK = 1 << 10; /** The container is going to show IME on its task after the transition. */ public static final int FLAG_WILL_IME_SHOWN = 1 << 11; @@ -125,6 +125,9 @@ public final class TransitionInfo implements Parcelable { /** The container attaches work profile thumbnail for cross profile animation. */ public static final int FLAG_CROSS_PROFILE_WORK_THUMBNAIL = 1 << 13; + /** The first unused bit. This can be used by remotes to attach custom flags to this change. */ + public static final int FLAG_FIRST_CUSTOM = 1 << 14; + /** @hide */ @IntDef(prefix = { "FLAG_" }, value = { FLAG_NONE, @@ -137,9 +140,12 @@ public final class TransitionInfo implements Parcelable { FLAG_OCCLUDES_KEYGUARD, FLAG_DISPLAY_HAS_ALERT_WINDOWS, FLAG_IS_INPUT_METHOD, - FLAG_IS_EMBEDDED, - FLAG_FIRST_CUSTOM, - FLAG_WILL_IME_SHOWN + FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY, + FLAG_FILLS_TASK, + FLAG_WILL_IME_SHOWN, + FLAG_CROSS_PROFILE_OWNER_THUMBNAIL, + FLAG_CROSS_PROFILE_WORK_THUMBNAIL, + FLAG_FIRST_CUSTOM }) public @interface ChangeFlags {} @@ -322,28 +328,31 @@ public final class TransitionInfo implements Parcelable { sb.append("IS_INPUT_METHOD"); } if ((flags & FLAG_TRANSLUCENT) != 0) { - sb.append((sb.length() == 0 ? "" : "|") + "TRANSLUCENT"); + sb.append(sb.length() == 0 ? "" : "|").append("TRANSLUCENT"); } if ((flags & FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT) != 0) { - sb.append((sb.length() == 0 ? "" : "|") + "STARTING_WINDOW_TRANSFER"); + sb.append(sb.length() == 0 ? "" : "|").append("STARTING_WINDOW_TRANSFER"); } if ((flags & FLAG_IS_VOICE_INTERACTION) != 0) { - sb.append((sb.length() == 0 ? "" : "|") + "IS_VOICE_INTERACTION"); + sb.append(sb.length() == 0 ? "" : "|").append("IS_VOICE_INTERACTION"); } if ((flags & FLAG_IS_DISPLAY) != 0) { - sb.append((sb.length() == 0 ? "" : "|") + "IS_DISPLAY"); + sb.append(sb.length() == 0 ? "" : "|").append("IS_DISPLAY"); } if ((flags & FLAG_OCCLUDES_KEYGUARD) != 0) { - sb.append((sb.length() == 0 ? "" : "|") + "OCCLUDES_KEYGUARD"); + sb.append(sb.length() == 0 ? "" : "|").append("OCCLUDES_KEYGUARD"); } if ((flags & FLAG_DISPLAY_HAS_ALERT_WINDOWS) != 0) { - sb.append((sb.length() == 0 ? "" : "|") + "DISPLAY_HAS_ALERT_WINDOWS"); + sb.append(sb.length() == 0 ? "" : "|").append("DISPLAY_HAS_ALERT_WINDOWS"); + } + if ((flags & FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY) != 0) { + sb.append(sb.length() == 0 ? "" : "|").append("IN_TASK_WITH_EMBEDDED_ACTIVITY"); } - if ((flags & FLAG_IS_EMBEDDED) != 0) { - sb.append((sb.length() == 0 ? "" : "|") + "IS_EMBEDDED"); + if ((flags & FLAG_FILLS_TASK) != 0) { + sb.append(sb.length() == 0 ? "" : "|").append("FILLS_TASK"); } if ((flags & FLAG_FIRST_CUSTOM) != 0) { - sb.append((sb.length() == 0 ? "" : "|") + "FIRST_CUSTOM"); + sb.append(sb.length() == 0 ? "" : "|").append("FIRST_CUSTOM"); } return sb.toString(); } diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java index a66b405844b8..8f0fc2db5d26 100644 --- a/core/java/com/android/internal/app/ChooserActivity.java +++ b/core/java/com/android/internal/app/ChooserActivity.java @@ -142,6 +142,7 @@ import java.lang.annotation.RetentionPolicy; import java.net.URISyntaxException; import java.text.Collator; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; @@ -2939,12 +2940,14 @@ public class ChooserActivity extends ResolverActivity implements private void startFinishAnimation() { View rootView = findRootView(); - rootView.startAnimation(new FinishAnimation(this, rootView)); + if (rootView != null) { + rootView.startAnimation(new FinishAnimation(this, rootView)); + } } private boolean maybeCancelFinishAnimation() { View rootView = findRootView(); - Animation animation = rootView.getAnimation(); + Animation animation = rootView == null ? null : rootView.getAnimation(); if (animation instanceof FinishAnimation) { boolean hasEnded = animation.hasEnded(); animation.cancel(); @@ -3708,6 +3711,7 @@ public class ChooserActivity extends ResolverActivity implements this.mRows = rows; this.mCellCountPerRow = cellCountPerRow; this.mCellVisibility = new boolean[rows.size() * cellCountPerRow]; + Arrays.fill(mCellVisibility, true); this.mListAdapterSupplier = listAdapterSupplier; } @@ -4071,11 +4075,13 @@ public class ChooserActivity extends ResolverActivity implements */ private static class FinishAnimation extends AlphaAnimation implements Animation.AnimationListener { + @Nullable private Activity mActivity; + @Nullable private View mRootView; private final float mFromAlpha; - FinishAnimation(Activity activity, View rootView) { + FinishAnimation(@NonNull Activity activity, @NonNull View rootView) { super(rootView.getAlpha(), 0.0f); mActivity = activity; mRootView = rootView; @@ -4099,7 +4105,9 @@ public class ChooserActivity extends ResolverActivity implements @Override public void cancel() { - mRootView.setAlpha(mFromAlpha); + if (mRootView != null) { + mRootView.setAlpha(mFromAlpha); + } cleanup(); super.cancel(); } @@ -4110,9 +4118,10 @@ public class ChooserActivity extends ResolverActivity implements @Override public void onAnimationEnd(Animation animation) { - if (mActivity != null) { - mActivity.finish(); - cleanup(); + Activity activity = mActivity; + cleanup(); + if (activity != null) { + activity.finish(); } } diff --git a/core/java/com/android/internal/app/ChooserListAdapter.java b/core/java/com/android/internal/app/ChooserListAdapter.java index e57b90ad1612..1ec5325623ec 100644 --- a/core/java/com/android/internal/app/ChooserListAdapter.java +++ b/core/java/com/android/internal/app/ChooserListAdapter.java @@ -43,7 +43,6 @@ import android.view.ViewGroup; import android.widget.TextView; import com.android.internal.R; -import com.android.internal.annotations.VisibleForTesting; import com.android.internal.app.ResolverActivity.ResolvedComponentInfo; import com.android.internal.app.chooser.ChooserTargetInfo; import com.android.internal.app.chooser.DisplayResolveInfo; @@ -87,7 +86,7 @@ public class ChooserListAdapter extends ResolverListAdapter { private final ChooserActivityLogger mChooserActivityLogger; private int mNumShortcutResults = 0; - private final Map<TargetInfo, AsyncTask> mIconLoaders = new HashMap<>(); + private Map<DisplayResolveInfo, LoadIconTask> mIconLoaders = new HashMap<>(); private boolean mApplySharingAppLimits; // Reserve spots for incoming direct share targets by adding placeholders @@ -105,8 +104,6 @@ public class ChooserListAdapter extends ResolverListAdapter { private AppPredictor mAppPredictor; private AppPredictor.Callback mAppPredictorCallback; - private LoadDirectShareIconTaskProvider mTestLoadDirectShareTaskProvider; - // For pinned direct share labels, if the text spans multiple lines, the TextView will consume // the full width, even if the characters actually take up less than that. Measure the actual // line widths and constrain the View's width based upon that so that the pin doesn't end up @@ -243,6 +240,7 @@ public class ChooserListAdapter extends ResolverListAdapter { mListViewDataChanged = false; } + private void createPlaceHolders() { mNumShortcutResults = 0; mServiceTargets.clear(); @@ -267,25 +265,31 @@ public class ChooserListAdapter extends ResolverListAdapter { return; } - if (info instanceof DisplayResolveInfo) { - DisplayResolveInfo dri = (DisplayResolveInfo) info; - holder.bindLabel(dri.getDisplayLabel(), dri.getExtendedInfo(), alwaysShowSubLabel()); - startDisplayResolveInfoIconLoading(holder, dri); - } else { + if (!(info instanceof DisplayResolveInfo)) { holder.bindLabel(info.getDisplayLabel(), info.getExtendedInfo(), alwaysShowSubLabel()); + holder.bindIcon(info); if (info instanceof SelectableTargetInfo) { - SelectableTargetInfo selectableInfo = (SelectableTargetInfo) info; // direct share targets should append the application name for a better readout - DisplayResolveInfo rInfo = selectableInfo.getDisplayResolveInfo(); + DisplayResolveInfo rInfo = ((SelectableTargetInfo) info).getDisplayResolveInfo(); CharSequence appName = rInfo != null ? rInfo.getDisplayLabel() : ""; - CharSequence extendedInfo = selectableInfo.getExtendedInfo(); - String contentDescription = String.join(" ", selectableInfo.getDisplayLabel(), + CharSequence extendedInfo = info.getExtendedInfo(); + String contentDescription = String.join(" ", info.getDisplayLabel(), extendedInfo != null ? extendedInfo : "", appName); holder.updateContentDescription(contentDescription); - startSelectableTargetInfoIconLoading(holder, selectableInfo); + } + } else { + DisplayResolveInfo dri = (DisplayResolveInfo) info; + holder.bindLabel(dri.getDisplayLabel(), dri.getExtendedInfo(), alwaysShowSubLabel()); + LoadIconTask task = mIconLoaders.get(dri); + if (task == null) { + task = new LoadIconTask(dri, holder); + mIconLoaders.put(dri, task); + task.execute(); } else { - holder.bindIcon(info); + // The holder was potentially changed as the underlying items were + // reshuffled, so reset the target holder + task.setViewHolder(holder); } } @@ -326,32 +330,6 @@ public class ChooserListAdapter extends ResolverListAdapter { } } - private void startDisplayResolveInfoIconLoading(ViewHolder holder, DisplayResolveInfo info) { - LoadIconTask task = (LoadIconTask) mIconLoaders.get(info); - if (task == null) { - task = new LoadIconTask(info, holder); - mIconLoaders.put(info, task); - task.execute(); - } else { - // The holder was potentially changed as the underlying items were - // reshuffled, so reset the target holder - task.setViewHolder(holder); - } - } - - private void startSelectableTargetInfoIconLoading( - ViewHolder holder, SelectableTargetInfo info) { - LoadDirectShareIconTask task = (LoadDirectShareIconTask) mIconLoaders.get(info); - if (task == null) { - task = mTestLoadDirectShareTaskProvider == null - ? new LoadDirectShareIconTask(info) - : mTestLoadDirectShareTaskProvider.get(); - mIconLoaders.put(info, task); - task.loadIcon(); - } - task.setViewHolder(holder); - } - void updateAlphabeticalList() { new AsyncTask<Void, Void, List<DisplayResolveInfo>>() { @Override @@ -366,7 +344,7 @@ public class ChooserListAdapter extends ResolverListAdapter { Map<String, DisplayResolveInfo> consolidated = new HashMap<>(); for (DisplayResolveInfo info : allTargets) { String resolvedTarget = info.getResolvedComponentName().getPackageName() - + '#' + info.getDisplayLabel(); + + '#' + info.getDisplayLabel(); DisplayResolveInfo multiDri = consolidated.get(resolvedTarget); if (multiDri == null) { consolidated.put(resolvedTarget, info); @@ -375,7 +353,7 @@ public class ChooserListAdapter extends ResolverListAdapter { } else { // create consolidated target from the single DisplayResolveInfo MultiDisplayResolveInfo multiDisplayResolveInfo = - new MultiDisplayResolveInfo(resolvedTarget, multiDri); + new MultiDisplayResolveInfo(resolvedTarget, multiDri); multiDisplayResolveInfo.addTarget(info); consolidated.put(resolvedTarget, multiDisplayResolveInfo); } @@ -762,24 +740,10 @@ public class ChooserListAdapter extends ResolverListAdapter { } /** - * An alias for onBindView to use with unit tests. - */ - @VisibleForTesting - public void testViewBind(View view, TargetInfo info, int position) { - onBindView(view, info, position); - } - - @VisibleForTesting - public void setTestLoadDirectShareTaskProvider(LoadDirectShareIconTaskProvider provider) { - mTestLoadDirectShareTaskProvider = provider; - } - - /** * Necessary methods to communicate between {@link ChooserListAdapter} * and {@link ChooserActivity}. */ - @VisibleForTesting - public interface ChooserListCommunicator extends ResolverListCommunicator { + interface ChooserListCommunicator extends ResolverListCommunicator { int getMaxRankedTargets(); @@ -787,59 +751,4 @@ public class ChooserListAdapter extends ResolverListAdapter { boolean isSendAction(Intent targetIntent); } - - /** - * Loads direct share targets icons. - */ - @VisibleForTesting - public class LoadDirectShareIconTask extends AsyncTask<Void, Void, Void> { - private final SelectableTargetInfo mTargetInfo; - private ViewHolder mViewHolder; - - private LoadDirectShareIconTask(SelectableTargetInfo targetInfo) { - mTargetInfo = targetInfo; - } - - @Override - protected Void doInBackground(Void... voids) { - mTargetInfo.loadIcon(); - return null; - } - - @Override - protected void onPostExecute(Void arg) { - if (mViewHolder != null) { - mViewHolder.bindIcon(mTargetInfo); - notifyDataSetChanged(); - } - } - - /** - * Specifies a view holder that will be updated when the task is completed. - */ - public void setViewHolder(ViewHolder viewHolder) { - mViewHolder = viewHolder; - mViewHolder.bindIcon(mTargetInfo); - notifyDataSetChanged(); - } - - /** - * An alias for execute to use with unit tests. - */ - public void loadIcon() { - execute(); - } - } - - /** - * An interface for the unit tests to override icon loading task creation - */ - @VisibleForTesting - public interface LoadDirectShareIconTaskProvider { - /** - * Provides an instance of the task. - * @return - */ - LoadDirectShareIconTask get(); - } } diff --git a/core/java/com/android/internal/app/ResolverListAdapter.java b/core/java/com/android/internal/app/ResolverListAdapter.java index 3a3baa726f17..66fff5c13ab7 100644 --- a/core/java/com/android/internal/app/ResolverListAdapter.java +++ b/core/java/com/android/internal/app/ResolverListAdapter.java @@ -834,11 +834,7 @@ public class ResolverListAdapter extends BaseAdapter { void onHandlePackagesChanged(ResolverListAdapter listAdapter); } - /** - * A view holder. - */ - @VisibleForTesting - public static class ViewHolder { + static class ViewHolder { public View itemView; public Drawable defaultItemViewBackground; @@ -846,8 +842,7 @@ public class ResolverListAdapter extends BaseAdapter { public TextView text2; public ImageView icon; - @VisibleForTesting - public ViewHolder(View view) { + ViewHolder(View view) { itemView = view; defaultItemViewBackground = view.getBackground(); text = (TextView) view.findViewById(com.android.internal.R.id.text1); diff --git a/core/java/com/android/internal/app/chooser/SelectableTargetInfo.java b/core/java/com/android/internal/app/chooser/SelectableTargetInfo.java index 37eab40ba2b8..264e4f76d35d 100644 --- a/core/java/com/android/internal/app/chooser/SelectableTargetInfo.java +++ b/core/java/com/android/internal/app/chooser/SelectableTargetInfo.java @@ -37,7 +37,6 @@ import android.service.chooser.ChooserTarget; import android.text.SpannableStringBuilder; import android.util.Log; -import com.android.internal.annotations.GuardedBy; import com.android.internal.app.ChooserActivity; import com.android.internal.app.ResolverActivity; import com.android.internal.app.ResolverListAdapter.ActivityInfoPresentationGetter; @@ -60,11 +59,8 @@ public final class SelectableTargetInfo implements ChooserTargetInfo { private final String mDisplayLabel; private final PackageManager mPm; private final SelectableTargetInfoCommunicator mSelectableTargetInfoCommunicator; - @GuardedBy("this") - private ShortcutInfo mShortcutInfo; private Drawable mBadgeIcon = null; private CharSequence mBadgeContentDescription; - @GuardedBy("this") private Drawable mDisplayIcon; private final Intent mFillInIntent; private final int mFillInFlags; @@ -82,7 +78,6 @@ public final class SelectableTargetInfo implements ChooserTargetInfo { mModifiedScore = modifiedScore; mPm = mContext.getPackageManager(); mSelectableTargetInfoCommunicator = selectableTargetInfoComunicator; - mShortcutInfo = shortcutInfo; mIsPinned = shortcutInfo != null && shortcutInfo.isPinned(); if (sourceInfo != null) { final ResolveInfo ri = sourceInfo.getResolveInfo(); @@ -97,6 +92,8 @@ public final class SelectableTargetInfo implements ChooserTargetInfo { } } } + // TODO(b/121287224): do this in the background thread, and only for selected targets + mDisplayIcon = getChooserTargetIconDrawable(chooserTarget, shortcutInfo); if (sourceInfo != null) { mBackupResolveInfo = null; @@ -121,10 +118,7 @@ public final class SelectableTargetInfo implements ChooserTargetInfo { mChooserTarget = other.mChooserTarget; mBadgeIcon = other.mBadgeIcon; mBadgeContentDescription = other.mBadgeContentDescription; - synchronized (other) { - mShortcutInfo = other.mShortcutInfo; - mDisplayIcon = other.mDisplayIcon; - } + mDisplayIcon = other.mDisplayIcon; mFillInIntent = fillInIntent; mFillInFlags = flags; mModifiedScore = other.mModifiedScore; @@ -147,25 +141,6 @@ public final class SelectableTargetInfo implements ChooserTargetInfo { return mSourceInfo; } - /** - * Load display icon, if needed. - */ - public void loadIcon() { - ShortcutInfo shortcutInfo; - Drawable icon; - synchronized (this) { - shortcutInfo = mShortcutInfo; - icon = mDisplayIcon; - } - if (icon == null && shortcutInfo != null) { - icon = getChooserTargetIconDrawable(mChooserTarget, shortcutInfo); - synchronized (this) { - mDisplayIcon = icon; - mShortcutInfo = null; - } - } - } - private Drawable getChooserTargetIconDrawable(ChooserTarget target, @Nullable ShortcutInfo shortcutInfo) { Drawable directShareIcon = null; @@ -295,7 +270,7 @@ public final class SelectableTargetInfo implements ChooserTargetInfo { } @Override - public synchronized Drawable getDisplayIcon(Context context) { + public Drawable getDisplayIcon(Context context) { return mDisplayIcon; } diff --git a/core/java/com/android/internal/policy/DividerSnapAlgorithm.java b/core/java/com/android/internal/policy/DividerSnapAlgorithm.java index 527286cf000e..a065e2b78d80 100644 --- a/core/java/com/android/internal/policy/DividerSnapAlgorithm.java +++ b/core/java/com/android/internal/policy/DividerSnapAlgorithm.java @@ -287,7 +287,6 @@ public class DividerSnapAlgorithm { int dividerMax = isHorizontalDivision ? mDisplayHeight : mDisplayWidth; - int navBarSize = isHorizontalDivision ? mInsets.bottom : mInsets.right; int startPos = -mDividerSize; if (dockedSide == DOCKED_RIGHT) { startPos += mInsets.left; @@ -308,8 +307,7 @@ public class DividerSnapAlgorithm { addMinimizedTarget(isHorizontalDivision, dockedSide); break; } - mTargets.add(new SnapTarget(dividerMax - navBarSize, dividerMax, - SnapTarget.FLAG_DISMISS_END, 0.35f)); + mTargets.add(new SnapTarget(dividerMax, dividerMax, SnapTarget.FLAG_DISMISS_END, 0.35f)); } private void addNonDismissingTargets(boolean isHorizontalDivision, int topPosition, diff --git a/core/java/com/android/internal/widget/ConversationLayout.java b/core/java/com/android/internal/widget/ConversationLayout.java index 4706affa3541..5f8acff80c0a 100644 --- a/core/java/com/android/internal/widget/ConversationLayout.java +++ b/core/java/com/android/internal/widget/ConversationLayout.java @@ -111,6 +111,7 @@ public class ConversationLayout extends FrameLayout private Icon mLargeIcon; private View mExpandButtonContainer; private ViewGroup mExpandButtonAndContentContainer; + private ViewGroup mExpandButtonContainerA11yContainer; private NotificationExpandButton mExpandButton; private MessagingLinearLayout mImageMessageContainer; private int mBadgeProtrusion; @@ -234,6 +235,8 @@ public class ConversationLayout extends FrameLayout }); mConversationText = findViewById(R.id.conversation_text); mExpandButtonContainer = findViewById(R.id.expand_button_container); + mExpandButtonContainerA11yContainer = + findViewById(R.id.expand_button_a11y_container); mConversationHeader = findViewById(R.id.conversation_header); mContentContainer = findViewById(R.id.notification_action_list_margin_target); mExpandButtonAndContentContainer = findViewById(R.id.expand_button_and_content_container); @@ -1091,7 +1094,7 @@ public class ConversationLayout extends FrameLayout newContainer = mExpandButtonAndContentContainer; } else { buttonGravity = Gravity.CENTER_HORIZONTAL | Gravity.TOP; - newContainer = this; + newContainer = mExpandButtonContainerA11yContainer; } mExpandButton.setExpanded(!mIsCollapsed); diff --git a/core/res/res/layout/notification_template_material_conversation.xml b/core/res/res/layout/notification_template_material_conversation.xml index 42fb4a26dd3b..ce8a90495572 100644 --- a/core/res/res/layout/notification_template_material_conversation.xml +++ b/core/res/res/layout/notification_template_material_conversation.xml @@ -89,45 +89,62 @@ <include layout="@layout/notification_material_action_list" /> </com.android.internal.widget.RemeasuringLinearLayout> - <!--This is dynamically placed between here and at the end of the layout. It starts here since - only FrameLayout layout params have gravity--> + <!--expand_button_a11y_container ensures talkback focus order is correct when view is expanded. + The -1px of marginTop and 1px of paddingTop make sure expand_button_a11y_container is prior to + its sibling view in accessibility focus order. + {see android.view.ViewGroup.addChildrenForAccessibility()} + expand_button_container will be moved under expand_button_and_content_container when collapsed, + this dynamic movement ensures message can flow under expand button when expanded--> <FrameLayout - android:id="@+id/expand_button_container" - android:layout_width="wrap_content" + android:id="@+id/expand_button_a11y_container" + android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="end|top" android:clipChildren="false" - android:clipToPadding="false"> - <!--This layout makes sure that we can nicely center the expand content in the - collapsed layout while the parent makes sure that we're never laid out bigger - than the messaging content.--> - <LinearLayout - android:id="@+id/expand_button_touch_container" + android:clipToPadding="false" + android:layout_marginTop="-1px" + android:paddingTop="1px" + > + <!--expand_button_container is dynamically placed between here and at the end of the + layout. It starts here since only FrameLayout layout params have gravity--> + <FrameLayout + android:id="@+id/expand_button_container" android:layout_width="wrap_content" - android:layout_height="@dimen/conversation_expand_button_height" - android:orientation="horizontal" + android:layout_height="match_parent" android:layout_gravity="end|top" - android:paddingEnd="0dp" - android:clipToPadding="false" android:clipChildren="false" - > - <!-- Images --> - <com.android.internal.widget.MessagingLinearLayout - android:id="@+id/conversation_image_message_container" - android:forceHasOverlappingRendering="false" - android:layout_width="40dp" - android:layout_height="40dp" - android:layout_marginStart="@dimen/conversation_image_start_margin" - android:spacing="0dp" - android:layout_gravity="center" + android:clipToPadding="false"> + <!--expand_button_touch_container makes sure that we can nicely center the expand + content in the collapsed layout while the parent makes sure that we're never laid out + bigger than the messaging content.--> + <LinearLayout + android:id="@+id/expand_button_touch_container" + android:layout_width="wrap_content" + android:layout_height="@dimen/conversation_expand_button_height" + android:orientation="horizontal" + android:layout_gravity="end|top" + android:paddingEnd="0dp" android:clipToPadding="false" android:clipChildren="false" - /> - <include layout="@layout/notification_expand_button" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_gravity="center" - /> - </LinearLayout> + > + <!-- Images --> + <com.android.internal.widget.MessagingLinearLayout + android:id="@+id/conversation_image_message_container" + android:forceHasOverlappingRendering="false" + android:layout_width="40dp" + android:layout_height="40dp" + android:layout_marginStart="@dimen/conversation_image_start_margin" + android:spacing="0dp" + android:layout_gravity="center" + android:clipToPadding="false" + android:clipChildren="false" + /> + <include layout="@layout/notification_expand_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + /> + </LinearLayout> + </FrameLayout> </FrameLayout> </com.android.internal.widget.ConversationLayout> diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml index 950394869909..0063eae2463a 100644 --- a/core/res/res/values-af/strings.xml +++ b/core/res/res/values-af/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Gebruik skermslot"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Voer jou skermslot in om voort te gaan"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Druk ferm op die sensor"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Kon nie vingerafdruk verwerk nie. Probeer asseblief weer."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Maak vingerafdruksensor skoon en probeer weer"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Maak sensor skoon en probeer weer"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Druk ferm op sensor"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Vinger is te stadig beweer. Probeer asseblief weer."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Probeer \'n ander vingerafdruk"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Te helder"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Probeer om dit te verstel"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Verander elke keer die posisie van jou vinger so effens"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Gesig is gestaaf; druk asseblief bevestig"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Vingerafdrukhardeware is nie beskikbaar nie."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Kan nie vingerafdruk opstel nie"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Vingerafdrukuittelling is bereik. Probeer weer."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Vingerafdrukhandeling is gekanselleer."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Vingerafdrukhandeling is deur gebruiker gekanselleer."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Te veel pogings. Probeer later weer."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Te veel pogings. Gebruik eerder skermslot."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Probeer weer."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Geen vingerafdrukke is geregistreer nie."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Hierdie toetstel het nie \'n vingerafdruksensor nie."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Sensor is tydelik gedeaktiveer."</string> @@ -638,7 +643,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Besoek \'n verskaffer wat herstelwerk doen."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"Kan nie jou gesigmodel skep nie. Probeer weer."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Te helder. Probeer sagter beligting."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Probeer helderder beligting"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"Beweeg foon verder weg"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Beweeg foon nader"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Beweeg foon hoër op"</string> @@ -1251,8 +1257,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Begin programme."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"Voltooi herlaai."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Jy het die aan/af-skakelaar gedruk – dit skakel gewoonlik die skerm af.\n\nProbeer liggies tik terwyl jy jou vingerafdruk opstel."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Tik om skerm af te skakel"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Skakel skerm af"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"Gaan voort met vingerafdrukverifiëring?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"Jy het die aan/af-skakelaar gedruk – dit skakel gewoonlik die skerm af.\n\nProbeer liggies tik om jou vingerafdruk te verifieer."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Skakel skerm af"</string> diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml index a21908597cb5..31c8bf6a48d5 100644 --- a/core/res/res/values-am/strings.xml +++ b/core/res/res/values-am/strings.xml @@ -111,8 +111,8 @@ <string name="roamingText0" msgid="7793257871609854208">"በዝውውር ላይ አመላካች በርቷል"</string> <string name="roamingText1" msgid="5073028598334616445">"በዝውውር ላይ አመልካች ጠፍቷል"</string> <string name="roamingText2" msgid="2834048284153110598">"በዝውውር ላይ አመልካች ብልጭ ብልጭ ይላል"</string> - <string name="roamingText3" msgid="831690234035748988">"ከጎረቤት ውጪ"</string> - <string name="roamingText4" msgid="2171252529065590728">"ከህንፃ ውጪ"</string> + <string name="roamingText3" msgid="831690234035748988">"ከጎረቤት ውጭ"</string> + <string name="roamingText4" msgid="2171252529065590728">"ከህንፃ ውጭ"</string> <string name="roamingText5" msgid="4294671587635796641">"የዝውውር- ተመራጭ ስርዓት"</string> <string name="roamingText6" msgid="5536156746637992029">"ዝውውር- ዝግጁ የሆነ ስርዓት"</string> <string name="roamingText7" msgid="1783303085512907706">" የዝውውር- አጋር ስምምነት"</string> @@ -433,7 +433,7 @@ <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"ይህ መተግበሪያ ሁሉንም በእርስዎ ጡባዊ ላይ የተከማቹ የቀን መቁጠሪያ ክስተቶችን ማንበብ ወይም የእርስዎን የቀን መቁጠሪያ ውሂብ ማስቀመጥ ይችላል።"</string> <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"ይህ መተግበሪያ ሁሉንም በእርስዎ Android TV መሣሪያ ላይ የተከማቹ የቀን መቁጠሪያ ክስተቶችን ማንበብ ወይም የእርስዎን የቀን መቁጠሪያ ውሂብ ማስቀመጥ ይችላል።"</string> <string name="permdesc_readCalendar" product="default" msgid="9118823807655829957">"ይህ መተግበሪያ ሁሉንም በእርስዎ ስልክ ላይ የተከማቹ የቀን መቁጠሪያ ክስተቶችን ማንበብ ወይም የእርስዎን የቀን መቁጠሪያ ውሂብ ማስቀመጥ ይችላል።"</string> - <string name="permlab_writeCalendar" msgid="6422137308329578076">"የቀን መቁጠሪያ ክስተቶችን ቀይር ወይም አክል እና ለእንግዶች ከባለቤቱ ዕውቅና ውጪ ላክ።"</string> + <string name="permlab_writeCalendar" msgid="6422137308329578076">"የቀን መቁጠሪያ ክስተቶችን ቀይር ወይም አክል እና ለእንግዶች ከባለቤቱ ዕውቅና ውጭ ላክ።"</string> <string name="permdesc_writeCalendar" product="tablet" msgid="8722230940717092850">"ይህ መተግበሪያ በእርስዎ ጡባዊ ላይ የቀን መቁጠሪያ ክስተቶችን ሊያክል፣ ሊያስወግድ ወይም ሊለውጥ ይችላል። ይህ መተግበሪያ ከቀን መቁጠሪያ የመጡ መስለው የሚታዩ መልእክቶችን ሊልክ ወይም ባለቤቶቹን ሳያሳውቅ ክስተቶችን ሊለውጥ ይችላል።"</string> <string name="permdesc_writeCalendar" product="tv" msgid="951246749004952706">"ይህ መተግበሪያ በእርስዎ Android TV መሣሪያ ላይ የቀን መቁጠሪያ ክስተቶችን ሊያክል፣ ሊያስወግድ ወይም ሊለውጥ ይችላል። ይህ መተግበሪያ ከቀን መቁጠሪያ የመጡ መስለው የሚታዩ መልእክቶችን ሊልክ ወይም ባለቤቶቹን ሳያሳውቅ ክስተቶችን ሊለውጥ ይችላል።"</string> <string name="permdesc_writeCalendar" product="default" msgid="5416380074475634233">"ይህ መተግበሪያ በእርስዎ ስልክ ላይ የቀን መቁጠሪያ ክስተቶችን ሊያክል፣ ሊያስወግድ ወይም ሊለውጥ ይችላል። ይህ መተግበሪያ ከቀን መቁጠሪያ የመጡ መስለው የሚታዩ መልእክቶችን ሊልክ ወይም ባለቤቶቹን ሳያሳውቅ ክስተቶችን ሊለውጥ ይችላል።"</string> @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"የማያ ገጽ መቆለፊን ይጠቀሙ"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"ለመቀጠል የማያ ገጽ ቁልፍዎን ያስገቡ"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"ዳሳሹን በደንብ ይጫኑት"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"ጣት አሻራን መስራት አልተቻለም። እባክዎ እንደገና ይሞክሩ።"</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"የጣት አሻራ ዳሳሽን ያጽዱ እና እንደገና ይሞክሩ"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"ዳሳሹን ያጽዱ እና እንደገና ይሞክሩ"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"ዳሳሹን ጠበቅ አድርገው ይጫኑት"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"ጣት ከልክ በላይ ተንቀራፎ ተንቀሳቅሷል። እባክዎ እንደገና ይሞክሩ።"</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"ሌላ የጣት አሻራ ይሞክሩ"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"በጣም ብርሃናማ"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"ለማስተካከል ይሞክሩ"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"በእያንዳንዱ ጊዜ የጣትዎን ቦታ በትንሹ ይለዋውጡ"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"ፊት ተረጋግጧል፣ እባክዎ አረጋግጥን ይጫኑ"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"የጣት አሻራ ሃርድዌር አይገኝም።"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"የጣት አሻራን ማዋቀር አልተቻለም"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"የጣት አሻራ ማብቂያ ጊዜ ደርሷል። እንደገና ይሞክሩ።"</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"የጣት አሻራ ስርዓተ ክወና ተትቷል።"</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"የጣት አሻራ ክወና በተጠቃሚ ተሰርዟል።"</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"ከልክ በላይ ብዙ ሙከራዎች። በኋላ ላይ እንደገና ይሞክሩ።"</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"በጣም ብዙ ሙከራዎች። በምትኩ የማያ ገጽ መቆለፊያን ይጠቀሙ።"</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"እንደገና ይሞክሩ።"</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"ምንም የጣት አሻራዎች አልተመዘገቡም።"</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"ይህ መሣሪያ የጣት አሻራ ዳሳሽ የለውም።"</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"ዳሳሽ ለጊዜው ተሰናክሏል።"</string> @@ -638,7 +643,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"የጥገና አገልግሎት ሰጪን ይጎብኙ።"</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"የመልክዎን ሞዴል መፍጠር አልተቻለም። እንደገና ይሞክሩ።"</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"ከልክ በላይ ፈካ ያለ። ይበልጥ ረጋ ያለ ብርሃን አጠቃቀምን ይሞክሩ።"</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"ከዚህ ፈካ ያለ ብርሃንን ይሞክሩ"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"ስልኩን ያርቁት"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"ስልኩን ያቅርቡት"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"ስልኩን ከፍ ወዳለ ቦታ ይውሰዱት"</string> @@ -1166,7 +1172,7 @@ <string name="dialog_alert_title" msgid="651856561974090712">"ትኩረት"</string> <string name="loading" msgid="3138021523725055037">"በመጫን ላይ…"</string> <string name="capital_on" msgid="2770685323900821829">"በ"</string> - <string name="capital_off" msgid="7443704171014626777">"ውጪ"</string> + <string name="capital_off" msgid="7443704171014626777">"ውጭ"</string> <string name="checked" msgid="9179896827054513119">"ምልክት ተደርጎበታል"</string> <string name="not_checked" msgid="7972320087569023342">"ምልክት አልተደረገበትም"</string> <string name="selected" msgid="6614607926197755875">"ተመርጧል"</string> @@ -1251,8 +1257,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"መተግበሪያዎችን በማስጀመር ላይ፡፡"</string> <string name="android_upgrading_complete" msgid="409800058018374746">"አጨራረስ ማስነሻ፡፡"</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"የማብሪያ/ማጥፊያ ቁልፉን ተጭነዋል — ይህ ብዙውን ጊዜ ማያ ገጹን ያጠፋል።\n\nየጣት አሻራዎን በሚያዋቅሩበት ጊዜ በትንሹ መታ ለማድረግ ይሞክሩ።"</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"ማያ ገጽን ለማጥፋት መታ ያድርጉ"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"ማያ ገጽን አጥፋ"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"የጣት አሻራዎን ማረጋገጥ ይቀጥሉ?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"የማብሪያ/ማጥፊያ ቁልፉን ተጭነዋል - ይህ ብዙውን ጊዜ ማያ ገጹን ያጠፋል። \n\n የጣት አሻራዎን ለማረጋገጥ በትንሹ መታ ለማድረግ ይሞክሩ።"</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"ማያ ገጽን አጥፋ"</string> @@ -1478,7 +1486,7 @@ <string name="permission_request_notification_title" msgid="1810025922441048273">"ፈቃድ ተጠይቋል"</string> <string name="permission_request_notification_with_subtitle" msgid="3743417870360129298">\n" ለ<xliff:g id="ACCOUNT">%s</xliff:g> መለያ ፈቃድ ተጠይቋል"</string> <string name="permission_request_notification_for_app_with_subtitle" msgid="1298704005732851350">"ለመለያ <xliff:g id="ACCOUNT">%2$s</xliff:g>\nበ<xliff:g id="APP">%1$s</xliff:g> የተጠየቀ ፈቃድ።"</string> - <string name="forward_intent_to_owner" msgid="4620359037192871015">"ከስራ መገለጫዎ ውጪ ሆነው መተግበሪያ እየተጠቀሙ ነው"</string> + <string name="forward_intent_to_owner" msgid="4620359037192871015">"ከስራ መገለጫዎ ውጭ ሆነው መተግበሪያ እየተጠቀሙ ነው"</string> <string name="forward_intent_to_work" msgid="3620262405636021151">"ይህን መተግበሪያ በእርስዎ የስራ መገለጫ ላይ እየተጠቀሙበት ነው"</string> <string name="input_method_binding_label" msgid="1166731601721983656">"ግቤት ስልት"</string> <string name="sync_binding_label" msgid="469249309424662147">"አስምር"</string> diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml index 01fc4bdbbb0e..1f0f0208ee4c 100644 --- a/core/res/res/values-ar/strings.xml +++ b/core/res/res/values-ar/strings.xml @@ -590,13 +590,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"استخدام قفل الشاشة"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"أدخِل قفل الشاشة للمتابعة"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"اضغط بقوة على المستشعر"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"تعذرت معالجة بصمة الإصبع. يُرجى إعادة المحاولة."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"يُرجى تنظيف مستشعر بصمات الإصبع ثم إعادة المحاولة."</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"تنظيف المستشعر ثم إعادة المحاولة"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"اضغط بقوة على المستشعر"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"تم تحريك الإصبع ببطء شديد. يُرجى إعادة المحاولة."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"يمكنك تجربة بصمة إصبع أخرى."</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"الصورة ساطعة للغاية."</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"حاوِل تعديل بصمة الإصبع."</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"غيِّر موضع إصبعك قليلاً في كل مرة."</string> <string-array name="fingerprint_acquired_vendor"> @@ -608,13 +611,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"تمّت مصادقة الوجه، يُرجى الضغط على \"تأكيد\"."</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"جهاز بصمة الإصبع غير متاح."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"يتعذّر إعداد بصمة الإصبع."</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"تم بلوغ مهلة إدخال بصمة الإصبع. أعد المحاولة."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"تم إلغاء تشغيل بصمة الإصبع."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"تم إلغاء تشغيل بصمة الإصبع بواسطة المستخدم."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"تم إجراء عدد كبير من المحاولات. أعد المحاولة لاحقًا."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"تم إجراء عدد كبير جدًا من المحاولات. عليك استخدام قفل الشاشة بدلاً من ذلك."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"أعد المحاولة."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"ليست هناك بصمات إصبع مسجَّلة."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"لا يحتوي هذا الجهاز على مستشعِر بصمات إصبع."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"تم إيقاف جهاز الاستشعار مؤقتًا."</string> @@ -642,7 +647,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"يُرجى التواصل مع مقدِّم خدمات إصلاح."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"يتعذّر إنشاء نموذج الوجه. يُرجى إعادة المحاولة."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"ساطع للغاية. تجربة مستوى سطوع أقلّ."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"جرِّب زيادة الإضاءة."</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"يُرجى إبعاد الهاتف عنك."</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"يُرجى تقريب الهاتف منك."</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"يُرجى رفع الهاتف للأعلى."</string> @@ -1255,8 +1261,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"بدء التطبيقات."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"جارٍ إعادة التشغيل."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"ضغطت على زر التشغيل، يؤدي هذا عادةً إلى إيقاف الشاشة.\n\nجرِّب النقر بخفة أثناء إعداد بصمتك."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"النقر لإيقاف الشاشة"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"إيقاف الشاشة"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"هل تريد مواصلة تأكيد بصمة إصبعك؟"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"ضغطت على زر التشغيل، يؤدي هذا عادةً إلى إيقاف الشاشة.\n\nجرِّب النقر بخفة لتأكيد بصمة إصبعك."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"إيقاف الشاشة"</string> diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml index 7fed29f04f7e..a3cd1aec2eaf 100644 --- a/core/res/res/values-as/strings.xml +++ b/core/res/res/values-as/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"স্ক্ৰীন ল\'ক ব্যৱহাৰ কৰক"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"অব্যাহত ৰাখিবলৈ আপোনাৰ স্ক্ৰীন লক দিয়ক"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"ছেন্সৰটোত ভালকৈ টিপক"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"ফিগাৰপ্ৰিণ্টৰ প্ৰক্ৰিয়া সম্পাদন কৰিবপৰা নগ\'ল। অনুগ্ৰহ কৰি আকৌ চেষ্টা কৰক৷"</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"ফিংগাৰপ্ৰিণ্ট ছেন্সৰটো মচি পুনৰ চেষ্টা কৰক"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"ছেন্সৰটো মচি পুনৰ চেষ্টা কৰক"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"ছেন্সৰটোত ভালকৈ টিপক"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"আঙুলিৰ গতি অতি মন্থৰ আছিল। অনুগ্ৰহ কৰি আকৌ চেষ্টা কৰক৷"</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"অন্য এটা ফিংগাৰপ্ৰিণ্ট ব্যৱহাৰ কৰি চাওক"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"অতি উজ্জ্বল"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"মিলাই চাওক"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"প্ৰতিবাৰতে আপোনাৰ আঙুলিটোৰ স্থান সামান্য সলনি কৰক"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"মুখমণ্ডলৰ বিশ্বাসযোগ্যতা প্ৰমাণীকৰণ কৰা হ’ল, অনুগ্ৰহ কৰি ‘নিশ্চিত কৰক’ বুটামটো টিপক"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"ফিংগাৰপ্ৰিণ্ট হাৰ্ডৱেৰ নাই।"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"ফিংগাৰপ্ৰিণ্ট ছেট আপ কৰিব নোৱাৰি"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"ফিংগাৰপ্ৰিণ্ট গ্ৰহণৰ সময়সীমা উকলি গৈছে। আকৌ চেষ্টা কৰক।"</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"ফিংগাৰপ্ৰিণ্ট কাৰ্য বাতিল কৰা হ’ল।"</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"ব্যৱহাৰকাৰীয়ে ফিংগাৰপ্ৰিণ্ট ক্ৰিয়া বাতিল কৰিছে।"</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"অত্যধিক ভুল প্ৰয়াস। কিছুসময়ৰ পাছত আকৌ চেষ্টা কৰক।"</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"অতি বেছিসংখ্যক প্ৰয়াস। ইয়াৰ সলনি স্ক্ৰীন লক ব্যৱহাৰ কৰক।"</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"আকৌ চেষ্টা কৰক।"</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"কোনো ফিংগাৰপ্ৰিণ্ট যোগ কৰা নহ\'ল।"</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"এই ডিভাইচটোত ফিংগাৰপ্ৰিণ্ট ছেন্সৰ নাই।"</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"ছেন্সৰটো সাময়িকভাৱে অক্ষম হৈ আছে।"</string> @@ -638,7 +643,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"মেৰামতি সেৱা প্ৰদানকাৰী কোনো প্ৰতিষ্ঠানলৈ যাওক।"</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"মুখাৱয়বৰ মডেল সৃষ্টি কৰিব নোৱাৰি। পুনৰ চেষ্টা কৰক।"</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"অতি উজ্জ্বল। ইয়াতকৈ কম পোহৰৰ উৎস ব্যৱহাৰ কৰক।"</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"উজ্জ্বল পোহৰ থকা ঠাইলৈ গৈ চাওক"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"ফ’নটো আৰু আঁতৰলৈ নিয়ক"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"ফ’নটো ওচৰলৈ আনক"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"ফ’নটো ওপৰলৈ নিয়ক"</string> @@ -1251,8 +1257,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"আৰম্ভ হৈ থকা এপসমূহ।"</string> <string name="android_upgrading_complete" msgid="409800058018374746">"বুট কাৰ্য সমাপ্ত কৰিছে।"</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"আপুনি পাৱাৰ বুটামটো টিপিছে — এইটোৱে সাধাৰণতে স্ক্ৰীনখন অফ কৰে।\n\nআপোনাৰ ফিংগাৰপ্ৰিণ্টটো ছেট আপ কৰাৰ সময়ত লাহেকৈ টিপি চাওক।"</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"স্ক্ৰীন অফ কৰিবলৈ টিপক"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"স্ক্ৰীন অফ কৰক"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"ফিংগাৰপ্ৰিণ্ট সত্যাপন কৰা জাৰি ৰাখিবনে?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"আপুনি পাৱাৰ বুটামটো টিপিছে — এইটোৱে সাধাৰণতে স্ক্ৰীনখন অফ কৰে।\n\nআপোনাৰ ফিংগাৰপ্ৰিণ্টটো সত্যাপন কৰিবলৈ লাহেকৈ টিপি চাওক।"</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"স্ক্ৰীন অফ কৰক"</string> diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml index da989aeb31fd..2c18c756eb72 100644 --- a/core/res/res/values-az/strings.xml +++ b/core/res/res/values-az/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Ekran kilidindən istifadə edin"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Davam etmək üçün ekran kilidinizi daxil edin"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Sensora basıb saxlayın"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Barmaq izi tanınmadı. Lütfən, yenidən cəhd edin."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Barmaq izi sensorunu silib yenidən cəhd edin"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Sensoru silib yenidən cəhd edin"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Sensora basıb saxlayın"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Barmağınızı çox yavaş hərəkət etdirdiniz. Lütfən, yenidən cəhd edin."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Başqa bir barmaq izini sınayın"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Çox işıqlıdır"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Tənzimləməyə çalışın"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Hər dəfə barmağınızın yerini bir az dəyişdirin"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Üz təsdiq edildi, təsdiq düyməsinə basın"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Barmaq izi üçün avadanlıq yoxdur."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Barmaq izini ayarlamaq mümkün deyil"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Barmaq izinin vaxtı başa çatdı. Yenidən cəhd edin."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Barmaq izi əməliyyatı ləğv edildi."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Barmaq izi əməliyyatı istifadəçi tərəfindən ləğv edildi."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Cəhdlər çox oldu. Sonraya saxlayın."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Həddindən çox cəhd edilib. Əvəzində ekran kilidindən istifadə edin."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Yenidən cəhd edin."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Barmaq izi qeydə alınmayıb."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Bu cihazda barmaq izi sensoru yoxdur."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Sensor müvəqqəti deaktivdir."</string> @@ -638,7 +643,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Təmir provayderini ziyarət edin."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"Üz modelinizi yaratmaq olmur. Yenə cəhd edin."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Çox işıqlıdır. Daha az işıqlı şəkli sınayın."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Parlaq işıqdan istifadə edin"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"Telefonu uzaq tutun"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Telefonu yaxına tutun"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Telefonu yuxarı tutun"</string> @@ -1251,8 +1257,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Tətbiqlər başladılır."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"Yükləmə başa çatır."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Qidalanma düyməsini basdınız — adətən bu, ekranı söndürür.\n\nBarmaq izini ayarlayarkən yüngülcə toxunmağa çalışın."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Ekranı söndürmək üçün toxunun"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Ekranı söndürün"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"Barmaq izini doğrulamağa davam edilsin?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"Qidalanma düyməsini basdınız — adətən bu, ekranı söndürür.\n\nBarmaq izini doğrulamaq üçün yüngülcə toxunmağa çalışın."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Ekranı söndürün"</string> diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml index 23397b0de30a..525ed310c237 100644 --- a/core/res/res/values-b+sr+Latn/strings.xml +++ b/core/res/res/values-b+sr+Latn/strings.xml @@ -587,13 +587,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Koristite zaključavanje ekrana"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Upotrebite zaključavanje ekrana da biste nastavili"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Jako pritisnite senzor"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Nije uspela obrada otiska prsta. Probajte ponovo."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Obrišite senzor za otisak prsta i probajte ponovo"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Obrišite senzor i probajte ponovo"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Jako pritisnite senzor"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Previše sporo ste pomerili prst. Probajte ponovo."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Probajte sa drugim otiskom prsta"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Previše je svetlo"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Probajte da prilagodite"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Svaki put pomalo promenite položaj prsta"</string> <string-array name="fingerprint_acquired_vendor"> @@ -605,13 +608,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Lice je potvrđeno. Pritisnite Potvrdi"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Hardver za otiske prstiju nije dostupan."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Podešavanje otiska prsta nije uspelo"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Vremensko ograničenje za otisak prsta je isteklo. Probajte ponovo."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Radnja sa otiskom prsta je otkazana."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Korisnik je otkazao radnju sa otiskom prsta."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Previše pokušaja. Probajte ponovo kasnije."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Previše pokušaja. Koristite zaključavanje ekrana umesto toga."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Probajte ponovo."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Nije registrovan nijedan otisak prsta."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Ovaj uređaj nema senzor za otisak prsta."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Senzor je privremeno onemogućen."</string> @@ -639,7 +644,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Posetite dobavljača za popravke."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"Pravljenje modela lica nije uspelo. Probajte ponovo."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Previše je svetlo. Probajte sa slabijim osvetljenjem."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Probajte sa jačim osvetljenjem"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"Udaljite telefon"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Približite telefon"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Pomerite telefon nagore"</string> @@ -1252,8 +1258,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Pokretanje aplikacija."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"Završavanje pokretanja."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Pritisnuli ste dugme za uključivanje – time obično isključujete ekran.\n\nProbajte lagano da dodirnete dok podešavate otisak prsta."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Dodirnite da biste isključili ekran"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Isključi ekran"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"Nastavljate verifikaciju otiska prsta?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"Pritisnuli ste dugme za uključivanje – time obično isključujete ekran.\n\nProbajte lagano da dodirnete da biste verifikovali otisak prsta."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Isključi ekran"</string> diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml index 0079624c47b8..777e7c73cd77 100644 --- a/core/res/res/values-be/strings.xml +++ b/core/res/res/values-be/strings.xml @@ -588,13 +588,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Ужываць блакіроўку экрана"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Каб працягнуць, скарыстайце свой сродак блакіроўкі экрана"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Моцна націсніце на сканер"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Не атрымалася апрацаваць адбітак пальца. Паспрабуйце яшчэ раз."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Ачысціце сканер адбіткаў пальцаў і паўтарыце спробу"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Ачысціце сканер і паўтарыце спробу"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Моцна націсніце на сканер"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Палец рухаўся занадта павольна. Паспрабуйце яшчэ раз."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Паспрабуйце іншы адбітак пальца"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Занадта светла"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Паспрабуйце наладзіць"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Кожны раз крыху мяняйце пазіцыю пальца"</string> <string-array name="fingerprint_acquired_vendor"> @@ -606,13 +609,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Твар распазнаны. Націсніце, каб пацвердзіць"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Апаратныя сродкі адбіткаў пальцаў недаступныя."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Не ўдалося захаваць адбітак пальца"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Час чакання выйшаў. Паспрабуйце яшчэ раз."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Аперацыя з адбіткамі пальцаў скасавана."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Аўтэнтыфікацыя па адбітках пальцаў скасавана карыстальнікам."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Занадта шмат спроб. Паспрабуйце яшчэ раз пазней."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Занадта шмат спроб. Скарыстайце блакіроўку экрана."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Паўтарыце спробу."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Адбіткі пальцаў не зарэгістраваны."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"На гэтай прыладзе няма сканера адбіткаў пальцаў."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Датчык часова выключаны."</string> @@ -640,7 +645,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Звярніцеся ў сэрвісны цэнтр."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"Не ўдалося стварыць мадэль твару. Паўтарыце."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Занадта светла. Прыглушыце асвятленне."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Павялічце асвятленне"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"Перамясціце тэлефон далей"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Перамясціце тэлефон бліжэй"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Перамясціце тэлефон вышэй"</string> @@ -1253,8 +1259,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Запуск прыкладанняў."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"Завяршэнне загрузкі."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Вы націснулі кнопку сілкавання. Звычайна ў выніку гэтага дзеяння выключаецца экран.\n\nПадчас наладжвання адбітка пальца злёгку дакраніцеся да кнопкі."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Націсніце, каб выключыць экран"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Выключыць экран"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"Працягнуць спраўджанне адбітка пальца?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"Вы націснулі кнопку сілкавання. Звычайна ў выніку гэтага дзеяння выключаецца экран.\n\nКаб спраўдзіць адбітак пальца, злёгку дакраніцеся да кнопкі."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Выключыць экран"</string> diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml index b5d9125c0719..e5a6ba603077 100644 --- a/core/res/res/values-bg/strings.xml +++ b/core/res/res/values-bg/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Ползване на заключв. на екрана"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Въведете опцията си за заключване на екрана, за да продължите"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Натиснете добре върху сензора"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Отпечатъкът не бе обработен. Моля, опитайте отново."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Почистете сензора за отпечатъци и опитайте отново"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Почистете сензора и опитайте отново"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Натиснете добре върху сензора"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Преместихте пръста си твърде бавно. Моля, опитайте отново."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Опитайте с друг отпечатък"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Твърде светло е"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Опитайте да коригирате"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Всеки път променяйте леко позицията на пръста си"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Лицето е удостоверено. Моля, натиснете „Потвърждаване“"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Хардуерът за отпечатъци не е налице."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Не може да се настрои отпечатък"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Времето за изчакване за отпечатък изтече. Опитайте отново."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Операцията за отпечатък е анулирана."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Операцията за удостоверяване чрез отпечатък бе анулирана от потребителя."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Твърде много опити. Пробвайте отново по-късно."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Твърде много опити. Вместо това използвайте опция за заключване на екрана."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Опитайте отново."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Няма регистрирани отпечатъци."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Това устройство няма сензор за отпечатъци."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Сензорът е временно деактивиран."</string> @@ -638,7 +643,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Посетете оторизиран сервиз."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"Моделът на лицето ви не бе създаден. Опитайте пак."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Твърде светло е. Опитайте при по-слабо осветление."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Опитайте при по-силно осветление"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"Отдалечете телефона"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Доближете телефона"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Преместете телефона по-високо"</string> @@ -1251,8 +1257,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Приложенията се стартират."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"Зареждането завършва."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Натиснахте бутона за включване/изключване – това обикновено изключва екрана.\n\nОпитайте да докоснете леко, докато настройвате отпечатъка си."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Докоснете за изключване на екрана"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Изключване на екрана"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"Напред с потвърждаването на отпечатъка?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"Натиснахте бутона за включване/изключване – това обикновено изключва екрана.\n\nОпитайте да докоснете леко, за да потвърдите отпечатъка си."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Изключване на екрана"</string> diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml index 57b0a2306faf..68115ee1312f 100644 --- a/core/res/res/values-bn/strings.xml +++ b/core/res/res/values-bn/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"স্ক্রিন লক ব্যবহার করুন"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"চালিয়ে যেতে আপনার স্ক্রিন লক ব্যবহার করুন"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"সেন্সর জোরে প্রেস করুন"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"আঙ্গুলের ছাপ প্রক্রিয়া করা যায়নি৷ অনুগ্রহ করে আবার চেষ্টা করুন৷"</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"আঙ্গুলের ছাপের সেন্সর পরিষ্কার করে আবার চেষ্টা করুন"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"সেন্সর পরিষ্কার করে আবার চেষ্টা করুন"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"সেন্সর জোরে প্রেস করুন"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"আঙ্গুল খুব ধীরে সরানো হয়েছে৷ অনুগ্রহ করে আবার চেষ্টা করুন৷"</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"অন্য আঙ্গুলের ছাপ দিয়ে চেষ্টা করুন"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"অত্যন্ত উজ্জ্বল"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"অ্যাডজাস্ট করার চেষ্টা করুন"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"প্রতিবার আঙ্গুলের ছাপ সেটআপ করার সময় আপনার আঙ্গুলের অবস্থান সামান্য পরিবর্তন করুন"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"ফেস যাচাই করা হয়েছে, \'কনফার্ম করুন\' বোতাম প্রেস করুন"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"আঙ্গুলের ছাপ নেওয়ার হার্ডওয়্যার অনুপলব্ধ৷"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"আঙ্গুলের ছাপ সেট-আপ করতে পারছি না"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"আঙ্গুলের ছাপ নেওয়ার সময়সীমা শেষ হযেছে৷ আবার চেষ্টা করুন৷"</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"আঙ্গুলের ছাপ অপারেশন বাতিল করা হয়েছে৷"</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"ব্যবহারকারী আঙ্গুলের ছাপের অপারেশনটি বাতিল করেছেন।"</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"অনেকবার প্রচেষ্টা করা হয়েছে৷ পরে আবার চেষ্টা করুন৷"</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"অনেকবার চেষ্টা করেছেন। পরিবর্তে স্ক্রিন লক ব্যবহার করুন।"</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"আবার চেষ্টা করুন৷"</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"কোনও আঙ্গুলের ছাপ নথিভুক্ত করা হয়নি।"</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"এই ডিভাইসে আঙ্গুলের ছাপ নেওয়ার সেন্সর নেই।"</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"সেন্সর অস্থায়ীভাবে বন্ধ করা আছে।"</string> @@ -638,7 +643,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"একজন মেরামতি মিস্ত্রির কাছে যান।"</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"ফেস মডেল তৈরি করা যাচ্ছে না। আবার চেষ্টা করুন।"</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"খুব উজ্জ্বল। আলো কমিয়ে চেষ্টা করে দেখুন।"</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"আরও উজ্জ্বল আলো ব্যবহার করে দেখুন"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"ফোন আরও দূরে নিয়ে যান"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"ফোন আরও কাছে নিয়ে আসুন"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"ফোন আরও উঁচুতে তুলুন"</string> @@ -1251,8 +1257,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"অ্যাপ্লিকেশানগুলি শুরু করা হচ্ছে৷"</string> <string name="android_upgrading_complete" msgid="409800058018374746">"চালু করা সম্পূর্ণ হচ্ছে৷"</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"আপনি \'পাওয়ার\' বোতাম প্রেস করেছেন — এর ফলে সাধারণত স্ক্রিন বন্ধ হয়ে যায়।\n\nআঙ্গুলের ছাপ সেট-আপ করার সময় হালকাভাবে ট্যাপ করে দেখুন।"</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"স্ক্রিন বন্ধ করতে ট্যাপ করুন"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"স্ক্রিন বন্ধ করুন"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"আঙ্গুলের ছাপ যাচাই করা চালিয়ে যাবেন?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"আপনি \'পাওয়ার\' বোতাম প্রেস করেছেন — এর ফলে সাধারণত স্ক্রিন বন্ধ হয়ে যায়।\n\nআঙ্গুলের ছাপ যাচাই করতে হালকাভাবে ট্যাপ করে দেখুন।"</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"স্ক্রিন বন্ধ করুন"</string> diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml index 39b7e62a4bf8..7411ae34b526 100644 --- a/core/res/res/values-bs/strings.xml +++ b/core/res/res/values-bs/strings.xml @@ -587,13 +587,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Koristi zaključavanje ekrana"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Unesite zaključavanje ekrana da nastavite"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Čvrsto pritisnite senzor"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Obrada otiska prsta nije uspjela. Pokušajte ponovo."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Očistite senzor za otisak prsta i pokušajte ponovo"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Očistite senzor i pokušajte ponovo"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Čvrsto pritisnite senzor"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Presporo ste pomjerili prst. Pokušajte ponovo."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Pokušajte s drugim otiskom prsta"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Presvijetlo"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Pokušajte podesiti"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Svaki put pomalo promijenite položaj prsta"</string> <string-array name="fingerprint_acquired_vendor"> @@ -605,13 +608,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Lice je provjereno, pritisnite dugme za potvrdu"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Hardver za otisak prsta nije dostupan."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Nije moguće postaviti otisak prsta"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Vrijeme za prepoznavanje otiska prsta je isteklo. Pokušajte ponovo."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Radnja s otiskom prsta je otkazana."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Korisnik je otkazao radnju s otiskom prsta."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Previše pokušaja. Pokušajte ponovo kasnije."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Previše pokušaja. Umjesto toga koristite zaključavanje ekrana."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Pokušajte ponovo."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Nije prijavljen nijedan otisak prsta."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Ovaj uređaj nema senzor za otisak prsta."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Senzor je privremeno onemogućen."</string> @@ -639,7 +644,7 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Posjetite pružaoca usluga za popravke."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"Nije moguće kreirati model lica. Pokušajte ponovo."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Previše svijetlo. Probajte s blažim osvjetljenjem."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Pokušajte s jačim osvjetljenjem"</string> + <string name="face_acquired_too_dark" msgid="8539853432479385326">"Nema dovoljno svjetla"</string> <string name="face_acquired_too_close" msgid="4453646176196302462">"Odmaknite telefon"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Primaknite telefon"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Pomjerite telefon naviše"</string> @@ -1252,8 +1257,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Pokretanje aplikacija."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"Pokretanje pri kraju."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Pritisnuli ste dugme za uključivanje. Tako se obično isključuje ekran.\n\nPokušajte ga lagano dodirnuti dok postavljate otisak prsta."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Dodirnite da isključite ekran"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Isključi ekran"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"Nastaviti s potvrđivanjem otiska prsta?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"Pritisnuli ste dugme za uključivanje. Tako se obično isključuje ekran.\n\nPokušajte ga lagano dodirnuti da potvrdite otisak prsta."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Isključi ekran"</string> diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml index daf12031c4df..cc03bba7796e 100644 --- a/core/res/res/values-ca/strings.xml +++ b/core/res/res/values-ca/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Utilitza el bloqueig de pantalla"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Introdueix el teu bloqueig de pantalla per continuar"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Prem el sensor de manera ferma"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"No s\'ha pogut processar l\'empremta digital. Torna-ho a provar."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Neteja el sensor d\'empremtes digitals i torna-ho a provar"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Neteja el sensor i torna-ho a provar"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Prem el sensor de manera ferma"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"El dit s\'ha mogut massa lentament. Torna-ho a provar."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Prova una altra empremta digital"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Hi ha massa llum"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Prova d\'ajustar l\'empremta digital"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Canvia lleugerament la posició del dit en cada intent"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Cara autenticada; prem el botó per confirmar"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"El maquinari d\'empremtes digitals no està disponible."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"No es pot configurar l\'empremta digital"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"S\'ha esgotat el temps d\'espera per a l\'empremta digital. Torna-ho a provar."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"S\'ha cancel·lat l\'operació d\'empremta digital."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"L\'usuari ha cancel·lat l\'operació d\'empremta digital."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"S\'han produït massa intents. Torna-ho a provar més tard."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Massa intents. Utilitza el bloqueig de pantalla."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Torna-ho a provar."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"No s\'ha registrat cap empremta digital."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Aquest dispositiu no té sensor d\'empremtes digitals."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"El sensor està desactivat temporalment."</string> @@ -638,7 +643,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Visita un proveïdor de reparacions."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"No es pot crear el model facial. Torna-ho a provar."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Massa brillant Prova una il·luminació més suau."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Prova amb més il·luminació"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"Allunya\'t del telèfon"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Apropa el telèfon"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Mou el telèfon més amunt"</string> @@ -1251,8 +1257,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"S\'estan iniciant les aplicacions."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"S\'està finalitzant l\'actualització."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Has premut el botó d\'engegada, fet que sol apagar la pantalla.\n\nProva de tocar-lo lleugerament en configurar l\'empremta digital."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Toca per apagar la pantalla"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Apaga la pantalla"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"Vols continuar verificant l\'empremta?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"Has premut el botó d\'engegada, fet que sol apagar la pantalla.\n\nProva de tocar-lo lleugerament per verificar l\'empremta digital."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Apaga la pantalla"</string> diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml index 9e96104dbdc4..2a052791d03f 100644 --- a/core/res/res/values-cs/strings.xml +++ b/core/res/res/values-cs/strings.xml @@ -588,13 +588,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Použít zámek obrazovky"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Pokračujte zadáním zámku obrazovky"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Pevně zatlačte na senzor"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Zpracování otisku prstu se nezdařilo. Zkuste to znovu."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Vyčistěte snímač otisků prstů a zkuste to znovu"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Vyčistěte senzor a zkuste to znovu"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Zatlačte silně na senzor"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Pohyb prstem byl příliš pomalý. Zkuste to znovu."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Zkuste jiný otisk prstu"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Je příliš světlo"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Zkuste provést úpravu"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Pokaždé lehce změňte polohu prstu"</string> <string-array name="fingerprint_acquired_vendor"> @@ -606,13 +609,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Obličej byl ověřen, stiskněte tlačítko pro potvrzení"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Není k dispozici hardware ke snímání otisků prstů."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Otisk prstu se nepodařilo nastavit"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Časový limit sejmutí otisku prstu vypršel. Zkuste to znovu."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Operace otisku prstu byla zrušena."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Uživatel operaci s otiskem prstu zrušil."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Příliš mnoho pokusů. Zkuste to později."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Příliš mnoho pokusů. Použijte zámek obrazovky."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Zkuste to znovu."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Nejsou zaregistrovány žádné otisky prstů."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Toto zařízení nemá snímač otisků prstů."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Senzor je dočasně deaktivován."</string> @@ -640,7 +645,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Navštivte servis"</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"Model se nepodařilo vytvořit. Zkuste to znovu."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Je příliš světlo. Zmírněte osvětlení."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Přejděte na světlo"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"Umístěte telefon dál"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Umístěte telefon blíž"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Umístěte telefon výš"</string> @@ -1253,8 +1259,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Spouštění aplikací."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"Dokončování inicializace."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Stiskli jste vypínač – tím se obvykle vypíná obrazovka.\n\nPři nastavování otisku prstu je třeba klepat lehce."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Klepnutím vypnete obrazovku"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Vypnout obrazovku"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"Pokračovat v ověřování otisku prstu?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"Stiskli jste vypínač – tím se obvykle vypíná obrazovka.\n\nZkuste lehkým klepnutím ověřit svůj otisk prstu."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Vypnout obrazovku"</string> diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml index 8f70d36d9153..9099ec67c120 100644 --- a/core/res/res/values-da/strings.xml +++ b/core/res/res/values-da/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Brug skærmlås"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Angiv din skærmlås for at fortsætte"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Hold fingeren nede på læseren"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Fingeraftrykket kunne ikke behandles. Prøv igen."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Rengør fingeraftrykslæseren, og prøv igen"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Rengør læseren, og prøv igen"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Hold fingeren nede på læseren"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Du bevægede fingeren for langsomt. Prøv igen."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Prøv med et andet fingeraftryk"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Der er for lyst"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Prøv at justere den"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Flyt fingeren en smule hver gang"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Ansigtet er godkendt. Tryk på Bekræft."</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Hardwaren til fingeraftryk er ikke tilgængelig."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Fingeraftrykket kan ikke gemmes"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Registrering af fingeraftryk fik timeout. Prøv igen."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Fingeraftrykshandlingen blev annulleret."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Fingeraftrykshandlingen blev annulleret af brugeren."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Du har prøvet for mange gange. Prøv igen senere."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Du har brugt for mange forsøg. Brug skærmlåsen i stedet."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Prøv igen."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Der er ikke registreret nogen fingeraftryk."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Denne enhed har ingen fingeraftrykslæser."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Sensoren er midlertidigt deaktiveret."</string> @@ -638,7 +643,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Få den repareret."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"Din ansigtsmodel kan ikke oprettes. Prøv igen."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Der er for lyst. Prøv en mere dæmpet belysning."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Prøv med mere belysning"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"Flyt telefonen længere væk"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Flyt telefonen tættere på"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Løft telefonen højere op"</string> @@ -1251,8 +1257,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Åbner dine apps."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"Gennemfører start."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Du har trykket på afbryderknappen, hvilket som regel slukker skærmen.\n\nPrøv at trykke let på knappen, mens du konfigurerer dit fingeraftryk."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Tryk for at slukke skærmen"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Sluk skærm"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"Vil du bekræfte dit fingeraftryk?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"Du har trykket på afbryderknappen, hvilket som regel slukker skærmen.\n\nPrøv at trykke let på knappen for at bekræfte dit fingeraftryk."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Sluk skærm"</string> diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml index 64ef8e1be759..9a4e3b226160 100644 --- a/core/res/res/values-de/strings.xml +++ b/core/res/res/values-de/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Displaysperre verwenden"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Displaysperre eingeben, um fortzufahren"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Drücke fest auf den Sensor"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Fingerabdruck konnte nicht verarbeitet werden. Bitte versuche es noch einmal."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Reinige den Fingerabdrucksensor und versuch es noch einmal"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Reinige den Sensor und versuche es noch einmal"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Drücke fest auf den Sensor"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Finger zu langsam bewegt. Bitte versuche es noch einmal."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Anderen Fingerabdruck verwenden"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Zu hell"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Versuche, den Finger anders aufzulegen"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Ändere jedes Mal leicht die Position deines Fingers"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Gesicht authentifiziert, bitte bestätigen"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Fingerabdruckhardware nicht verfügbar"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Fingerabdruck konnte nicht eingerichtet werden"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Zeitüberschreitung bei Fingerabdruck. Bitte versuche es noch einmal."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Fingerabdruckvorgang abgebrochen"</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Vorgang der Fingerabdruckauthentifizierung vom Nutzer abgebrochen."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Zu viele Versuche, bitte später noch einmal versuchen"</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Zu viele Versuche. Verwende stattdessen die Displaysperre."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Bitte versuche es noch einmal."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Keine Fingerabdrücke erfasst."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Dieses Gerät hat keinen Fingerabdrucksensor."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Der Sensor ist vorübergehend deaktiviert."</string> @@ -638,7 +643,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Suche einen Reparaturdienstleister auf."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"Kein Gesichtsmodell möglich. Versuche es erneut."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Zu hell. Schwächere Beleuchtung ausprobieren."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Probiere es mit einer helleren Beleuchtung"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"Bewege das Smartphone weiter weg"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Bewege das Smartphone näher heran"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Bewege das Smartphone nach oben"</string> @@ -1251,8 +1257,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Apps werden gestartet..."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"Start wird abgeschlossen..."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Du hast die Ein-/Aus-Taste gedrückt — damit wird der Bildschirm ausgeschaltet.\n\nTippe die Taste leicht an, um deinen Fingerabdruck einzurichten."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Tippen, um Display auszuschalten"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Display ausschalten"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"Mit der Fingerabdruckprüfung fortfahren?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"Du hast die Ein-/Aus-Taste gedrückt — damit wird der Bildschirm ausgeschaltet.\n\nTippe die Taste leicht an, um mit deinem Fingerabdruck deine Identität zu bestätigen."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Ausschalten"</string> diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml index cca5c9f512dd..00c11f3ea5e2 100644 --- a/core/res/res/values-el/strings.xml +++ b/core/res/res/values-el/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Χρήση κλειδώματος οθόνης"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Χρησιμοποιήστε το κλείδωμα οθόνης για να συνεχίσετε"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Πιέστε σταθερά τον αισθητήρα"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Δεν ήταν δυνατή η επεξεργασία του δακτυλικού αποτυπώματος. Δοκιμάστε ξανά."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Καθαρίστε τον αισθητήρα δακτυλικών αποτυπωμάτων και δοκιμάστε ξανά"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Καθαρίστε τον αισθητήρα και δοκιμάστε ξανά"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Πιέστε σταθερά τον αισθητήρα"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Πολύ αργή κίνηση δαχτύλου. Δοκιμάστε ξανά."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Δοκιμάστε άλλο δακτυλικό αποτύπωμα"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Υπερβολικά έντονος φωτισμός"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Δοκιμάστε να το προσαρμόσετε"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Αλλάζετε ελαφρώς τη θέση του δακτύλου σας κάθε φορά."</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Έγινε έλεγχος ταυτότητας προσώπου, πατήστε \"Επιβεβαίωση\""</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Ο εξοπλισμός δακτυλικού αποτυπώματος δεν είναι διαθέσιμος."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Δεν είναι δυνατή η ρύθμιση του δακτυλικού αποτυπώματος"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Λήξη χρονικού ορίου δακτυλικού αποτυπώματος. Δοκιμάστε ξανά."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Η λειτουργία δακτυλικού αποτυπώματος ακυρώθηκε."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Η λειτουργία δακτυλικού αποτυπώματος ακυρώθηκε από τον χρήστη."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Πάρα πολλές προσπάθειες. Δοκιμάστε ξανά αργότερα."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Υπερβολικά πολλές προσπάθειες. Χρησιμοποιήστε εναλλακτικά το κλείδωμα οθόνης."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Δοκιμάστε ξανά."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Δεν έχουν καταχωριστεί δακτυλικά αποτυπώματα."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Αυτή η συσκευή δεν διαθέτει αισθητήρα δακτυλικού αποτυπώματος."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Ο αισθητήρας απενεργοποιήθηκε προσωρινά."</string> @@ -638,7 +643,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Επισκεφτείτε έναν πάροχο υπηρεσιών επισκευής."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"Αδύν. η δημιουρ. του μοντ. προσώπ. Δοκιμάστε ξανά."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Υπερβολικά έντονος φωτισμός. Δοκιμάστε πιο ήπιο."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Δοκιμάστε με περισσότερο φως"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"Απομακρύνετε περισσότερο το τηλέφωνο"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Φέρτε πιο κοντά το τηλέφωνό σας"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Μετακινήστε το τηλέφωνο πιο ψηλά"</string> @@ -1251,8 +1257,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Έναρξη εφαρμογών."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"Ολοκλήρωση εκκίνησης."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Πατήσατε το κουμπί λειτουργίας. Αυτό συνήθως απενεργοποιεί την οθόνη.\n\nΔοκιμάστε να πατήσετε απαλά κατά τη ρύθμιση του δακτυλικού σας αποτυπώματος."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Πατήστε για απενεργοποίηση οθόνης"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Απενεργοπ. οθόνης"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"Συνέχιση επαλήθευσης δακτ. αποτυπώματος;"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"Πατήσατε το κουμπί λειτουργίας. Αυτό συνήθως απενεργοποιεί την οθόνη.\n\nΔοκιμάστε να πατήστε απαλά για να επαληθεύσετε το δακτυλικό σας αποτύπωμα."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Απενεργοπ. οθόνης"</string> diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml index d0351a798232..8af6b4dfae2d 100644 --- a/core/res/res/values-en-rAU/strings.xml +++ b/core/res/res/values-en-rAU/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Use screen lock"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Enter your screen lock to continue"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Press firmly on the sensor"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Couldn\'t process fingerprint. Please try again."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Clean fingerprint sensor and try again"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Clean sensor and try again"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Press firmly on the sensor"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Finger moved too slow. Please try again."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Try another fingerprint"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Too bright"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Try adjusting"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Change the position of your finger slightly each time"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,12 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Face authenticated. Please press confirm"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Fingerprint hardware not available."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Can’t set up fingerprint"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Fingerprint timeout reached. Try again."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Fingerprint operation cancelled."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Fingerprint operation cancelled by user."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Too many attempts. Try again later."</string> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Too many attempts. Use screen lock instead."</string> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Try again."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> + <skip /> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"No fingerprints enrolled."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"This device does not have a fingerprint sensor."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Sensor temporarily disabled."</string> @@ -637,7 +643,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Visit a repair provider."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"Can’t create your face model. Try again."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Too bright. Try gentler lighting."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Try brighter lighting"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"Move phone further away"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Move phone closer"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Move phone higher"</string> @@ -1250,8 +1257,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Starting apps."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"Finishing boot."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"You pressed the power button – this usually turns off the screen.\n\nTry tapping lightly while setting up your fingerprint."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Tap to turn off screen"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Turn off screen"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"Continue verifying your fingerprint?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"You pressed the power button – this usually turns off the screen.\n\nTry tapping lightly to verify your fingerprint."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Turn off screen"</string> diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml index cb4f71edcbc7..32cc5dee4de6 100644 --- a/core/res/res/values-en-rCA/strings.xml +++ b/core/res/res/values-en-rCA/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Use screen lock"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Enter your screen lock to continue"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Press firmly on the sensor"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Couldn\'t process fingerprint. Please try again."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Clean fingerprint sensor and try again"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Clean sensor and try again"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Press firmly on the sensor"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Finger moved too slow. Please try again."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Try another fingerprint"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Too bright"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Try adjusting"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Change the position of your finger slightly each time"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,12 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Face authenticated. Please press confirm"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Fingerprint hardware not available."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Can’t set up fingerprint"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Fingerprint timeout reached. Try again."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Fingerprint operation cancelled."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Fingerprint operation cancelled by user."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Too many attempts. Try again later."</string> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Too many attempts. Use screen lock instead."</string> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Try again."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> + <skip /> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"No fingerprints enrolled."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"This device does not have a fingerprint sensor."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Sensor temporarily disabled."</string> @@ -637,7 +643,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Visit a repair provider."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"Can’t create your face model. Try again."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Too bright. Try gentler lighting."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Try brighter lighting"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"Move phone further away"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Move phone closer"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Move phone higher"</string> @@ -1250,8 +1257,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Starting apps."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"Finishing boot."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"You pressed the power button – this usually turns off the screen.\n\nTry tapping lightly while setting up your fingerprint."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Tap to turn off screen"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Turn off screen"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"Continue verifying your fingerprint?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"You pressed the power button – this usually turns off the screen.\n\nTry tapping lightly to verify your fingerprint."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Turn off screen"</string> diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml index 8c31f7b13580..fd351df1dd88 100644 --- a/core/res/res/values-en-rGB/strings.xml +++ b/core/res/res/values-en-rGB/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Use screen lock"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Enter your screen lock to continue"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Press firmly on the sensor"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Couldn\'t process fingerprint. Please try again."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Clean fingerprint sensor and try again"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Clean sensor and try again"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Press firmly on the sensor"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Finger moved too slow. Please try again."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Try another fingerprint"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Too bright"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Try adjusting"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Change the position of your finger slightly each time"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,12 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Face authenticated. Please press confirm"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Fingerprint hardware not available."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Can’t set up fingerprint"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Fingerprint timeout reached. Try again."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Fingerprint operation cancelled."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Fingerprint operation cancelled by user."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Too many attempts. Try again later."</string> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Too many attempts. Use screen lock instead."</string> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Try again."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> + <skip /> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"No fingerprints enrolled."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"This device does not have a fingerprint sensor."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Sensor temporarily disabled."</string> @@ -637,7 +643,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Visit a repair provider."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"Can’t create your face model. Try again."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Too bright. Try gentler lighting."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Try brighter lighting"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"Move phone further away"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Move phone closer"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Move phone higher"</string> @@ -1250,8 +1257,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Starting apps."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"Finishing boot."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"You pressed the power button – this usually turns off the screen.\n\nTry tapping lightly while setting up your fingerprint."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Tap to turn off screen"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Turn off screen"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"Continue verifying your fingerprint?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"You pressed the power button – this usually turns off the screen.\n\nTry tapping lightly to verify your fingerprint."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Turn off screen"</string> diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml index cdce2f09e669..1b0bf8e89ebb 100644 --- a/core/res/res/values-en-rIN/strings.xml +++ b/core/res/res/values-en-rIN/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Use screen lock"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Enter your screen lock to continue"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Press firmly on the sensor"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Couldn\'t process fingerprint. Please try again."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Clean fingerprint sensor and try again"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Clean sensor and try again"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Press firmly on the sensor"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Finger moved too slow. Please try again."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Try another fingerprint"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Too bright"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Try adjusting"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Change the position of your finger slightly each time"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,12 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Face authenticated. Please press confirm"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Fingerprint hardware not available."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Can’t set up fingerprint"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Fingerprint timeout reached. Try again."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Fingerprint operation cancelled."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Fingerprint operation cancelled by user."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Too many attempts. Try again later."</string> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Too many attempts. Use screen lock instead."</string> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Try again."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> + <skip /> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"No fingerprints enrolled."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"This device does not have a fingerprint sensor."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Sensor temporarily disabled."</string> @@ -637,7 +643,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Visit a repair provider."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"Can’t create your face model. Try again."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Too bright. Try gentler lighting."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Try brighter lighting"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"Move phone further away"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Move phone closer"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Move phone higher"</string> @@ -1250,8 +1257,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Starting apps."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"Finishing boot."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"You pressed the power button – this usually turns off the screen.\n\nTry tapping lightly while setting up your fingerprint."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Tap to turn off screen"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Turn off screen"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"Continue verifying your fingerprint?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"You pressed the power button – this usually turns off the screen.\n\nTry tapping lightly to verify your fingerprint."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Turn off screen"</string> diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml index c29ad1a7ebde..60675ba05356 100644 --- a/core/res/res/values-en-rXC/strings.xml +++ b/core/res/res/values-en-rXC/strings.xml @@ -586,13 +586,14 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Use screen lock"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Enter your screen lock to continue"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Press firmly on the sensor"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Couldn\'t process fingerprint. Please try again."</string> + <string name="fingerprint_acquired_insufficient" msgid="623888149088216458">"Can’t recognize fingerprint. Try again."</string> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Clean fingerprint sensor and try again"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Clean sensor and try again"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Press firmly on the sensor"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Finger moved too slow. Please try again."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Try another fingerprint"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Too bright"</string> + <string name="fingerprint_acquired_power_press" msgid="3107864151278434961">"Power press detected"</string> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Try adjusting"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Change the position of your finger slightly each time"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,12 +605,12 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Face authenticated, please press confirm"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Fingerprint hardware not available."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Can’t set up fingerprint"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Fingerprint time out reached. Try again."</string> + <string name="fingerprint_error_timeout" msgid="7361192266621252164">"Fingerprint setup timed out. Try again."</string> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Fingerprint operation canceled."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Fingerprint operation canceled by user."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Too many attempts. Try again later."</string> + <string name="fingerprint_error_lockout" msgid="6626753679019351368">"Too many attempts. Use screen lock instead."</string> <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Too many attempts. Use screen lock instead."</string> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Try again."</string> + <string name="fingerprint_error_unable_to_process" msgid="2446280592818621224">"Can’t process fingerprint. Try again."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"No fingerprints enrolled."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"This device does not have a fingerprint sensor."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Sensor temporarily disabled."</string> @@ -637,7 +638,7 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Visit a repair provider."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"Can’t create your face model. Try again."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Too bright. Try gentler lighting."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Try brighter lighting"</string> + <string name="face_acquired_too_dark" msgid="8539853432479385326">"Not enough light"</string> <string name="face_acquired_too_close" msgid="4453646176196302462">"Move phone farther away"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Move phone closer"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Move phone higher"</string> @@ -1250,8 +1251,8 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Starting apps."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"Finishing boot."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"You pressed the power button — this usually turns off the screen.\n\nTry tapping lightly while setting up your fingerprint."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Tap to turn off screen"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Turn off screen"</string> + <string name="fp_power_button_enrollment_title" msgid="6976841690455338563">"To end setup, turn off screen"</string> + <string name="fp_power_button_enrollment_button_text" msgid="3199783266386029200">"Turn off"</string> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"Continue verifying your fingerprint?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"You pressed the power button — this usually turns off the screen.\n\nTry tapping lightly to verify your fingerprint."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Turn off screen"</string> diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml index 9e968fcc64e3..66bee60c87b5 100644 --- a/core/res/res/values-es-rUS/strings.xml +++ b/core/res/res/values-es-rUS/strings.xml @@ -51,6 +51,7 @@ <string name="needPuk2" msgid="7032612093451537186">"Escribir PUK2 para desbloquear la tarjeta SIM."</string> <string name="enablePin" msgid="2543771964137091212">"Error; habilita el bloqueo de SIM/RUIM."</string> <plurals name="pinpuk_attempts" formatted="false" msgid="1619867269012213584"> + <item quantity="many">You have <xliff:g id="NUMBER_1">%d</xliff:g> remaining attempts before SIM is locked.</item> <item quantity="other">Tienes <xliff:g id="NUMBER_1">%d</xliff:g> intentos más antes de que se bloquee la tarjeta SIM.</item> <item quantity="one">Tienes <xliff:g id="NUMBER_0">%d</xliff:g> un intento más antes de que se bloquee la tarjeta SIM.</item> </plurals> @@ -180,7 +181,7 @@ <string name="low_memory" product="watch" msgid="3479447988234030194">"El almacenamiento del reloj está completo. Elimina algunos archivos para liberar espacio."</string> <string name="low_memory" product="tv" msgid="6663680413790323318">"El almacenamiento del dispositivo Android TV está lleno. Borra algunos archivos para liberar espacio."</string> <string name="low_memory" product="default" msgid="2539532364144025569">"Se ha agotado el espacio de almacenamiento del dispositivo. Elimina algunos archivos para liberar espacio."</string> - <string name="ssl_ca_cert_warning" msgid="7233573909730048571">"{count,plural, =1{Se instaló la autoridad certificadora}other{Se instalaron las autoridades certificadoras}}"</string> + <string name="ssl_ca_cert_warning" msgid="7233573909730048571">"{count,plural, =1{Se instaló la autoridad certificadora}many{Se instalaron las autoridades certificadoras}other{Se instalaron las autoridades certificadoras}}"</string> <string name="ssl_ca_cert_noti_by_unknown" msgid="4961102218216815242">"Por un tercero desconocido"</string> <string name="ssl_ca_cert_noti_by_administrator" msgid="4564941950768783879">"Por parte de tu administrador del perfil de trabajo"</string> <string name="ssl_ca_cert_noti_managed" msgid="217337232273211674">"Por <xliff:g id="MANAGING_DOMAIN">%s</xliff:g>"</string> @@ -254,7 +255,7 @@ <string name="bugreport_option_interactive_summary" msgid="8493795476325339542">"Usa esta opción en la mayoría de los casos. Te permite realizar un seguimiento del progreso del informe, ingresar más detalles acerca del problema y tomar capturas de pantalla. Es posible que se omitan secciones menos usadas cuyos informes demoran más en completarse."</string> <string name="bugreport_option_full_title" msgid="7681035745950045690">"Informe completo"</string> <string name="bugreport_option_full_summary" msgid="1975130009258435885">"Usa esta opción para reducir al mínimo la interferencia del sistema cuando tu dispositivo no responde o funciona muy lento, o cuando necesitas todas las secciones del informe. No permite ingresar más detalles ni tomar capturas de pantalla adicionales."</string> - <string name="bugreport_countdown" msgid="6418620521782120755">"{count,plural, =1{Se tomará una captura de pantalla para el informe de errores en # segundo.}other{Se tomará una captura de pantalla para el informe de errores en # segundos.}}"</string> + <string name="bugreport_countdown" msgid="6418620521782120755">"{count,plural, =1{Se tomará una captura de pantalla para el informe de errores en # segundo.}many{Se tomará una captura de pantalla para el informe de errores en # segundos.}other{Se tomará una captura de pantalla para el informe de errores en # segundos.}}"</string> <string name="bugreport_screenshot_success_toast" msgid="7986095104151473745">"Se tomó la captura de pantalla con el informe de errores"</string> <string name="bugreport_screenshot_failure_toast" msgid="6736320861311294294">"No se pudo tomar la captura de pantalla con el informe de errores"</string> <string name="global_action_toggle_silent_mode" msgid="8464352592860372188">"Modo silencioso"</string> @@ -586,13 +587,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Usar bloqueo de pantalla"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Ingresa tu bloqueo de pantalla para continuar"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Presiona con firmeza el sensor"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"No se pudo procesar la huella dactilar. Vuelve a intentarlo."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Limpia el sensor de huellas dactilares y vuelve a intentarlo"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Limpia el sensor y vuelve a intentarlo"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Presiona con firmeza el sensor"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Moviste el dedo muy lento. Vuelve a intentarlo."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Prueba con otra huella dactilar"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Demasiada luz"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Prueba ajustarla"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Cambia un poco la posición del dedo cada vez"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +608,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Se autenticó el rostro; presiona Confirmar"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"El hardware para detectar huellas dactilares no está disponible."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"No se puede configurar la huella dactilar"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Finalizó el tiempo de espera para la huella dactilar. Vuelve a intentarlo."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Se canceló la operación de huella dactilar."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"El usuario canceló la operación de huella dactilar."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Demasiados intentos. Vuelve a intentarlo más tarde."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Demasiados intentos. Utiliza el bloqueo de pantalla en su lugar."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Vuelve a intentarlo."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"No se registraron huellas digitales."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Este dispositivo no tiene sensor de huellas dactilares."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Se inhabilitó temporalmente el sensor."</string> @@ -638,7 +644,7 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Consulta a un proveedor de reparaciones."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"No se puede crear modelo de rostro. Reinténtalo."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Demasiado brillante. Prueba con menos iluminación."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Prueba con más iluminación"</string> + <string name="face_acquired_too_dark" msgid="8539853432479385326">"No hay suficiente luz"</string> <string name="face_acquired_too_close" msgid="4453646176196302462">"Aleja el teléfono un poco más"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Acerca el teléfono"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Mueve el teléfono hacia arriba"</string> @@ -1088,7 +1094,7 @@ <string name="enable_explore_by_touch_warning_message" product="default" msgid="4312979647356179250">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> desea activar la exploración táctil. Cuando esta función esté activada, podrás escuchar o ver descripciones del contenido seleccionado o usar gestos para interactuar con el dispositivo."</string> <string name="oneMonthDurationPast" msgid="4538030857114635777">"Hace 1 mes."</string> <string name="beforeOneMonthDurationPast" msgid="8315149541372065392">"Anterior a 1 mes atrás"</string> - <string name="last_num_days" msgid="2393660431490280537">"{count,plural, =1{Último # día}other{Últimos # días}}"</string> + <string name="last_num_days" msgid="2393660431490280537">"{count,plural, =1{Último # día}many{Últimos # días}other{Últimos # días}}"</string> <string name="last_month" msgid="1528906781083518683">"Último mes"</string> <string name="older" msgid="1645159827884647400">"Antiguos"</string> <string name="preposition_for_date" msgid="2780767868832729599">"activado <xliff:g id="DATE">%s</xliff:g>"</string> @@ -1115,14 +1121,14 @@ <string name="duration_hours_shortest_future" msgid="2979276794547981674">"en <xliff:g id="COUNT">%d</xliff:g> h"</string> <string name="duration_days_shortest_future" msgid="3392722163935571543">"en <xliff:g id="COUNT">%d</xliff:g> d"</string> <string name="duration_years_shortest_future" msgid="5537464088352970388">"en <xliff:g id="COUNT">%d</xliff:g> años"</string> - <string name="duration_minutes_relative" msgid="8620337701051015593">"{count,plural, =1{Hace # minuto}other{Hace # minutos}}"</string> - <string name="duration_hours_relative" msgid="4836449961693180253">"{count,plural, =1{Hace # hora}other{Hace # horas}}"</string> - <string name="duration_days_relative" msgid="621965767567258302">"{count,plural, =1{Hace # día}other{Hace # días}}"</string> - <string name="duration_years_relative" msgid="8731202348869424370">"{count,plural, =1{Hace # año}other{Hace # años}}"</string> - <string name="duration_minutes_relative_future" msgid="5259574171747708115">"{count,plural, =1{# minuto}other{# minutos}}"</string> - <string name="duration_hours_relative_future" msgid="6670440478481140565">"{count,plural, =1{# hora}other{# horas}}"</string> - <string name="duration_days_relative_future" msgid="8870658635774250746">"{count,plural, =1{# día}other{# días}}"</string> - <string name="duration_years_relative_future" msgid="8855853883925918380">"{count,plural, =1{# año}other{# años}}"</string> + <string name="duration_minutes_relative" msgid="8620337701051015593">"{count,plural, =1{Hace # minuto}many{Hace # minutos}other{Hace # minutos}}"</string> + <string name="duration_hours_relative" msgid="4836449961693180253">"{count,plural, =1{Hace # hora}many{Hace # horas}other{Hace # horas}}"</string> + <string name="duration_days_relative" msgid="621965767567258302">"{count,plural, =1{Hace # día}many{Hace # días}other{Hace # días}}"</string> + <string name="duration_years_relative" msgid="8731202348869424370">"{count,plural, =1{Hace # año}many{Hace # años}other{Hace # años}}"</string> + <string name="duration_minutes_relative_future" msgid="5259574171747708115">"{count,plural, =1{# minuto}many{# minutos}other{# minutos}}"</string> + <string name="duration_hours_relative_future" msgid="6670440478481140565">"{count,plural, =1{# hora}many{# horas}other{# horas}}"</string> + <string name="duration_days_relative_future" msgid="8870658635774250746">"{count,plural, =1{# día}many{# días}other{# días}}"</string> + <string name="duration_years_relative_future" msgid="8855853883925918380">"{count,plural, =1{# año}many{# años}other{# años}}"</string> <string name="VideoView_error_title" msgid="5750686717225068016">"Problemas de video"</string> <string name="VideoView_error_text_invalid_progressive_playback" msgid="3782449246085134720">"No es posible transmitir este video al dispositivo."</string> <string name="VideoView_error_text_unknown" msgid="7658683339707607138">"No se puede reproducir el video."</string> @@ -1251,8 +1257,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Iniciando aplicaciones"</string> <string name="android_upgrading_complete" msgid="409800058018374746">"Finalizando el inicio"</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Presionaste el botón de encendido. Por lo general, esta acción apaga la pantalla.\n\nPresiona suavemente mientras configuras tu huella dactilar."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Presiona para apagar la pantalla"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Apagar pantalla"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"¿Verificar huella dactilar?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"Presionaste el botón de encendido. Por lo general, esta acción apaga la pantalla.\n\nPresiona suavemente para verificar tu huella dactilar."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Apagar pantalla"</string> @@ -1509,7 +1517,7 @@ <string name="skip_button_label" msgid="3566599811326688389">"Omitir"</string> <string name="no_matches" msgid="6472699895759164599">"Sin coincidencias"</string> <string name="find_on_page" msgid="5400537367077438198">"Buscar en la página"</string> - <string name="matches_found" msgid="2296462299979507689">"{count,plural, =1{# coincidencia}other{# de {total}}}"</string> + <string name="matches_found" msgid="2296462299979507689">"{count,plural, =1{# coincidencia}many{# de {total}}other{# de {total}}}"</string> <string name="action_mode_done" msgid="2536182504764803222">"Listo"</string> <string name="progress_erasing" msgid="6891435992721028004">"Borrando almacenamiento compartido…"</string> <string name="share" msgid="4157615043345227321">"Compartir"</string> @@ -1862,14 +1870,14 @@ <string name="data_saver_description" msgid="4995164271550590517">"Para reducir el uso de datos, el modo Ahorro de datos evita que algunas apps envíen y reciban datos en segundo plano. La app que estés usando podrá acceder a los datos, pero con menor frecuencia. De esta forma, por ejemplo, las imágenes no se mostrarán hasta que las presiones."</string> <string name="data_saver_enable_title" msgid="7080620065745260137">"¿Deseas activar Ahorro de datos?"</string> <string name="data_saver_enable_button" msgid="4399405762586419726">"Activar"</string> - <string name="zen_mode_duration_minutes_summary" msgid="4555514757230849789">"{count,plural, =1{Por un minuto (hasta {formattedTime})}other{Por # minutos (hasta {formattedTime})}}"</string> - <string name="zen_mode_duration_minutes_summary_short" msgid="1187553788355486950">"{count,plural, =1{Durante 1 min (hasta {formattedTime})}other{Durante # min (hasta {formattedTime})}}"</string> - <string name="zen_mode_duration_hours_summary" msgid="3866333100793277211">"{count,plural, =1{Durante 1 hora (hasta {formattedTime})}other{Durante # horas (hasta {formattedTime})}}"</string> - <string name="zen_mode_duration_hours_summary_short" msgid="687919813833347945">"{count,plural, =1{Durante 1 h (hasta {formattedTime})}other{Durante # h (hasta {formattedTime})}}"</string> - <string name="zen_mode_duration_minutes" msgid="2340007982276569054">"{count,plural, =1{Durante un minuto}other{Durante # minutos}}"</string> - <string name="zen_mode_duration_minutes_short" msgid="2435756450204526554">"{count,plural, =1{Durante 1 min}other{Durante # min}}"</string> - <string name="zen_mode_duration_hours" msgid="7841806065034711849">"{count,plural, =1{Durante 1 hora}other{Durante # horas}}"</string> - <string name="zen_mode_duration_hours_short" msgid="3666949653933099065">"{count,plural, =1{Durante 1 h}other{Durante # h}}"</string> + <string name="zen_mode_duration_minutes_summary" msgid="4555514757230849789">"{count,plural, =1{Por un minuto (hasta {formattedTime})}many{Por # minutos (hasta {formattedTime})}other{Por # minutos (hasta {formattedTime})}}"</string> + <string name="zen_mode_duration_minutes_summary_short" msgid="1187553788355486950">"{count,plural, =1{Durante 1 min (hasta {formattedTime})}many{Durante # min (hasta {formattedTime})}other{Durante # min (hasta {formattedTime})}}"</string> + <string name="zen_mode_duration_hours_summary" msgid="3866333100793277211">"{count,plural, =1{Durante 1 hora (hasta {formattedTime})}many{Durante # horas (hasta {formattedTime})}other{Durante # horas (hasta {formattedTime})}}"</string> + <string name="zen_mode_duration_hours_summary_short" msgid="687919813833347945">"{count,plural, =1{Durante 1 h (hasta {formattedTime})}many{Durante # h (hasta {formattedTime})}other{Durante # h (hasta {formattedTime})}}"</string> + <string name="zen_mode_duration_minutes" msgid="2340007982276569054">"{count,plural, =1{Durante un minuto}many{Durante # minutos}other{Durante # minutos}}"</string> + <string name="zen_mode_duration_minutes_short" msgid="2435756450204526554">"{count,plural, =1{Durante 1 min}many{Durante # min}other{Durante # min}}"</string> + <string name="zen_mode_duration_hours" msgid="7841806065034711849">"{count,plural, =1{Durante 1 hora}many{Durante # horas}other{Durante # horas}}"</string> + <string name="zen_mode_duration_hours_short" msgid="3666949653933099065">"{count,plural, =1{Durante 1 h}many{Durante # h}other{Durante # h}}"</string> <string name="zen_mode_until_next_day" msgid="1403042784161725038">"Hasta las <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> <string name="zen_mode_until" msgid="2250286190237669079">"Hasta la(s) <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> <string name="zen_mode_alarm" msgid="7046911727540499275">"Hasta la hora <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (próxima alarma)"</string> @@ -2000,7 +2008,7 @@ <string name="autofill_save_accessibility_title" msgid="1523225776218450005">"Guardar para Autocompletar"</string> <string name="autofill_error_cannot_autofill" msgid="6528827648643138596">"El contenido no puede autocompletarse"</string> <string name="autofill_picker_no_suggestions" msgid="1076022650427481509">"No hay sugerencias de Autocompletar"</string> - <string name="autofill_picker_some_suggestions" msgid="5560549696296202701">"{count,plural, =1{Una sugerencia de autocompletar}other{# sugerencias de autocompletar}}"</string> + <string name="autofill_picker_some_suggestions" msgid="5560549696296202701">"{count,plural, =1{Una sugerencia de autocompletar}many{# sugerencias de autocompletar}other{# sugerencias de autocompletar}}"</string> <string name="autofill_save_title" msgid="7719802414283739775">"¿Quieres guardar en "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string> <string name="autofill_save_title_with_type" msgid="3002460014579799605">"¿Quieres guardar la <xliff:g id="TYPE">%1$s</xliff:g> en "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string> <string name="autofill_save_title_with_2types" msgid="3783270967447869241">"¿Quieres guardar <xliff:g id="TYPE_0">%1$s</xliff:g> y <xliff:g id="TYPE_1">%2$s</xliff:g> en "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string> @@ -2110,7 +2118,7 @@ <string name="mime_type_presentation_ext" msgid="8761049335564371468">"Presentación <xliff:g id="EXTENSION">%1$s</xliff:g>"</string> <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"La conexión Bluetooth permanecerá activa durante el modo de avión"</string> <string name="car_loading_profile" msgid="8219978381196748070">"Cargando"</string> - <string name="file_count" msgid="3220018595056126969">"{count,plural, =1{{file_name} y # archivo más}other{{file_name} y # archivos más}}"</string> + <string name="file_count" msgid="3220018595056126969">"{count,plural, =1{{file_name} y # archivo más}many{{file_name} y # archivos más}other{{file_name} y # archivos más}}"</string> <string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"No hay personas recomendadas con quienes compartir"</string> <string name="chooser_all_apps_button_label" msgid="3230427756238666328">"Lista de apps"</string> <string name="usb_device_resolve_prompt_warn" msgid="325871329788064199">"Aunque no se le otorgó permiso de grabación a esta app, puede capturar audio con este dispositivo USB."</string> diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml index 6be15fc27421..02860342f77b 100644 --- a/core/res/res/values-es/strings.xml +++ b/core/res/res/values-es/strings.xml @@ -51,6 +51,7 @@ <string name="needPuk2" msgid="7032612093451537186">"Introduce el código PUK2 para desbloquear la tarjeta SIM."</string> <string name="enablePin" msgid="2543771964137091212">"Error, habilitar bloqueo de SIM/RUIM."</string> <plurals name="pinpuk_attempts" formatted="false" msgid="1619867269012213584"> + <item quantity="many">You have <xliff:g id="NUMBER_1">%d</xliff:g> remaining attempts before SIM is locked.</item> <item quantity="other">Te quedan <xliff:g id="NUMBER_1">%d</xliff:g> intentos para bloquear la tarjeta SIM.</item> <item quantity="one">Te queda <xliff:g id="NUMBER_0">%d</xliff:g> intento para bloquear la tarjeta SIM.</item> </plurals> @@ -180,7 +181,7 @@ <string name="low_memory" product="watch" msgid="3479447988234030194">"El almacenamiento del reloj está lleno. Elimina algunos archivos para liberar espacio."</string> <string name="low_memory" product="tv" msgid="6663680413790323318">"El espacio de almacenamiento de tu dispositivo Android TV está lleno. Elimina algunos archivos para liberar espacio."</string> <string name="low_memory" product="default" msgid="2539532364144025569">"Se ha agotado el espacio de almacenamiento del teléfono. Elimina algunos archivos para liberar espacio."</string> - <string name="ssl_ca_cert_warning" msgid="7233573909730048571">"{count,plural, =1{Autoridad de certificación instalada}other{Autoridades de certificación instaladas}}"</string> + <string name="ssl_ca_cert_warning" msgid="7233573909730048571">"{count,plural, =1{Autoridad de certificación instalada}many{Autoridades de certificación instaladas}other{Autoridades de certificación instaladas}}"</string> <string name="ssl_ca_cert_noti_by_unknown" msgid="4961102218216815242">"Por un tercero desconocido"</string> <string name="ssl_ca_cert_noti_by_administrator" msgid="4564941950768783879">"Por el administrador de tu perfil de trabajo"</string> <string name="ssl_ca_cert_noti_managed" msgid="217337232273211674">"Por <xliff:g id="MANAGING_DOMAIN">%s</xliff:g>"</string> @@ -254,7 +255,7 @@ <string name="bugreport_option_interactive_summary" msgid="8493795476325339542">"Usa esta opción en la mayoría de los casos. Te permite realizar un seguimiento del progreso del informe, introducir más información sobre el problema y hacer capturas de pantalla. Es posible que se omitan algunas secciones menos utilizadas y que requieran más tiempo."</string> <string name="bugreport_option_full_title" msgid="7681035745950045690">"Informe completo"</string> <string name="bugreport_option_full_summary" msgid="1975130009258435885">"Utiliza esta opción para que la interferencia del sistema sea mínima cuando el dispositivo no responda o funcione demasiado lento, o bien cuando necesites todas las secciones del informe. No permite introducir más detalles ni hacer más capturas de pantalla."</string> - <string name="bugreport_countdown" msgid="6418620521782120755">"{count,plural, =1{La captura de pantalla para el informe de errores se hará en # segundo.}other{La captura de pantalla para el informe de errores se hará en # segundos.}}"</string> + <string name="bugreport_countdown" msgid="6418620521782120755">"{count,plural, =1{La captura de pantalla para el informe de errores se hará en # segundo.}many{La captura de pantalla para el informe de errores se hará en # segundos.}other{La captura de pantalla para el informe de errores se hará en # segundos.}}"</string> <string name="bugreport_screenshot_success_toast" msgid="7986095104151473745">"Se ha hecho la captura de pantalla con el informe de errores"</string> <string name="bugreport_screenshot_failure_toast" msgid="6736320861311294294">"No se ha podido hacer la captura de pantalla con el informe de errores"</string> <string name="global_action_toggle_silent_mode" msgid="8464352592860372188">"Modo Silencio"</string> @@ -586,13 +587,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Usar bloqueo de pantalla"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Introduce tu bloqueo de pantalla para continuar"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Mantén pulsado firmemente el sensor"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"No se ha podido procesar la huella digital. Vuelve a intentarlo."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Limpia el sensor de huellas digitales e inténtalo de nuevo"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Limpia el sensor e inténtalo de nuevo"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Mantén pulsado firmemente el sensor"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Has movido el dedo demasiado despacio. Vuelve a intentarlo."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Prueba con otra huella digital"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Demasiada luz"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Prueba a mover el dedo"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Cambia ligeramente el dedo de posición cada vez"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +608,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Se ha autenticado la cara, pulsa para confirmar"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"El hardware de huella digital no está disponible."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"No se puede configurar la huella digital"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Se ha alcanzado el tiempo de espera de la huella digital. Vuelve a intentarlo."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Se ha cancelado la operación de huella digital."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"El usuario ha cancelado la operación de huella digital."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Demasiados intentos. Vuelve a intentarlo más tarde."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Demasiados intentos. Usa el bloqueo de pantalla."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Vuelve a intentarlo."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"No se ha registrado ninguna huella digital."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Este dispositivo no tiene sensor de huellas digitales."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"El sensor está inhabilitado en estos momentos."</string> @@ -638,7 +644,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Visita un proveedor de reparaciones."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"No se puede crear tu modelo. Inténtalo de nuevo."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Hay demasiada luz. Busca un sitio menos iluminado."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Prueba en un lugar con más luz"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"Aleja el teléfono"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Acerca el teléfono"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Sube el teléfono"</string> @@ -1088,7 +1095,7 @@ <string name="enable_explore_by_touch_warning_message" product="default" msgid="4312979647356179250">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> quiere habilitar la exploración táctil. Cuando esta función esté activada, podrás escuchar o ver descripciones del contenido seleccionado o usar gestos para interactuar con el teléfono."</string> <string name="oneMonthDurationPast" msgid="4538030857114635777">"Hace un mes"</string> <string name="beforeOneMonthDurationPast" msgid="8315149541372065392">"Hace más de un mes"</string> - <string name="last_num_days" msgid="2393660431490280537">"{count,plural, =1{Último día (#)}other{Últimos # días}}"</string> + <string name="last_num_days" msgid="2393660431490280537">"{count,plural, =1{Último día (#)}many{Últimos # días}other{Últimos # días}}"</string> <string name="last_month" msgid="1528906781083518683">"El mes pasado"</string> <string name="older" msgid="1645159827884647400">"Anterior"</string> <string name="preposition_for_date" msgid="2780767868832729599">"<xliff:g id="DATE">%s</xliff:g>"</string> @@ -1115,14 +1122,14 @@ <string name="duration_hours_shortest_future" msgid="2979276794547981674">"en <xliff:g id="COUNT">%d</xliff:g>h"</string> <string name="duration_days_shortest_future" msgid="3392722163935571543">"en <xliff:g id="COUNT">%d</xliff:g> d"</string> <string name="duration_years_shortest_future" msgid="5537464088352970388">"en <xliff:g id="COUNT">%d</xliff:g>a"</string> - <string name="duration_minutes_relative" msgid="8620337701051015593">"{count,plural, =1{Hace # minuto}other{Hace # minutos}}"</string> - <string name="duration_hours_relative" msgid="4836449961693180253">"{count,plural, =1{Hace # hora}other{Hace # horas}}"</string> - <string name="duration_days_relative" msgid="621965767567258302">"{count,plural, =1{Hace # día}other{Hace # días}}"</string> - <string name="duration_years_relative" msgid="8731202348869424370">"{count,plural, =1{Hace # año}other{Hace # años}}"</string> - <string name="duration_minutes_relative_future" msgid="5259574171747708115">"{count,plural, =1{# minuto}other{# minutos}}"</string> - <string name="duration_hours_relative_future" msgid="6670440478481140565">"{count,plural, =1{# hora}other{# horas}}"</string> - <string name="duration_days_relative_future" msgid="8870658635774250746">"{count,plural, =1{# día}other{# días}}"</string> - <string name="duration_years_relative_future" msgid="8855853883925918380">"{count,plural, =1{# año}other{# años}}"</string> + <string name="duration_minutes_relative" msgid="8620337701051015593">"{count,plural, =1{Hace # minuto}many{Hace # minutos}other{Hace # minutos}}"</string> + <string name="duration_hours_relative" msgid="4836449961693180253">"{count,plural, =1{Hace # hora}many{Hace # horas}other{Hace # horas}}"</string> + <string name="duration_days_relative" msgid="621965767567258302">"{count,plural, =1{Hace # día}many{Hace # días}other{Hace # días}}"</string> + <string name="duration_years_relative" msgid="8731202348869424370">"{count,plural, =1{Hace # año}many{Hace # años}other{Hace # años}}"</string> + <string name="duration_minutes_relative_future" msgid="5259574171747708115">"{count,plural, =1{# minuto}many{# minutos}other{# minutos}}"</string> + <string name="duration_hours_relative_future" msgid="6670440478481140565">"{count,plural, =1{# hora}many{# horas}other{# horas}}"</string> + <string name="duration_days_relative_future" msgid="8870658635774250746">"{count,plural, =1{# día}many{# días}other{# días}}"</string> + <string name="duration_years_relative_future" msgid="8855853883925918380">"{count,plural, =1{# año}many{# años}other{# años}}"</string> <string name="VideoView_error_title" msgid="5750686717225068016">"Incidencias con el vídeo"</string> <string name="VideoView_error_text_invalid_progressive_playback" msgid="3782449246085134720">"Este vídeo no se puede transmitir al dispositivo."</string> <string name="VideoView_error_text_unknown" msgid="7658683339707607138">"No se puede reproducir el vídeo."</string> @@ -1251,8 +1258,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Iniciando aplicaciones"</string> <string name="android_upgrading_complete" msgid="409800058018374746">"Finalizando inicio..."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Has pulsado el botón de encendido, lo que suele apagar la pantalla.\n\nPrueba a apoyar el dedo ligeramente para verificar tu huella digital."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Toca para apagar la pantalla"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Apagar pantalla"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"¿Seguir verificando tu huella digital?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"Has pulsado el botón de encendido, lo que suele apagar la pantalla.\n\nPrueba a apoyar el dedo ligeramente para verificar tu huella digital."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Apagar pantalla"</string> @@ -1509,7 +1518,7 @@ <string name="skip_button_label" msgid="3566599811326688389">"Saltar"</string> <string name="no_matches" msgid="6472699895759164599">"No hay coincidencias."</string> <string name="find_on_page" msgid="5400537367077438198">"Buscar en la página"</string> - <string name="matches_found" msgid="2296462299979507689">"{count,plural, =1{# coincidencia}other{# de {total}}}"</string> + <string name="matches_found" msgid="2296462299979507689">"{count,plural, =1{# coincidencia}many{# de {total}}other{# de {total}}}"</string> <string name="action_mode_done" msgid="2536182504764803222">"Hecho"</string> <string name="progress_erasing" msgid="6891435992721028004">"Borrando almacenamiento compartido…"</string> <string name="share" msgid="4157615043345227321">"Compartir"</string> @@ -1862,14 +1871,14 @@ <string name="data_saver_description" msgid="4995164271550590517">"Para reducir el uso de datos, Ahorro de datos evita que algunas aplicaciones envíen o reciban datos en segundo plano. Si estás usando una aplicación, podrá acceder a datos, pero con menos frecuencia. Esto significa que es posible que, por ejemplo, algunas imágenes no se muestren hasta que las toques."</string> <string name="data_saver_enable_title" msgid="7080620065745260137">"¿Activar Ahorro de datos?"</string> <string name="data_saver_enable_button" msgid="4399405762586419726">"Activar"</string> - <string name="zen_mode_duration_minutes_summary" msgid="4555514757230849789">"{count,plural, =1{Durante un minuto (hasta las {formattedTime})}other{Durante # minutos (hasta las {formattedTime})}}"</string> - <string name="zen_mode_duration_minutes_summary_short" msgid="1187553788355486950">"{count,plural, =1{Durante 1 min (hasta las {formattedTime})}other{Durante # min (hasta las {formattedTime})}}"</string> - <string name="zen_mode_duration_hours_summary" msgid="3866333100793277211">"{count,plural, =1{Durante 1 hora (hasta las {formattedTime})}other{Durante # horas (hasta las {formattedTime})}}"</string> - <string name="zen_mode_duration_hours_summary_short" msgid="687919813833347945">"{count,plural, =1{Durante 1 h (hasta las {formattedTime})}other{Durante # h (hasta las {formattedTime})}}"</string> - <string name="zen_mode_duration_minutes" msgid="2340007982276569054">"{count,plural, =1{Durante 1 minuto}other{Durante # minutos}}"</string> - <string name="zen_mode_duration_minutes_short" msgid="2435756450204526554">"{count,plural, =1{Durante 1 min}other{Durante # min}}"</string> - <string name="zen_mode_duration_hours" msgid="7841806065034711849">"{count,plural, =1{Durante 1 hora}other{Durante # horas}}"</string> - <string name="zen_mode_duration_hours_short" msgid="3666949653933099065">"{count,plural, =1{Durante 1 h}other{Durante # h}}"</string> + <string name="zen_mode_duration_minutes_summary" msgid="4555514757230849789">"{count,plural, =1{Durante un minuto (hasta las {formattedTime})}many{Durante # minutos (hasta las {formattedTime})}other{Durante # minutos (hasta las {formattedTime})}}"</string> + <string name="zen_mode_duration_minutes_summary_short" msgid="1187553788355486950">"{count,plural, =1{Durante 1 min (hasta las {formattedTime})}many{Durante # min (hasta las {formattedTime})}other{Durante # min (hasta las {formattedTime})}}"</string> + <string name="zen_mode_duration_hours_summary" msgid="3866333100793277211">"{count,plural, =1{Durante 1 hora (hasta las {formattedTime})}many{Durante # horas (hasta las {formattedTime})}other{Durante # horas (hasta las {formattedTime})}}"</string> + <string name="zen_mode_duration_hours_summary_short" msgid="687919813833347945">"{count,plural, =1{Durante 1 h (hasta las {formattedTime})}many{Durante # h (hasta las {formattedTime})}other{Durante # h (hasta las {formattedTime})}}"</string> + <string name="zen_mode_duration_minutes" msgid="2340007982276569054">"{count,plural, =1{Durante 1 minuto}many{Durante # minutos}other{Durante # minutos}}"</string> + <string name="zen_mode_duration_minutes_short" msgid="2435756450204526554">"{count,plural, =1{Durante 1 min}many{Durante # min}other{Durante # min}}"</string> + <string name="zen_mode_duration_hours" msgid="7841806065034711849">"{count,plural, =1{Durante 1 hora}many{Durante # horas}other{Durante # horas}}"</string> + <string name="zen_mode_duration_hours_short" msgid="3666949653933099065">"{count,plural, =1{Durante 1 h}many{Durante # h}other{Durante # h}}"</string> <string name="zen_mode_until_next_day" msgid="1403042784161725038">"Hasta las <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> <string name="zen_mode_until" msgid="2250286190237669079">"Hasta <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> <string name="zen_mode_alarm" msgid="7046911727540499275">"Hasta las <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (próxima alarma)"</string> @@ -2000,7 +2009,7 @@ <string name="autofill_save_accessibility_title" msgid="1523225776218450005">"Guardar en la función Autocompletar"</string> <string name="autofill_error_cannot_autofill" msgid="6528827648643138596">"El contenido no se puede autocompletar"</string> <string name="autofill_picker_no_suggestions" msgid="1076022650427481509">"No hay sugerencias de Autocompletar"</string> - <string name="autofill_picker_some_suggestions" msgid="5560549696296202701">"{count,plural, =1{1 sugerencia de Autocompletar}other{# sugerencias de Autocompletar}}"</string> + <string name="autofill_picker_some_suggestions" msgid="5560549696296202701">"{count,plural, =1{1 sugerencia de Autocompletar}many{# sugerencias de Autocompletar}other{# sugerencias de Autocompletar}}"</string> <string name="autofill_save_title" msgid="7719802414283739775">"¿Guardar en "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string> <string name="autofill_save_title_with_type" msgid="3002460014579799605">"¿Guardar <xliff:g id="TYPE">%1$s</xliff:g> en "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string> <string name="autofill_save_title_with_2types" msgid="3783270967447869241">"¿Guardar <xliff:g id="TYPE_0">%1$s</xliff:g> y <xliff:g id="TYPE_1">%2$s</xliff:g> en "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string> @@ -2110,7 +2119,7 @@ <string name="mime_type_presentation_ext" msgid="8761049335564371468">"Presentación <xliff:g id="EXTENSION">%1$s</xliff:g>"</string> <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"El Bluetooth seguirá activado en el modo Avión"</string> <string name="car_loading_profile" msgid="8219978381196748070">"Cargando"</string> - <string name="file_count" msgid="3220018595056126969">"{count,plural, =1{{file_name} y # archivo más}other{{file_name} y # archivos más}}"</string> + <string name="file_count" msgid="3220018595056126969">"{count,plural, =1{{file_name} y # archivo más}many{{file_name} y # archivos más}other{{file_name} y # archivos más}}"</string> <string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"No hay sugerencias de personas con las que compartir"</string> <string name="chooser_all_apps_button_label" msgid="3230427756238666328">"Lista de aplicaciones"</string> <string name="usb_device_resolve_prompt_warn" msgid="325871329788064199">"Esta aplicación no tiene permiso para grabar, pero podría capturar audio con este dispositivo USB."</string> diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml index dcddeab22840..e5a6583e243d 100644 --- a/core/res/res/values-et/strings.xml +++ b/core/res/res/values-et/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Ekraaniluku kasutamine"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Jätkamiseks sisestage oma ekraanilukk"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Vajutage tugevalt andurile"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Sõrmejälge ei õnnestunud töödelda. Proovige uuesti."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Puhastage sõrmejäljeandur ja proovige uuesti"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Puhastage andur ja proovige uuesti"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Vajutage tugevalt andurile"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Sõrm liikus liiga aeglaselt. Proovige uuesti."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Proovige teist sõrmejälge"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Liiga ere"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Proovige kohandada"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Muutke iga kord pisut oma sõrme asendit"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Nägu on autenditud, vajutage käsku Kinnita"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Sõrmejälje riistvara pole saadaval."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Sõrmejälge ei saa seadistada"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Sõrmejälje riistvara taimeri ajalõpp. Proovige uuesti."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Sõrmejälje toiming tühistati."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Kasutaja tühistas sõrmejälje kasutamise."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Liiga palju katseid. Proovige hiljem uuesti."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Liiga palju katseid. Kasutage selle asemel ekraanilukku."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Proovige uuesti."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Ühtegi sõrmejälge pole registreeritud."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Selles seadmes pole sõrmejäljeandurit."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Andur on ajutiselt keelatud."</string> @@ -638,7 +643,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Külastage remonditeenuse pakkujat."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"Teie näomudelit ei saa luua. Proovige uuesti."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Liiga ere. Proovige hämaramat valgust."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Proovige parema valgustusega kohas"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"Liigutage telefoni kaugemale"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Liigutage telefoni lähemale"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Liigutage telefoni kõrgemale"</string> @@ -1251,8 +1257,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Rakenduste käivitamine."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"Käivitamise lõpuleviimine."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Vajutasite toitenuppu – tavaliselt lülitab see ekraani välja.\n\nPuudutage õrnalt ja seadistage oma sõrmejälg."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Puudutage ekraani väljalülitamiseks"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Lülita ekraan välja"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"Kas jätkata sõrmejälje kinnitamist?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"Vajutasite toitenuppu – tavaliselt lülitab see ekraani välja.\n\nPuudutage õrnalt, et oma sõrmejälg kinnitada."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Lülita ekraan välja"</string> diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml index 10f6857f90c8..17a9a4f54496 100644 --- a/core/res/res/values-eu/strings.xml +++ b/core/res/res/values-eu/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Erabili pantailaren blokeoa"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Aurrera egiteko, desblokeatu pantailaren blokeoa"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Sakatu irmo sentsorea"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Ezin izan da prozesatu hatz-marka. Saiatu berriro."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Garbitu hatz-marken sentsorea eta saiatu berriro"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Garbitu sentsorea eta saiatu berriro"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Sakatu irmo sentsorea"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Mantsoegi mugitu duzu hatza. Saiatu berriro."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Erabili beste hatz-marka bat"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Argi gehiegi dago"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Saiatu doituta"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Aldi bakoitzean, aldatu hatzaren posizioa apur bat"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Autentifikatu da aurpegia; sakatu Berretsi"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Hatz-marken hardwarea ez dago erabilgarri."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Ezin da konfiguratu hatz-marka"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Hatz-markak prozesatzeko denbora-muga gainditu da. Saiatu berriro."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Hatz-markaren eragiketa bertan behera utzi da."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Erabiltzaileak bertan behera utzi du hatz-marka bidezko eragiketa."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Saiakera gehiegi egin dituzu. Saiatu berriro geroago."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Saiakera gehiegi egin dira. Erabili pantailaren blokeoa."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Saiatu berriro."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Ez da erregistratu hatz-markarik."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Gailu honek ez du hatz-marken sentsorerik."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Sentsorea aldi baterako desgaitu da."</string> @@ -638,7 +643,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Jarri harremanetan konponketak egiten dituen hornitzaile batekin."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"Ezin da sortu aurpegi-eredua. Saiatu berriro."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Argi gehiegi dago. Joan toki ilunago batera."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Erabili argi gehiago"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"Urrundu telefonoa"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Hurbildu telefonoa"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Igo telefonoa"</string> @@ -1251,8 +1257,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Aplikazioak abiarazten."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"Bertsio-berritzea amaitzen."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Etengailua sakatu duzu; pantaila itzaltzeko balio du horrek.\n\nUki ezazu arin, hatz-marka konfiguratu bitartean."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Pantaila itzaltzeko, sakatu hau"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Itzali pantaila"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"Hatz-marka egiaztatzen jarraitu nahi duzu?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"Etengailua sakatu duzu; pantaila itzaltzeko balio du horrek.\n\nUki ezazu arin, hatz-marka egiaztatzeko."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Itzali pantaila"</string> diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml index 184010f9a6b9..3647f403564b 100644 --- a/core/res/res/values-fa/strings.xml +++ b/core/res/res/values-fa/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"از قفل صفحه استفاده کنید"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"برای ادامه، قفل صفحهتان را وارد کنید"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"محکم روی حسگر فشار دهید"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"اثرانگشت پردازش نشد. لطفاً دوباره امتحان کنید."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"حسگر اثر انگشت را تمیز و دوباره امتحان کنید"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"حسگر را تمیز و دوباره امتحان کنید"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"محکم روی حسگر فشار دهید"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"حرکت انگشت خیلی آهسته بود. لطفاً دوباره امتحان کنید."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"اثر انگشت دیگری را امتحان کنید"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"خیلی روشن است"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"اثر انگشت را تنظیم کنید"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"هربار موقعیت انگشتتان را کمی تغییر دهید"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"چهره اصالتسنجی شد، لطفاً تأیید را فشار دهید"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"سختافزار اثرانگشت در دسترس نیست."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"اثر انگشت راهاندازی نشد"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"مهلت ثبت اثر انگشت بهپایان رسید. دوباره امتحان کنید."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"عملکرد اثر انگشت لغو شد."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"کاربر عملیات اثر انگشت را لغو کرد"</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"تلاشهای زیادی انجام شده است. بعداً دوباره امتحان کنید."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"تلاشهای بیشازحد. حالا از قفل صفحه استفاده کنید."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"دوباره امتحان کنید."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"اثر انگشتی ثبت نشده است."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"این دستگاه حسگر اثر انگشت ندارد."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"حسگر بهطور موقت غیرفعال است."</string> @@ -638,7 +643,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"به ارائهدهنده خدمات تعمیر مراجعه کنید."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"مدل چهره ایجاد نشد. دوباره امتحان کنید."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"خیلی روشن است. روشناییاش را ملایمتر کنید."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"نور را بیشتر کنید"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"تلفن را دورتر ببرید"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"تلفن را نزدیکتر بیاورید"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"تلفن را بالاتر ببرید"</string> @@ -1251,8 +1257,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"درحال آغاز کردن برنامهها."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"درحال اتمام راهاندازی."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"دکمه روشن/ خاموش را فشار دادید — این کار معمولاً صفحهنمایش را خاموش میکند.\n\nهنگام راهاندازی اثر انگشت، آرام ضربه بزنید."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"برای خاموش کردن صفحهنمایش، ضربه بزنید"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"خاموش کردن صفحه"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"تأیید اثر انگشت را ادامه میدهید؟"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"دکمه روشن/ خاموش را فشار دادید — این کار معمولاً صفحهنمایش را خاموش میکند.\n\nبرای تأیید اثر انگشتتان، آرام ضربه بزنید."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"خاموش کردن صفحه"</string> diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml index dcbe1ba3b672..d680bf48f444 100644 --- a/core/res/res/values-fi/strings.xml +++ b/core/res/res/values-fi/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Käytä näytön lukitusta"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Jatka lisäämällä näytön lukituksen avaustapa"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Paina anturia voimakkaasti"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Sormenjäljen prosessointi epäonnistui. Yritä uudelleen."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Puhdista sormenjälkitunnistin ja yritä uudelleen"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Puhdista anturi ja yritä uudelleen"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Paina anturia voimakkaasti"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Liikutit sormea liian hitaasti. Yritä uudelleen."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Kokeile toista sormenjälkeä"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Liian kirkas"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Kokeile muuttaa asentoa"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Liikuta sormeasi hieman joka kerralla"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Kasvot tunnistettu, valitse Vahvista"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Sormenjälkilaitteisto ei ole käytettävissä."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Sormenjälkeä ei voi ottaa käyttöön"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Sormenjälkitunnistimen toiminta aikakatkaistiin. Yritä uudelleen."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Sormenjälkitoiminto peruutettiin."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Käyttäjä peruutti sormenjälkitoiminnon."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Liian monta yritystä. Yritä myöhemmin uudelleen."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Liian monta yritystä. Käytä näytön lukituksen avaustapaa."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Yritä uudelleen."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Sormenjälkiä ei ole otettu käyttöön."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Laitteessa ei ole sormenjälkitunnistinta."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Tunnistin poistettu väliaikaisesti käytöstä."</string> @@ -638,7 +643,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Ota yhteys korjauspalveluun."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"Kasvomallia ei voi luoda. Yritä uudelleen."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Liian kirkasta. Kokeile pehmeämpää valaistusta."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Kokeile kirkkaampaa valaistusta"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"Vie puhelin kauemmas"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Tuo puhelin lähemmäs"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Siirrä puhelinta ylemmäs"</string> @@ -1251,8 +1257,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Käynnistetään sovelluksia."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"Viimeistellään päivitystä."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Painoit virtapainiketta, mikä yleensä sammuttaa näytön.\n\nKosketa painiketta kevyesti tallentaessasi sormenjälkeä."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Sammuta näyttö napauttamalla"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Sammuta näyttö"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"Jatketaanko sormenjäljen vahvistamista?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"Painoit virtapainiketta, mikä yleensä sammuttaa näytön.\n\nVahvista sormenjälki koskettamalla painiketta kevyesti."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Sammuta näyttö"</string> diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml index e9ec78a0f7f3..50ee7664ffe1 100644 --- a/core/res/res/values-fr-rCA/strings.xml +++ b/core/res/res/values-fr-rCA/strings.xml @@ -52,6 +52,7 @@ <string name="enablePin" msgid="2543771964137091212">"Opération infructueuse. Activez le verrouillage SIM/RUIM."</string> <plurals name="pinpuk_attempts" formatted="false" msgid="1619867269012213584"> <item quantity="one">Il vous reste <xliff:g id="NUMBER_1">%d</xliff:g> tentative avant que votre carte SIM soit verrouillée.</item> + <item quantity="many">You have <xliff:g id="NUMBER_1">%d</xliff:g> remaining attempts before SIM is locked.</item> <item quantity="other">Il vous reste <xliff:g id="NUMBER_1">%d</xliff:g> tentatives avant que votre carte SIM soit verrouillée.</item> </plurals> <string name="imei" msgid="2157082351232630390">"Code IIEM"</string> @@ -180,7 +181,7 @@ <string name="low_memory" product="watch" msgid="3479447988234030194">"La mémoire de la montre est pleine. Supprimez des fichiers pour libérer de l\'espace."</string> <string name="low_memory" product="tv" msgid="6663680413790323318">"L\'espace de stockage de l\'appareil Android TV est plein. Supprimez des fichiers pour libérer de l\'espace."</string> <string name="low_memory" product="default" msgid="2539532364144025569">"La mémoire du téléphone est pleine. Veuillez supprimer des fichiers pour libérer de l\'espace."</string> - <string name="ssl_ca_cert_warning" msgid="7233573909730048571">"{count,plural, =1{Autorité de certification installée}one{Autorité de certification installée}other{Autorités de certification installées}}"</string> + <string name="ssl_ca_cert_warning" msgid="7233573909730048571">"{count,plural, =1{Autorité de certification installée}one{Autorité de certification installée}many{Autorités de certification installées}other{Autorités de certification installées}}"</string> <string name="ssl_ca_cert_noti_by_unknown" msgid="4961102218216815242">"Par un tiers inconnu"</string> <string name="ssl_ca_cert_noti_by_administrator" msgid="4564941950768783879">"Par l\'administrateur de votre profil professionnel"</string> <string name="ssl_ca_cert_noti_managed" msgid="217337232273211674">"Par <xliff:g id="MANAGING_DOMAIN">%s</xliff:g>"</string> @@ -254,7 +255,7 @@ <string name="bugreport_option_interactive_summary" msgid="8493795476325339542">"Utilisez cette option dans la plupart des circonstances. Elle vous permet de suivre la progression du rapport, d\'entrer plus d\'information sur le problème et d\'effectuer des saisies d\'écran. Certaines sections moins utilisées et dont le remplissage demande beaucoup de temps peuvent être omises."</string> <string name="bugreport_option_full_title" msgid="7681035745950045690">"Rapport complet"</string> <string name="bugreport_option_full_summary" msgid="1975130009258435885">"Utilisez cette option pour qu\'il y ait le moins d\'interférences système possible lorsque votre appareil ne répond pas ou qu\'il est trop lent, ou lorsque vous avez besoin de toutes les sections du rapport de bogue. Aucune capture d\'écran supplémentaire ne peut être capturée, et vous ne pouvez entrer aucune autre information."</string> - <string name="bugreport_countdown" msgid="6418620521782120755">"{count,plural, =1{Saisie d\'une capture d\'écran pour le rapport de bogue dans # seconde.}one{Saisie d\'une capture d\'écran pour le rapport de bogue dans # seconde.}other{Saisie d\'une capture d\'écran pour le rapport de bogue dans # secondes.}}"</string> + <string name="bugreport_countdown" msgid="6418620521782120755">"{count,plural, =1{Saisie d\'une capture d\'écran pour le rapport de bogue dans # seconde.}one{Saisie d\'une capture d\'écran pour le rapport de bogue dans # seconde.}many{Saisie d\'une capture d\'écran pour le rapport de bogue dans # secondes.}other{Saisie d\'une capture d\'écran pour le rapport de bogue dans # secondes.}}"</string> <string name="bugreport_screenshot_success_toast" msgid="7986095104151473745">"Capture d\'écran prise avec le rapport de bogue"</string> <string name="bugreport_screenshot_failure_toast" msgid="6736320861311294294">"Échec de la prise de capture d\'écran avec le rapport de bogue"</string> <string name="global_action_toggle_silent_mode" msgid="8464352592860372188">"Mode silencieux"</string> @@ -586,13 +587,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Utiliser le verrouillage de l\'écran"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Entrez votre verrouillage d\'écran pour continuer"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Appuyez fermement sur le capteur"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Impossible de reconnaître l\'empreinte digitale. Veuillez réessayer."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Nettoyez le capteur d\'empreintes digitales et réessayez"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Nettoyez le capteur et réessayez"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Appuyez fermement sur le capteur"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Vous avez déplacé votre doigt trop lentement. Veuillez réessayer."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Essayez une autre empreinte digitale"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Trop lumineux"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Essayez de l\'ajuster"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Modifiez légèrement la position de votre doigt chaque fois"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +608,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Visage authentifié, veuillez appuyer sur le bouton Confirmer"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Lecteur d\'empreintes digitales indisponible."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Impossible de configurer l\'empreinte digitale"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Le temps attribué pour lire l\'empreinte digitale est écoulé. Veuillez réessayer."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Opération d\'empreinte digitale numérique annulée."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"L\'opération d\'empreinte digitale a été annulée par l\'utilisateur."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Trop de tentatives. Veuillez réessayer plus tard."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Trop de tentatives. Utilisez plutôt le verrouillage de l\'écran."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Réessayer."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Aucune empreinte digitale enregistrée."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Cet appareil ne possède pas de capteur d\'empreintes digitales."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Le capteur a été désactivé temporairement."</string> @@ -638,7 +644,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Consultez un fournisseur de services de réparation."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"Impossible de créer votre modèle facial. Réessayez."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Trop lumineux. Essayez un éclairage plus faible."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Essayez avec un éclairage plus fort"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"Éloignez le téléphone"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Rapprochez le téléphone"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Tenez le téléphone plus haut"</string> @@ -1088,7 +1095,7 @@ <string name="enable_explore_by_touch_warning_message" product="default" msgid="4312979647356179250">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> souhaite activer la fonctionnalité \"Explorer au toucher\". Lorsque celle-ci est activée, vous pouvez entendre ou voir les descriptions des éléments que vous sélectionnez, ou bien interagir avec le téléphone en effectuant certains gestes."</string> <string name="oneMonthDurationPast" msgid="4538030857114635777">"Il y a 1 mois"</string> <string name="beforeOneMonthDurationPast" msgid="8315149541372065392">"Il y a plus d\'un mois"</string> - <string name="last_num_days" msgid="2393660431490280537">"{count,plural, =1{# dernier jour}one{# dernier jour}other{# derniers jours}}"</string> + <string name="last_num_days" msgid="2393660431490280537">"{count,plural, =1{# dernier jour}one{# dernier jour}many{# derniers jours}other{# derniers jours}}"</string> <string name="last_month" msgid="1528906781083518683">"Le mois dernier"</string> <string name="older" msgid="1645159827884647400">"Précédent"</string> <string name="preposition_for_date" msgid="2780767868832729599">"le <xliff:g id="DATE">%s</xliff:g>"</string> @@ -1115,14 +1122,14 @@ <string name="duration_hours_shortest_future" msgid="2979276794547981674">"dans <xliff:g id="COUNT">%d</xliff:g> h"</string> <string name="duration_days_shortest_future" msgid="3392722163935571543">"dans <xliff:g id="COUNT">%d</xliff:g> j"</string> <string name="duration_years_shortest_future" msgid="5537464088352970388">"dans <xliff:g id="COUNT">%d</xliff:g> a"</string> - <string name="duration_minutes_relative" msgid="8620337701051015593">"{count,plural, =1{Il y a # minute}one{Il y a # minute}other{Il y a # minutes}}"</string> - <string name="duration_hours_relative" msgid="4836449961693180253">"{count,plural, =1{Il y a # heure}one{Il y a # heure}other{Il y a # heures}}"</string> - <string name="duration_days_relative" msgid="621965767567258302">"{count,plural, =1{Il y a # jour}one{Il y a # jour}other{Il y a # jours}}"</string> - <string name="duration_years_relative" msgid="8731202348869424370">"{count,plural, =1{Il y a # an}one{Il y a # an}other{Il y a # ans}}"</string> - <string name="duration_minutes_relative_future" msgid="5259574171747708115">"{count,plural, =1{# minute}one{# minute}other{# minutes}}"</string> - <string name="duration_hours_relative_future" msgid="6670440478481140565">"{count,plural, =1{# heure}one{# heure}other{# heures}}"</string> - <string name="duration_days_relative_future" msgid="8870658635774250746">"{count,plural, =1{# jour}one{# jour}other{# jours}}"</string> - <string name="duration_years_relative_future" msgid="8855853883925918380">"{count,plural, =1{# an}one{# an}other{# ans}}"</string> + <string name="duration_minutes_relative" msgid="8620337701051015593">"{count,plural, =1{Il y a # minute}one{Il y a # minute}many{Il y a # minutes}other{Il y a # minutes}}"</string> + <string name="duration_hours_relative" msgid="4836449961693180253">"{count,plural, =1{Il y a # heure}one{Il y a # heure}many{Il y a # heures}other{Il y a # heures}}"</string> + <string name="duration_days_relative" msgid="621965767567258302">"{count,plural, =1{Il y a # jour}one{Il y a # jour}many{Il y a # jours}other{Il y a # jours}}"</string> + <string name="duration_years_relative" msgid="8731202348869424370">"{count,plural, =1{Il y a # an}one{Il y a # an}many{Il y a # ans}other{Il y a # ans}}"</string> + <string name="duration_minutes_relative_future" msgid="5259574171747708115">"{count,plural, =1{# minute}one{# minute}many{# minutes}other{# minutes}}"</string> + <string name="duration_hours_relative_future" msgid="6670440478481140565">"{count,plural, =1{# heure}one{# heure}many{# heures}other{# heures}}"</string> + <string name="duration_days_relative_future" msgid="8870658635774250746">"{count,plural, =1{# jour}one{# jour}many{# jours}other{# jours}}"</string> + <string name="duration_years_relative_future" msgid="8855853883925918380">"{count,plural, =1{# an}one{# an}many{# ans}other{# ans}}"</string> <string name="VideoView_error_title" msgid="5750686717225068016">"Problème vidéo"</string> <string name="VideoView_error_text_invalid_progressive_playback" msgid="3782449246085134720">"Impossible de lire cette vidéo en continu sur cet appareil."</string> <string name="VideoView_error_text_unknown" msgid="7658683339707607138">"Impossible de lire la vidéo."</string> @@ -1251,8 +1258,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Lancement des applications…"</string> <string name="android_upgrading_complete" msgid="409800058018374746">"Finalisation de la mise à jour."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Vous avez appuyé sur le l\'interrupteur – cette action éteint habituellement l\'écran.\n\nEssayez de toucher légèrement pendant la configuration de votre empreinte digitale."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Toucher pour éteindre l\'écran"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Éteindre l\'écran"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"Poursuivre vérifica. empreinte digitale?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"Vous avez appuyé sur le l\'interrupteur – cette action éteint habituellement l\'écran.\n\nEssayez de toucher légèrement pour vérifier votre empreinte digitale."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Éteindre l\'écran"</string> @@ -1509,7 +1518,7 @@ <string name="skip_button_label" msgid="3566599811326688389">"Ignorer"</string> <string name="no_matches" msgid="6472699895759164599">"Aucune partie"</string> <string name="find_on_page" msgid="5400537367077438198">"Rechercher sur la page"</string> - <string name="matches_found" msgid="2296462299979507689">"{count,plural, =1{# correspondance}one{# sur {total}}other{# sur {total}}}"</string> + <string name="matches_found" msgid="2296462299979507689">"{count,plural, =1{# correspondance}one{# sur {total}}many{# sur {total}}other{# sur {total}}}"</string> <string name="action_mode_done" msgid="2536182504764803222">"Terminé"</string> <string name="progress_erasing" msgid="6891435992721028004">"Effacement du stockage partagé en cours…"</string> <string name="share" msgid="4157615043345227321">"Partager"</string> @@ -1862,14 +1871,14 @@ <string name="data_saver_description" msgid="4995164271550590517">"Pour aider à diminuer l\'utilisation des données, la fonctionnalité Économiseur de données empêche certaines applications d\'envoyer ou de recevoir des données en arrière-plan. Une application que vous utilisez actuellement peut accéder à des données, mais peut le faire moins souvent. Cela peut signifier, par exemple, que les images ne s\'affichent pas jusqu\'à ce que vous les touchiez."</string> <string name="data_saver_enable_title" msgid="7080620065745260137">"Activer l\'économiseur de données?"</string> <string name="data_saver_enable_button" msgid="4399405762586419726">"Activer"</string> - <string name="zen_mode_duration_minutes_summary" msgid="4555514757230849789">"{count,plural, =1{Pendant une minute (jusqu\'à {formattedTime})}one{Pendant # minute (jusqu\'à {formattedTime})}other{Pendant # minutes (jusqu\'à {formattedTime})}}"</string> - <string name="zen_mode_duration_minutes_summary_short" msgid="1187553788355486950">"{count,plural, =1{Pendant 1 m (jusqu\'à {formattedTime})}one{Pendant # m (jusqu\'à {formattedTime})}other{Pendant # m (jusqu\'à {formattedTime})}}"</string> - <string name="zen_mode_duration_hours_summary" msgid="3866333100793277211">"{count,plural, =1{Pendant 1 heure (jusqu\'à {formattedTime})}one{Pendant # heure (jusqu\'à {formattedTime})}other{Pendant # heures (jusqu\'à {formattedTime})}}"</string> - <string name="zen_mode_duration_hours_summary_short" msgid="687919813833347945">"{count,plural, =1{Pendant 1 h (jusqu\'à {formattedTime})}one{Pendant # h (jusqu\'à {formattedTime})}other{Pendant # h (jusqu\'à {formattedTime})}}"</string> - <string name="zen_mode_duration_minutes" msgid="2340007982276569054">"{count,plural, =1{Pendant une minute}one{Pendant # minute}other{Pendant # minutes}}"</string> - <string name="zen_mode_duration_minutes_short" msgid="2435756450204526554">"{count,plural, =1{Pendant 1 m}one{Pendant # m}other{Pendant # m}}"</string> - <string name="zen_mode_duration_hours" msgid="7841806065034711849">"{count,plural, =1{Pendant 1 heure}one{Pendant # heure}other{Pendant # heures}}"</string> - <string name="zen_mode_duration_hours_short" msgid="3666949653933099065">"{count,plural, =1{Pendant 1 h}one{Pendant # h}other{Pendant # h}}"</string> + <string name="zen_mode_duration_minutes_summary" msgid="4555514757230849789">"{count,plural, =1{Pendant une minute (jusqu\'à {formattedTime})}one{Pendant # minute (jusqu\'à {formattedTime})}many{Pendant # minutes (jusqu\'à {formattedTime})}other{Pendant # minutes (jusqu\'à {formattedTime})}}"</string> + <string name="zen_mode_duration_minutes_summary_short" msgid="1187553788355486950">"{count,plural, =1{Pendant 1 m (jusqu\'à {formattedTime})}one{Pendant # m (jusqu\'à {formattedTime})}many{Pendant # m (jusqu\'à {formattedTime})}other{Pendant # m (jusqu\'à {formattedTime})}}"</string> + <string name="zen_mode_duration_hours_summary" msgid="3866333100793277211">"{count,plural, =1{Pendant 1 heure (jusqu\'à {formattedTime})}one{Pendant # heure (jusqu\'à {formattedTime})}many{Pendant # heures (jusqu\'à {formattedTime})}other{Pendant # heures (jusqu\'à {formattedTime})}}"</string> + <string name="zen_mode_duration_hours_summary_short" msgid="687919813833347945">"{count,plural, =1{Pendant 1 h (jusqu\'à {formattedTime})}one{Pendant # h (jusqu\'à {formattedTime})}many{Pendant # h (jusqu\'à {formattedTime})}other{Pendant # h (jusqu\'à {formattedTime})}}"</string> + <string name="zen_mode_duration_minutes" msgid="2340007982276569054">"{count,plural, =1{Pendant une minute}one{Pendant # minute}many{Pendant # minutes}other{Pendant # minutes}}"</string> + <string name="zen_mode_duration_minutes_short" msgid="2435756450204526554">"{count,plural, =1{Pendant 1 m}one{Pendant # m}many{Pendant # m}other{Pendant # m}}"</string> + <string name="zen_mode_duration_hours" msgid="7841806065034711849">"{count,plural, =1{Pendant 1 heure}one{Pendant # heure}many{Pendant # heures}other{Pendant # heures}}"</string> + <string name="zen_mode_duration_hours_short" msgid="3666949653933099065">"{count,plural, =1{Pendant 1 h}one{Pendant # h}many{Pendant # h}other{Pendant # h}}"</string> <string name="zen_mode_until_next_day" msgid="1403042784161725038">"Jusqu\'à <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> <string name="zen_mode_until" msgid="2250286190237669079">"Jusqu\'à <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> <string name="zen_mode_alarm" msgid="7046911727540499275">"Jusqu\'à <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (alarme suivante)"</string> @@ -2000,7 +2009,7 @@ <string name="autofill_save_accessibility_title" msgid="1523225776218450005">"Enregistrer pour le remplissage automatique"</string> <string name="autofill_error_cannot_autofill" msgid="6528827648643138596">"Le contenu ne peut pas être entré automatiquement"</string> <string name="autofill_picker_no_suggestions" msgid="1076022650427481509">"Aucune suggestion de remplissage automatique"</string> - <string name="autofill_picker_some_suggestions" msgid="5560549696296202701">"{count,plural, =1{Une suggestion de remplissage automatique}one{# suggestion de remplissage automatique}other{# suggestions de remplissage automatique}}"</string> + <string name="autofill_picker_some_suggestions" msgid="5560549696296202701">"{count,plural, =1{Une suggestion de remplissage automatique}one{# suggestion de remplissage automatique}many{# suggestions de remplissage automatique}other{# suggestions de remplissage automatique}}"</string> <string name="autofill_save_title" msgid="7719802414283739775">"Enregistrer sous "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string> <string name="autofill_save_title_with_type" msgid="3002460014579799605">"Enregistrer <xliff:g id="TYPE">%1$s</xliff:g> sous "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string> <string name="autofill_save_title_with_2types" msgid="3783270967447869241">"Enregistrer <xliff:g id="TYPE_0">%1$s</xliff:g> et <xliff:g id="TYPE_1">%2$s</xliff:g> sous "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string> @@ -2110,7 +2119,7 @@ <string name="mime_type_presentation_ext" msgid="8761049335564371468">"Présentation <xliff:g id="EXTENSION">%1$s</xliff:g>"</string> <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Le Bluetooth restera activé en mode Avion"</string> <string name="car_loading_profile" msgid="8219978381196748070">"Chargement en cours…"</string> - <string name="file_count" msgid="3220018595056126969">"{count,plural, =1{{file_name} + # fichier}one{{file_name} + # fichier}other{{file_name} + # fichiers}}"</string> + <string name="file_count" msgid="3220018595056126969">"{count,plural, =1{{file_name} + # fichier}one{{file_name} + # fichier}many{{file_name} + # fichiers}other{{file_name} + # fichiers}}"</string> <string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"Aucune recommandation de personnes avec lesquelles effectuer un partage"</string> <string name="chooser_all_apps_button_label" msgid="3230427756238666328">"Liste des applications"</string> <string name="usb_device_resolve_prompt_warn" msgid="325871329788064199">"Cette application n\'a pas été autorisée à effectuer des enregistrements, mais elle pourrait capturer du contenu audio par l\'intermédiaire de cet appareil USB."</string> diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml index dbbe31b08aa3..574b113739f5 100644 --- a/core/res/res/values-fr/strings.xml +++ b/core/res/res/values-fr/strings.xml @@ -52,6 +52,7 @@ <string name="enablePin" msgid="2543771964137091212">"Échec de l\'opération. Veuillez activer le verrouillage de la carte SIM/RUIM."</string> <plurals name="pinpuk_attempts" formatted="false" msgid="1619867269012213584"> <item quantity="one">Il vous reste <xliff:g id="NUMBER_1">%d</xliff:g> tentative avant que votre carte SIM ne soit verrouillée.</item> + <item quantity="many">You have <xliff:g id="NUMBER_1">%d</xliff:g> remaining attempts before SIM is locked.</item> <item quantity="other">Il vous reste <xliff:g id="NUMBER_1">%d</xliff:g> tentatives avant que votre carte SIM ne soit verrouillée.</item> </plurals> <string name="imei" msgid="2157082351232630390">"Code IMEI"</string> @@ -180,7 +181,7 @@ <string name="low_memory" product="watch" msgid="3479447988234030194">"La mémoire de la montre est saturée. Veuillez supprimer des fichiers pour libérer de l\'espace."</string> <string name="low_memory" product="tv" msgid="6663680413790323318">"L\'espace de stockage de l\'appareil Android TV est saturé. Supprimez certains fichiers pour libérer de l\'espace."</string> <string name="low_memory" product="default" msgid="2539532364144025569">"La mémoire du téléphone est pleine. Veuillez supprimer des fichiers pour libérer de l\'espace."</string> - <string name="ssl_ca_cert_warning" msgid="7233573909730048571">"{count,plural, =1{Autorité de certification installée}one{Autorité de certification installée}other{Autorités de certification installées}}"</string> + <string name="ssl_ca_cert_warning" msgid="7233573909730048571">"{count,plural, =1{Autorité de certification installée}one{Autorité de certification installée}many{Autorités de certification installées}other{Autorités de certification installées}}"</string> <string name="ssl_ca_cert_noti_by_unknown" msgid="4961102218216815242">"Par un tiers inconnu"</string> <string name="ssl_ca_cert_noti_by_administrator" msgid="4564941950768783879">"Par l\'administrateur de votre profil professionnel"</string> <string name="ssl_ca_cert_noti_managed" msgid="217337232273211674">"Par <xliff:g id="MANAGING_DOMAIN">%s</xliff:g>"</string> @@ -254,7 +255,7 @@ <string name="bugreport_option_interactive_summary" msgid="8493795476325339542">"Utilisez cette option dans la plupart des circonstances. Elle vous permet de suivre la progression du rapport, de saisir plus d\'informations sur le problème et d\'effectuer des captures d\'écran. Certaines sections moins utilisées et dont le remplissage demande beaucoup de temps peuvent être omises."</string> <string name="bugreport_option_full_title" msgid="7681035745950045690">"Rapport complet"</string> <string name="bugreport_option_full_summary" msgid="1975130009258435885">"Utilisez cette option pour qu\'il y ait le moins d\'interférences système possible lorsque votre appareil ne répond pas ou qu\'il est trop lent, ou lorsque vous avez besoin de toutes les sections du rapport de bug. Aucune capture d\'écran supplémentaire ne peut être prise, et vous ne pouvez saisir aucune autre information."</string> - <string name="bugreport_countdown" msgid="6418620521782120755">"{count,plural, =1{Capture d\'écran pour le rapport de bug dans # seconde.}one{Capture d\'écran pour le rapport de bug dans # seconde.}other{Capture d\'écran pour le rapport de bug dans # secondes.}}"</string> + <string name="bugreport_countdown" msgid="6418620521782120755">"{count,plural, =1{Capture d\'écran pour le rapport de bug dans # seconde.}one{Capture d\'écran pour le rapport de bug dans # seconde.}many{Capture d\'écran pour le rapport de bug dans # secondes.}other{Capture d\'écran pour le rapport de bug dans # secondes.}}"</string> <string name="bugreport_screenshot_success_toast" msgid="7986095104151473745">"Capture d\'écran avec rapport de bug effectuée"</string> <string name="bugreport_screenshot_failure_toast" msgid="6736320861311294294">"Échec de la capture d\'écran avec le rapport de bug"</string> <string name="global_action_toggle_silent_mode" msgid="8464352592860372188">"Mode silencieux"</string> @@ -586,13 +587,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Utiliser verrouillage écran"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Utilisez le verrouillage de l\'écran pour continuer"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Appuyez bien sur le lecteur"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Impossible de reconnaître l\'empreinte digitale. Veuillez réessayer."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Nettoyez le lecteur d\'empreinte digitale et réessayez"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Nettoyez le lecteur et réessayez"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Appuyez bien sur le lecteur"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Vous avez déplacé votre doigt trop lentement. Veuillez réessayer."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Essayez une autre empreinte"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Trop de lumière"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Essayez de repositionner le doigt"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Changez légèrement de position à chaque fois"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +608,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Visage authentifié, veuillez appuyer sur \"Confirmer\""</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Matériel d\'empreinte digitale indisponible."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Impossible de configurer l\'empreinte"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Délai de détection de l\'empreinte digitale expiré. Veuillez réessayer."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Opération d\'empreinte digitale annulée."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Opération d\'authentification par empreinte digitale annulée par l\'utilisateur."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Trop de tentatives. Veuillez réessayer plus tard."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Trop de tentatives. Utilisez plutôt le verrouillage de l\'écran."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Veuillez réessayer."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Aucune empreinte digitale enregistrée."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Aucun lecteur d\'empreinte digitale n\'est installé sur cet appareil."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Capteur temporairement désactivé."</string> @@ -638,7 +644,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Contactez un réparateur."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"Impossible de créer l\'empreinte faciale. Réessayez."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Trop lumineux. Essayez de baisser la lumière."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Essayez un éclairage plus lumineux"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"Éloignez le téléphone."</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Rapprochez le téléphone"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Déplacez le téléphone vers le haut"</string> @@ -1088,7 +1095,7 @@ <string name="enable_explore_by_touch_warning_message" product="default" msgid="4312979647356179250">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> souhaite activer la fonctionnalité \"Explorer au toucher\". Lorsque celle-ci est activée, vous pouvez entendre ou voir les descriptions des éléments que vous sélectionnez, ou bien interagir avec le téléphone en effectuant certains gestes."</string> <string name="oneMonthDurationPast" msgid="4538030857114635777">"Il y a 1 mois"</string> <string name="beforeOneMonthDurationPast" msgid="8315149541372065392">"Il y a plus d\'un mois"</string> - <string name="last_num_days" msgid="2393660431490280537">"{count,plural, =1{Dernier jour (#)}one{Dernier jour (#)}other{# derniers jours}}"</string> + <string name="last_num_days" msgid="2393660431490280537">"{count,plural, =1{Dernier jour (#)}one{Dernier jour (#)}many{# derniers jours}other{# derniers jours}}"</string> <string name="last_month" msgid="1528906781083518683">"Le mois dernier"</string> <string name="older" msgid="1645159827884647400">"Préc."</string> <string name="preposition_for_date" msgid="2780767868832729599">"le <xliff:g id="DATE">%s</xliff:g>"</string> @@ -1115,14 +1122,14 @@ <string name="duration_hours_shortest_future" msgid="2979276794547981674">"dans <xliff:g id="COUNT">%d</xliff:g> h"</string> <string name="duration_days_shortest_future" msgid="3392722163935571543">"dans <xliff:g id="COUNT">%d</xliff:g> j"</string> <string name="duration_years_shortest_future" msgid="5537464088352970388">"dans <xliff:g id="COUNT">%d</xliff:g> an"</string> - <string name="duration_minutes_relative" msgid="8620337701051015593">"{count,plural, =1{Il y a # minute}one{Il y a # minute}other{Il y a # minutes}}"</string> - <string name="duration_hours_relative" msgid="4836449961693180253">"{count,plural, =1{Il y a # heure}one{Il y a # heure}other{Il y a # heures}}"</string> - <string name="duration_days_relative" msgid="621965767567258302">"{count,plural, =1{Il y a # jour}one{Il y a # jour}other{Il y a # jours}}"</string> - <string name="duration_years_relative" msgid="8731202348869424370">"{count,plural, =1{Il y a # an}one{Il y a # an}other{Il y a # ans}}"</string> - <string name="duration_minutes_relative_future" msgid="5259574171747708115">"{count,plural, =1{# minute}one{# minute}other{# minutes}}"</string> - <string name="duration_hours_relative_future" msgid="6670440478481140565">"{count,plural, =1{# heure}one{# heure}other{# heures}}"</string> - <string name="duration_days_relative_future" msgid="8870658635774250746">"{count,plural, =1{# jour}one{# jour}other{# jours}}"</string> - <string name="duration_years_relative_future" msgid="8855853883925918380">"{count,plural, =1{# an}one{# an}other{# ans}}"</string> + <string name="duration_minutes_relative" msgid="8620337701051015593">"{count,plural, =1{Il y a # minute}one{Il y a # minute}many{Il y a # minutes}other{Il y a # minutes}}"</string> + <string name="duration_hours_relative" msgid="4836449961693180253">"{count,plural, =1{Il y a # heure}one{Il y a # heure}many{Il y a # heures}other{Il y a # heures}}"</string> + <string name="duration_days_relative" msgid="621965767567258302">"{count,plural, =1{Il y a # jour}one{Il y a # jour}many{Il y a # jours}other{Il y a # jours}}"</string> + <string name="duration_years_relative" msgid="8731202348869424370">"{count,plural, =1{Il y a # an}one{Il y a # an}many{Il y a # ans}other{Il y a # ans}}"</string> + <string name="duration_minutes_relative_future" msgid="5259574171747708115">"{count,plural, =1{# minute}one{# minute}many{# minutes}other{# minutes}}"</string> + <string name="duration_hours_relative_future" msgid="6670440478481140565">"{count,plural, =1{# heure}one{# heure}many{# heures}other{# heures}}"</string> + <string name="duration_days_relative_future" msgid="8870658635774250746">"{count,plural, =1{# jour}one{# jour}many{# jours}other{# jours}}"</string> + <string name="duration_years_relative_future" msgid="8855853883925918380">"{count,plural, =1{# an}one{# an}many{# ans}other{# ans}}"</string> <string name="VideoView_error_title" msgid="5750686717225068016">"Problème vidéo"</string> <string name="VideoView_error_text_invalid_progressive_playback" msgid="3782449246085134720">"Impossible de lire cette vidéo en streaming sur cet appareil."</string> <string name="VideoView_error_text_unknown" msgid="7658683339707607138">"Impossible de lire la vidéo."</string> @@ -1251,8 +1258,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Lancement des applications…"</string> <string name="android_upgrading_complete" msgid="409800058018374746">"Finalisation de la mise à jour."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Vous avez appuyé sur le bouton Marche/Arrêt, ce qui éteint généralement l\'écran.\n\nEssayez d\'appuyer doucement pendant la configuration de votre empreinte digitale."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Appuyer pour éteindre l\'écran"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Éteindre l\'écran"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"Continuer de valider votre empreinte ?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"Vous avez appuyé sur le bouton Marche/Arrêt, ce qui éteint généralement l\'écran.\n\nPour valider votre empreinte digitale, appuyez plus doucement."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Éteindre l\'écran"</string> @@ -1509,7 +1518,7 @@ <string name="skip_button_label" msgid="3566599811326688389">"Ignorer"</string> <string name="no_matches" msgid="6472699895759164599">"Aucune correspondance"</string> <string name="find_on_page" msgid="5400537367077438198">"Rechercher sur la page"</string> - <string name="matches_found" msgid="2296462299979507689">"{count,plural, =1{# correspondance}one{# sur {total}}other{# sur {total}}}"</string> + <string name="matches_found" msgid="2296462299979507689">"{count,plural, =1{# correspondance}one{# sur {total}}many{# sur {total}}other{# sur {total}}}"</string> <string name="action_mode_done" msgid="2536182504764803222">"OK"</string> <string name="progress_erasing" msgid="6891435992721028004">"Suppression de l\'espace de stockage partagé…"</string> <string name="share" msgid="4157615043345227321">"Partager"</string> @@ -1862,14 +1871,14 @@ <string name="data_saver_description" msgid="4995164271550590517">"Pour réduire la consommation des données, l\'Économiseur de données empêche certaines applis d\'envoyer ou de recevoir des données en arrière-plan. Les applis que vous utiliserez pourront toujours accéder aux données, mais le feront moins fréquemment. Par exemple, les images pourront ne pas s\'afficher tant que vous n\'aurez pas appuyé dessus."</string> <string name="data_saver_enable_title" msgid="7080620065745260137">"Activer l\'Économiseur de données ?"</string> <string name="data_saver_enable_button" msgid="4399405762586419726">"Activer"</string> - <string name="zen_mode_duration_minutes_summary" msgid="4555514757230849789">"{count,plural, =1{Pendant 1 minute (jusqu\'à {formattedTime})}one{Pendant # minute (jusqu\'à {formattedTime})}other{Pendant # minutes (jusqu\'à {formattedTime})}}"</string> - <string name="zen_mode_duration_minutes_summary_short" msgid="1187553788355486950">"{count,plural, =1{Pendant 1 min (jusqu\'à {formattedTime})}one{Pendant # min (jusqu\'à {formattedTime})}other{Pendant # min (jusqu\'à {formattedTime})}}"</string> - <string name="zen_mode_duration_hours_summary" msgid="3866333100793277211">"{count,plural, =1{Pendant 1 heure (jusqu\'à {formattedTime})}one{Pendant # heure (jusqu\'à {formattedTime})}other{Pendant # heures (jusqu\'à {formattedTime})}}"</string> - <string name="zen_mode_duration_hours_summary_short" msgid="687919813833347945">"{count,plural, =1{Pendant 1 h (jusqu\'à {formattedTime})}one{Pendant # h (jusqu\'à {formattedTime})}other{Pendant # h (jusqu\'à {formattedTime})}}"</string> - <string name="zen_mode_duration_minutes" msgid="2340007982276569054">"{count,plural, =1{Pendant 1 minute}one{Pendant # minute}other{Pendant # minutes}}"</string> - <string name="zen_mode_duration_minutes_short" msgid="2435756450204526554">"{count,plural, =1{Pendant 1 min}one{Pendant # min}other{Pendant # min}}"</string> - <string name="zen_mode_duration_hours" msgid="7841806065034711849">"{count,plural, =1{Pendant 1 heure}one{Pendant # heure}other{Pendant # heures}}"</string> - <string name="zen_mode_duration_hours_short" msgid="3666949653933099065">"{count,plural, =1{Pendant 1 h}one{Pendant # h}other{Pendant # h}}"</string> + <string name="zen_mode_duration_minutes_summary" msgid="4555514757230849789">"{count,plural, =1{Pendant 1 minute (jusqu\'à {formattedTime})}one{Pendant # minute (jusqu\'à {formattedTime})}many{Pendant # minutes (jusqu\'à {formattedTime})}other{Pendant # minutes (jusqu\'à {formattedTime})}}"</string> + <string name="zen_mode_duration_minutes_summary_short" msgid="1187553788355486950">"{count,plural, =1{Pendant 1 min (jusqu\'à {formattedTime})}one{Pendant # min (jusqu\'à {formattedTime})}many{Pendant # min (jusqu\'à {formattedTime})}other{Pendant # min (jusqu\'à {formattedTime})}}"</string> + <string name="zen_mode_duration_hours_summary" msgid="3866333100793277211">"{count,plural, =1{Pendant 1 heure (jusqu\'à {formattedTime})}one{Pendant # heure (jusqu\'à {formattedTime})}many{Pendant # heures (jusqu\'à {formattedTime})}other{Pendant # heures (jusqu\'à {formattedTime})}}"</string> + <string name="zen_mode_duration_hours_summary_short" msgid="687919813833347945">"{count,plural, =1{Pendant 1 h (jusqu\'à {formattedTime})}one{Pendant # h (jusqu\'à {formattedTime})}many{Pendant # h (jusqu\'à {formattedTime})}other{Pendant # h (jusqu\'à {formattedTime})}}"</string> + <string name="zen_mode_duration_minutes" msgid="2340007982276569054">"{count,plural, =1{Pendant 1 minute}one{Pendant # minute}many{Pendant # minutes}other{Pendant # minutes}}"</string> + <string name="zen_mode_duration_minutes_short" msgid="2435756450204526554">"{count,plural, =1{Pendant 1 min}one{Pendant # min}many{Pendant # min}other{Pendant # min}}"</string> + <string name="zen_mode_duration_hours" msgid="7841806065034711849">"{count,plural, =1{Pendant 1 heure}one{Pendant # heure}many{Pendant # heures}other{Pendant # heures}}"</string> + <string name="zen_mode_duration_hours_short" msgid="3666949653933099065">"{count,plural, =1{Pendant 1 h}one{Pendant # h}many{Pendant # h}other{Pendant # h}}"</string> <string name="zen_mode_until_next_day" msgid="1403042784161725038">"Jusqu\'à <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> <string name="zen_mode_until" msgid="2250286190237669079">"Jusqu\'à <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> <string name="zen_mode_alarm" msgid="7046911727540499275">"Jusqu\'à <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (alarme suivante)"</string> @@ -2000,7 +2009,7 @@ <string name="autofill_save_accessibility_title" msgid="1523225776218450005">"Enregistrer pour la saisie automatique"</string> <string name="autofill_error_cannot_autofill" msgid="6528827648643138596">"Le contenu ne peut pas être saisi automatiquement"</string> <string name="autofill_picker_no_suggestions" msgid="1076022650427481509">"Aucune suggestion de saisie automatique"</string> - <string name="autofill_picker_some_suggestions" msgid="5560549696296202701">"{count,plural, =1{1 suggestion de saisie automatique}one{# suggestion de saisie automatique}other{# suggestions de saisie automatique}}"</string> + <string name="autofill_picker_some_suggestions" msgid="5560549696296202701">"{count,plural, =1{1 suggestion de saisie automatique}one{# suggestion de saisie automatique}many{# suggestions de saisie automatique}other{# suggestions de saisie automatique}}"</string> <string name="autofill_save_title" msgid="7719802414283739775">"Enregistrer dans "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>" ?"</string> <string name="autofill_save_title_with_type" msgid="3002460014579799605">"Enregistrer la <xliff:g id="TYPE">%1$s</xliff:g> dans "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>" ?"</string> <string name="autofill_save_title_with_2types" msgid="3783270967447869241">"Enregistrer <xliff:g id="TYPE_0">%1$s</xliff:g> et <xliff:g id="TYPE_1">%2$s</xliff:g> dans "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>" ?"</string> @@ -2110,7 +2119,7 @@ <string name="mime_type_presentation_ext" msgid="8761049335564371468">"Présentation <xliff:g id="EXTENSION">%1$s</xliff:g>"</string> <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Le Bluetooth restera activé en mode Avion"</string> <string name="car_loading_profile" msgid="8219978381196748070">"Chargement…"</string> - <string name="file_count" msgid="3220018595056126969">"{count,plural, =1{{file_name} + # fichier}one{{file_name} + # fichier}other{{file_name} + # fichiers}}"</string> + <string name="file_count" msgid="3220018595056126969">"{count,plural, =1{{file_name} + # fichier}one{{file_name} + # fichier}many{{file_name} + # fichiers}other{{file_name} + # fichiers}}"</string> <string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"Aucune recommandation de personnes avec lesquelles effectuer un partage"</string> <string name="chooser_all_apps_button_label" msgid="3230427756238666328">"Liste des applications"</string> <string name="usb_device_resolve_prompt_warn" msgid="325871329788064199">"Cette application n\'a pas reçu l\'autorisation d\'enregistrer des contenus audio, mais peut le faire via ce périphérique USB."</string> diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml index e6384e6e2ed0..ee98aa2a53f0 100644 --- a/core/res/res/values-gl/strings.xml +++ b/core/res/res/values-gl/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Usar credencial do dispositivo"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Desbloquea a pantalla para continuar"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Preme o sensor con firmeza"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Non se puido procesar a impresión dixital. Téntao de novo."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Limpa o sensor de impresión dixital e téntao de novo"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Limpa o sensor e téntao de novo"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Preme o sensor con firmeza"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"O dedo moveuse demasiado lento. Téntao de novo."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Proba con outra impresión dixital"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Hai demasiada luz"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Proba a axustar a impresión dixital"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Cambia lixeiramente a posición do dedo en cada intento"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Autenticouse a cara, preme Confirmar"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Hardware de impresión dixital non dispoñible."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Non se puido configurar a impresión dixital"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Esgotouse o tempo de espera da impresión dixital. Téntao de novo."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Cancelouse a operación da impresión dixital."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"O usuario cancelou a operación da impresión dixital."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Demasiados intentos. Téntao de novo máis tarde."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Demasiados intentos. Mellor usa o bloqueo de pantalla."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Téntao de novo."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Non se rexistraron impresións dixitais."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Este dispositivo non ten sensor de impresión dixital."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Desactivouse o sensor temporalmente."</string> @@ -638,7 +643,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Visita un provedor de reparacións."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"Non se puido crear o modelo facial. Téntao de novo."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Hai demasiada iluminación. Proba cunha máis suave."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Proba con máis luz"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"Afasta o teléfono"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Achega o teléfono"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Sube o teléfono"</string> @@ -1251,8 +1257,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Iniciando aplicacións."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"Está finalizando o arranque"</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Premiches o botón de acendido, o que adoita facer que se apague a pantalla.\n\nProba a dar un toque suave namentres configuras a impresión dixital."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Toca para desactivar a pantalla"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Desactivar pantalla"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"Queres seguir verificando a impresión?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"Premiches o botón de acendido, o que adoita facer que se apague a pantalla.\n\nProba a dar un toque suave para verificar a impresión dixital."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Desactivar pantalla"</string> diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml index 9a5b87c670d4..6129f3f05187 100644 --- a/core/res/res/values-gu/strings.xml +++ b/core/res/res/values-gu/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"સ્ક્રીન લૉકનો ઉપયોગ કરો"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"આગળ વધવા માટે તમારું સ્ક્રીન લૉક દાખલ કરો"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"સેન્સર પર જોરથી દબાવો"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"ફિંગરપ્રિન્ટ પ્રક્રિયા કરી શકાઈ નથી. કૃપા કરીને ફરી પ્રયાસ કરો."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"ફિંગરપ્રિન્ટ સેન્સર સાફ કરો અને ફરી પ્રયાસ કરો"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"સેન્સર સાફ કરો અને ફરી પ્રયાસ કરો"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"સેન્સર પર જોરથી દબાવો"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"આંગળી બહુ જ ધીમેથી ખસેડી. કૃપા કરીને ફરી પ્રયાસ કરો."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"અન્ય ફિંગરપ્રિન્ટ અજમાવી જુઓ"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"અતિશય પ્રકાશિત"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"ગોઠવણી કરી જુઓ"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"દરેક વખતે સ્કૅનર પર તમારી આંગળીની સ્થિતિ સહેજ બદલતા રહો"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"ચહેરા પ્રમાણિત, કૃપા કરીને કન્ફર્મ કરો"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"ફિંગરપ્રિન્ટ હાર્ડવેર ઉપલબ્ધ નથી."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"ફિંગરપ્રિન્ટનું સેટઅપ કરી શકતા નથી"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"ફિંગરપ્રિન્ટનો સમય બાહ્ય થયો. ફરી પ્રયાસ કરો."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"ફિંગરપ્રિન્ટ ઓપરેશન રદ કર્યું."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"ફિંગરપ્રિન્ટ ચકાસવાની પ્રક્રિયા વપરાશકર્તાએ રદ કરી."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"ઘણા બધા પ્રયત્નો. પછીથી ફરી પ્રયાસ કરો."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"ઘણા બધા પ્રયાસો. વિકલ્પ તરીકે સ્ક્રીન લૉકનો ઉપયોગ કરો."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"ફરી પ્રયાસ કરો."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"કોઈ ફિંગરપ્રિન્ટની નોંધણી કરવામાં આવી નથી."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"આ ડિવાઇસમાં કોઈ ફિંગરપ્રિન્ટ સેન્સર નથી."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"સેન્સર હંગામી રૂપે બંધ કર્યું છે."</string> @@ -638,7 +643,7 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"રિપેર કરવાની સેવા આપતા પ્રદાતાની મુલાકાત લો."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"તમારા ચહેરાનું મૉડલ ન બનાવી શકાય. ફરી પ્રયાસ કરો."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"અતિશય પ્રકાશિત. થોડો હળવો પ્રકાશ અજમાવી જુઓ."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"વધુ પ્રકાશિત લાઇટિંગ અજમાવો"</string> + <string name="face_acquired_too_dark" msgid="8539853432479385326">"પૂરતો પ્રકાશ નથી"</string> <string name="face_acquired_too_close" msgid="4453646176196302462">"ફોનને વધુ દૂર લઈ જાઓ"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"ફોનને વધુ નજીક લાવો"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"ફોનને વધુ ઊંચે લઈ જાઓ"</string> @@ -1251,8 +1256,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"ઍપ્લિકેશનો શરૂ કરી રહ્યાં છે."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"બૂટ સમાપ્ત કરી રહ્યાં છે."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"તમે પાવર બટન દબાવ્યું છે — જેનાથી સામાન્ય રીતે સ્ક્રીન બંધ થઈ જાય છે.\n\nતમારી ફિંગરપ્રિન્ટનું સેટઅપ કરતી વખતે હળવેથી ટૅપ કરવાનો પ્રયાસ કરો."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"સ્ક્રીન બંધ કરવા માટે ટૅપ કરો"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"સ્ક્રીન બંધ કરો"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"શું તમારી ફિંગરપ્રિન્ટની ચકાસણી કરીએ?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"તમે પાવર બટન દબાવ્યું છે — જેનાથી સામાન્ય રીતે સ્ક્રીન બંધ થઈ જાય છે.\n\nતમારી ફિંગરપ્રિન્ટની ચકાસણી કરવા માટે, તેને હળવેથી ટૅપ કરવાનો પ્રયાસ કરો."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"સ્ક્રીન બંધ કરો"</string> diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml index 7e0e8c353704..5bc446998788 100644 --- a/core/res/res/values-hi/strings.xml +++ b/core/res/res/values-hi/strings.xml @@ -307,7 +307,7 @@ <string name="permgroupdesc_sms" msgid="5726462398070064542">"मैसेज (एसएमएस) भेजें और देखें"</string> <string name="permgrouplab_storage" msgid="17339216290379241">"फ़ाइलें"</string> <string name="permgroupdesc_storage" msgid="5378659041354582769">"अपने डिवाइस में मौजूद फ़ाइलों का ऐक्सेस दें"</string> - <string name="permgrouplab_readMediaAural" msgid="1858331312624942053">"संगीत और ऑडियो के ऐक्सेस"</string> + <string name="permgrouplab_readMediaAural" msgid="1858331312624942053">"संगीत और ऑडियो"</string> <string name="permgroupdesc_readMediaAural" msgid="7565467343667089595">"आपके डिवाइस पर संगीत और ऑडियो को ऐक्सेस करने की अनुमति"</string> <string name="permgrouplab_readMediaVisual" msgid="4724874717811908660">"फ़ोटो और वीडियो के ऐक्सेस"</string> <string name="permgroupdesc_readMediaVisual" msgid="4080463241903508688">"आपके डिवाइस पर फ़ोटो और वीडियो को ऐक्सेस करने की अनुमति"</string> @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"स्क्रीन लॉक का क्रेडेंशियल इस्तेमाल करें"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"जारी रखने के लिए, अपने स्क्रीन लॉक की पुष्टि करें"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"सेंसर को उंगली से ज़ोर से दबाएं"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"फ़िंगरप्रिंट प्रोसेस नहीं हो सका. कृपया दोबारा कोशिश करें."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"फ़िंगरप्रिंट सेंसर को साफ़ करके फिर से कोशिश करें"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"फ़िंगरप्रिंट सेंसर को साफ़ करके फिर से कोशिश करें"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"सेंसर को उंगली से ज़ोर से दबाएं"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"उंगली बहुत धीरे चलाई गई. कृपया फिर से कोशिश करें."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"किसी दूसरे फ़िंगरप्रिंट से कोशिश करें"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"बहुत रोशनी है"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"सेंसर पर सही तरीके से उंगली लगाने की कोशिश करें"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"फ़िंगरप्रिंट सेट अप करते समय, अपनी उंगली को हर बार थोड़ी अलग स्थिति में रखें"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"चेहरे की पहचान की गई, कृपया पुष्टि बटन दबाएं"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"फ़िंगरप्रिंट हार्डवेयर उपलब्ध नहीं है."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"फ़िंगरप्रिंट सेट अप नहीं किया जा सका"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"फ़िंगरप्रिंट का समय खत्म हो गया. फिर से कोशिश करें."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"फ़िंगरप्रिंट ऑपरेशन रोक दिया गया."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"उपयोगकर्ता ने फिंगरप्रिंट की पुष्टि की कार्रवाई रद्द कर दी है."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"बहुत ज़्यादा प्रयास कर लिए गए हैं. बाद में फिर से प्रयास करें."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"इससे ज़्यादा बार कोशिश नहीं की जा सकती. इसके बजाय, स्क्रीन लॉक का इस्तेमाल करें."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"फिर से कोशिश करें."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"कोई फ़िंगरप्रिंट रजिस्टर नहीं किया गया है."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"इस डिवाइस में फ़िंगरप्रिंट सेंसर नहीं है."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"सेंसर कुछ समय के लिए बंद कर दिया गया है."</string> @@ -638,7 +643,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"फ़िंगरप्रिंट सेंसर को रिपेयर करने की सेवा देने वाली कंपनी से संपर्क करें."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"चेहरे का माॅडल नहीं बन सका. फिर से कोशिश करें."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"बहुत रोशनी है. हल्की रोशनी आज़माएं."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"बेहतर रोशनी में कोशिश करें"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"फ़ोन को दूर ले जाएं"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"फ़ोन को नज़दीक लाएं"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"फ़ोन को थोड़ा और ऊपर ले जाएं"</string> @@ -1251,8 +1257,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"ऐप्स प्रारंभ होने वाले हैं"</string> <string name="android_upgrading_complete" msgid="409800058018374746">"बूट खत्म हो रहा है."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"आपने पावर बटन दबाया - आम तौर पर, इससे स्क्रीन बंद हो जाती है.\n\nअपना फ़िंगरप्रिंट सेट अप करते समय, बटन को हल्के से टैप करके देखें."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"स्क्रीन बंद करने के लिए टैप करें"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"स्क्रीन बंद करें"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"फ़िंगरप्रिंट की पुष्टि करना जारी रखना है?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"आपने पावर बटन दबाया - आम तौर पर, इससे स्क्रीन बंद हो जाती है.\n\nअपने फ़िंगरप्रिंट की पुष्टि करने के लिए, बटन पर हल्के से टैप करके देखें."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"स्क्रीन बंद करें"</string> @@ -1857,8 +1865,8 @@ <string name="package_updated_device_owner" msgid="7560272363805506941">"आपके व्यवस्थापक ने अपडेट किया है"</string> <string name="package_deleted_device_owner" msgid="2292335928930293023">"आपके व्यवस्थापक ने हटा दिया है"</string> <string name="confirm_battery_saver" msgid="5247976246208245754">"ठीक है"</string> - <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"बैटरी सेवर, गहरे रंग वाली थीम को चालू करता है. साथ ही, यह बैकग्राउंड की गतिविधि, कुछ विज़ुअल इफ़ेक्ट, कुछ खास सुविधाओं, और कुछ खास तरह के इंटरनेट कनेक्शन इस्तेमाल करने से डिवाइस को रोकता है या इन्हें बंद कर देता है."</string> - <string name="battery_saver_description" msgid="8518809702138617167">"बैटरी सेवर, गहरे रंग वाली थीम को चालू करता है. साथ ही, यह बैकग्राउंड की गतिविधि, कुछ विज़ुअल इफ़ेक्ट, कुछ खास सुविधाओं, और कुछ खास तरह के इंटरनेट कनेक्शन इस्तेमाल करने से डिवाइस को रोकता है या इन्हें बंद कर देता है."</string> + <string name="battery_saver_description_with_learn_more" msgid="5444908404021316250">"बैटरी सेवर, गहरे रंग वाली थीम को चालू करता है. साथ ही, इस मोड में बैकग्राउंड की गतिविधि, कुछ विज़ुअल इफ़ेक्ट, और कुछ खास सुविधाएं कम या बंद हो जाती हैं. कुछ इंटरनेट कनेक्शन भी पूरी तरह काम नहीं करते."</string> + <string name="battery_saver_description" msgid="8518809702138617167">"बैटरी सेवर, गहरे रंग वाली थीम को चालू करता है. साथ ही, इस मोड में बैकग्राउंड की गतिविधि, कुछ विज़ुअल इफ़ेक्ट, और कुछ सुविधाएं सीमित या बंद हो जाती हैं. कुछ इंटरनेट कनेक्शन भी पूरी तरह काम नहीं करते."</string> <string name="data_saver_description" msgid="4995164271550590517">"डेटा खर्च को कम करने के लिए, डेटा बचाने की सेटिंग कुछ ऐप्लिकेशन को बैकग्राउंड में डेटा भेजने या डेटा पाने से रोकती है. फ़िलहाल, जिस ऐप्लिकेशन का इस्तेमाल किया जा रहा है वह डेटा ऐक्सेस कर सकता है, लेकिन ऐसा कभी-कभी ही हो पाएगा. उदाहरण के लिए, इमेज तब तक दिखाई नहीं देंगी, जब तक उन पर टैप नहीं किया जाएगा."</string> <string name="data_saver_enable_title" msgid="7080620065745260137">"डेटा बचाने की सेटिंग चालू करें?"</string> <string name="data_saver_enable_button" msgid="4399405762586419726">"चालू करें"</string> diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml index 820071473000..79661603be0d 100644 --- a/core/res/res/values-hr/strings.xml +++ b/core/res/res/values-hr/strings.xml @@ -587,13 +587,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Upotreba zaključavanja zaslona"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Upotrijebite zaključavanje zaslona da biste nastavili"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Čvrsto pritisnite senzor"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Obrada otiska prsta nije uspjela. Pokušajte ponovo."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Očistite senzor otiska prsta i pokušajte ponovno"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Očistite senzor i pokušajte ponovno"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Čvrsto pritisnite senzor"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Presporo pomicanje prsta. Pokušajte ponovo."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Isprobajte drugi otisak prsta"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Presvijetlo"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Pokušajte ga prilagoditi"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Svaki put lagano promijenite položaj prsta"</string> <string-array name="fingerprint_acquired_vendor"> @@ -605,13 +608,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Lice je autentificirano, pritisnite Potvrdi"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Hardver za otisak prsta nije dostupan."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Postavljanje otiska prsta nije uspjelo"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Isteklo je vrijeme čekanja za otisak prsta. Pokušajte ponovo."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Radnja otiska prsta otkazana je."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Radnju s otiskom prsta otkazao je korisnik."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Previše pokušaja. Pokušajte ponovo kasnije."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Previše pokušaja. Umjesto toga upotrijebite zaključavanje zaslona."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Pokušajte ponovo."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Nije registriran nijedan otisak prsta."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Ovaj uređaj nema senzor otiska prsta."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Senzor je privremeno onemogućen."</string> @@ -639,7 +644,7 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Posjetite davatelja usluga popravaka."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"Izrada modela lica nije uspjela. Pokušajte ponovo."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Presvijetlo je. Pokušajte sa slabijim svjetlom."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Pokušajte s jačim osvjetljenjem"</string> + <string name="face_acquired_too_dark" msgid="8539853432479385326">"Nema dovoljno svjetla"</string> <string name="face_acquired_too_close" msgid="4453646176196302462">"Udaljite telefon"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Približite telefon"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Pomaknite telefon prema gore"</string> @@ -1252,8 +1257,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Pokretanje aplikacija."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"Završetak inicijalizacije."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Pritisnuli ste tipku za uključivanje/isključivanje, čime se obično isključuje zaslon.\n\nPokušajte lagano dodirnuti dok postavljate svoj otisak prsta."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Dodirnite da biste isključili zaslon"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Isključi zaslon"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"Nastaviti s potvrđivanjem otiska prsta?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"Pritisnuli ste tipku za uključivanje/isključivanje, čime se obično isključuje zaslon.\n\nPokušajte lagano dodirnuti da biste potvrdili svoj otisak prsta."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Isključi zaslon"</string> diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml index f92b1d79430f..887ef503fb48 100644 --- a/core/res/res/values-hu/strings.xml +++ b/core/res/res/values-hu/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Képernyőzár használata"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"A folytatáshoz adja meg a képernyőzár hitelesítési adatait"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Nyomja meg határozottan az érzékelőt"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Nem sikerült feldolgozni az ujjlenyomatot. Próbálkozzon újra."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Tisztítsa meg az ujjlenyomat-érzékelőt, majd próbálja újra"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Tisztítsa meg az érzékelőt, majd próbálja újra"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Nyomja meg határozottan az érzékelőt"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Túl lassan húzta az ujját. Próbálkozzon újra."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Próbálkozzon másik ujjlenyomattal"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Túl világos"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Próbálja beállítani"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Módosítsa minden alkalommal kis mértékben ujja helyzetét."</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Arc hitelesítve; nyomja meg a Megerősítés lehetőséget"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Az ujjlenyomathoz szükséges hardver nem érhető el."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Nem sikerült beállítani az ujjlenyomatot"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Az ujjlenyomat-beolvasási műveletkor időtúllépés történt. Próbálkozzon újra."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Ujjlenyomattal kapcsolatos művelet megszakítva"</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Az ujjlenyomattal kapcsolatos műveletet a felhasználó megszakította."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Túl sok próbálkozás. Próbálja újra később."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Túl sok próbálkozás. Használja inkább a képernyőzárat."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Próbálkozzon újra."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Nincsenek regisztrált ujjlenyomatok."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Ez az eszköz nem rendelkezik ujjlenyomat-érzékelővel."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Az érzékelő átmenetileg le van tiltva."</string> @@ -638,7 +643,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Keresse fel a szervizt."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"Nem lehet létrehozni az arcmodellt. Próbálja újra."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Túl világos. Próbálja kevésbé erős világítással."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Próbálja jobb megvilágítás mellett"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"Tartsa távolabb a telefont"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Tartsa közelebb a telefont"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Emelje magasabbra a telefont"</string> @@ -1251,8 +1257,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Kezdő alkalmazások."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"Rendszerindítás befejezése."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Megnyomta a bekapcsológombot — ezzel általában kikapcsol a képernyő.\n\nPróbáljon finoman rákoppintani az ujjlenyomat beállítása közben."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Koppintson a képernyő kikapcsolásához"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Képernyő kikapcsolása"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"Folytatja az ujjlenyomat ellenőrzését?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"Megnyomta a bekapcsológombot — ezzel általában kikapcsol a képernyő.\n\nPróbáljon finoman rákoppintani az ujjlenyomat ellenőrzéséhez."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Kikapcsolom"</string> diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml index 1e4900cf3d50..0f2746e995a6 100644 --- a/core/res/res/values-hy/strings.xml +++ b/core/res/res/values-hy/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Էկրանի կողպում"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Շարունակելու համար ապակողպեք էկրանը"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Մատը ուժեղ սեղմեք սկաների վրա"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Չհաջողվեց մշակել մատնահետքը: Նորից փորձեք:"</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Մաքրեք մատնահետքերի սկաները և նորից փորձեք"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Մաքրեք սկաները և նորից փորձեք"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Մատը ուժեղ սեղմեք սկաների վրա"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Շատ դանդաղ անցկացրիք մատը: Փորձեք նորից:"</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Փորձեք մեկ այլ մատնահետք"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Շատ լուսավոր է"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Փորձեք փոխել մատի դիրքը"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Ամեն անգամ թեթևակի փոխեք մատի դիրքը"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Դեմքը ճանաչվեց: Սեղմեք «Հաստատել»:"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Մատնահետքի սարքն անհասանելի է:"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Հնարավոր չէ կարգավորել մատնահետքը"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Մատնահետքի գրանցման ժամանակը սպառվել է: Փորձեք նորից:"</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Իսկորոշումը մատնահետքի միջոցով չեղարկվեց:"</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Մատնահետքով նույնականացման գործողությունը չեղարկվել է օգտատիրոջ կողմից:"</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Չափից շատ փորձ եք կատարել: Փորձեք նորից քիչ հետո:"</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Չափազանց շատ փորձեր են արվել։ Օգտագործեք էկրանի կողպումը։"</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Փորձեք նորից:"</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Գրանցված մատնահետք չկա:"</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Այս սարքը չունի մատնահետքերի սկաներ։"</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Տվիչը ժամանակավորապես անջատված է:"</string> @@ -638,7 +643,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Այցելեք սպասարկման կենտրոն։"</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"Չհաջողվեց ստեղծել ձեր դեմքի մոդելը։ Նորից փորձեք։"</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Շատ լուսավոր է։ Փորձեք ավելի թեթև լուսավորություն։"</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Ավելի պայծառ դարձրեք լուսավորությունը"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"Փոքր-ինչ հեռու պահեք հեռախոսը"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Մոտեցրեք հեռախոսը"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Բարձրացրեք հեռախոսը"</string> @@ -1251,8 +1257,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Հավելվածները մեկնարկում են:"</string> <string name="android_upgrading_complete" msgid="409800058018374746">"Բեռնումն ավարտվում է:"</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Դուք սեղմել եք սնուցման կոճակը։ Սովորաբար դրա արդյունքում էկրանն անջատվում է։\n\nՄատնահետքը ավելացնելու համար թեթևակի հպեք կոճակին։"</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Հպեք՝ էկրանն անջատելու համար"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Անջատել էկրանը"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"Շարունակե՞լ մատնահետքի սկանավորումը"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"Դուք սեղմել եք սնուցման կոճակը։ Սովորաբար դրա արդյունքում էկրանն անջատվում է։\n\nՄատնահետքը սկանավորելու համար թեթևակի հպեք կոճակին։"</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Անջատել էկրանը"</string> diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml index 1a7ecf183c00..6072abbdb27c 100644 --- a/core/res/res/values-in/strings.xml +++ b/core/res/res/values-in/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Gunakan kunci layar"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Masukkan kunci layar untuk melanjutkan"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Tekan sensor dengan kuat"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Tidak dapat memproses sidik jari. Coba lagi."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Bersihkan sensor sidik jari lalu coba lagi"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Bersihkan sensor lalu coba lagi"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Tekan sensor dengan kuat"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Jari digerakkan terlalu lambat. Coba lagi."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Coba sidik jari lain"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Terlalu terang"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Coba sesuaikan"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Ubah sedikit posisi jari di setiap percobaan"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Wajah diautentikasi, silakan tekan konfirmasi"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Hardware sidik jari tidak tersedia."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Tidak dapat menyiapkan sidik jari"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Waktu sidik jari habis. Coba lagi."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Operasi sidik jari dibatalkan."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Operasi sidik jari dibatalkan oleh pengguna."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Terlalu banyak upaya. Coba lagi nanti."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Terlalu banyak upaya gagal. Gunakan kunci layar."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Coba lagi."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Tidak ada sidik jari yang terdaftar."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Perangkat ini tidak memiliki sensor sidik jari."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Sensor dinonaktifkan untuk sementara."</string> @@ -638,7 +643,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Kunjungi penyedia reparasi."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"Tidak dapat membuat model wajah Anda. Coba lagi."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Terlalu terang. Coba cahaya yang lebih lembut."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Coba pencahayaan yang lebih cerah"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"Jauhkan ponsel"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Dekatkan ponsel"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Gerakkan ponsel ke atas"</string> @@ -1251,8 +1257,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Memulai aplikasi."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"Menyelesaikan boot."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Anda menekan tombol daya; tindakan ini biasanya akan menonaktifkan layar.\n\nCoba ketuk lembut saat menyiapkan sidik jari Anda."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Ketuk untuk menonaktifkan layar"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Nonaktifkan layar"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"Lanjutkan verifikasi sidik jari?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"Anda menekan tombol daya; tindakan ini biasanya akan menonaktifkan layar.\n\nCoba ketuk lembut untuk memverifikasi sidik jari Anda."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Nonaktifkan layar"</string> diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml index 24720ef10e40..0d73bcee3515 100644 --- a/core/res/res/values-is/strings.xml +++ b/core/res/res/values-is/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Nota skjálás"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Sláðu inn skjálásinn þinn til að halda áfram"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Ýttu ákveðið á lesarann"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Ekki var hægt að vinna úr fingrafarinu. Reyndu aftur."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Hreinsaðu fingrafaralesarann og reyndu aftur"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Hreinsaðu lesarann og reyndu aftur"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Ýttu ákveðið á lesarann"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Fingurinn hreyfðist of hægt. Reyndu aftur."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Prófaðu annað fingrafar"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Of bjart"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Prófaðu að breyta stöðu fingursins"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Breyttu stöðu fingursins örlítið í hvert skipti"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Andlit staðfest, ýttu til að staðfesta"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Fingrafarsvélbúnaður ekki til staðar."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Ekki er hægt að setja upp fingrafar"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Tímamörk runnu út fyrir fingrafar. Reyndu aftur."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Hætt við fingrafarsaðgerð."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Notandi hætti við að nota fingrafar."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Of margar tilraunir. Reyndu aftur síðar."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Of margar tilraunir. Notaðu skjálás í staðinn."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Reyndu aftur."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Engin fingraför hafa verið skráð."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Þetta tæki er ekki með fingrafaralesara."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Slökkt tímabundið á skynjara."</string> @@ -638,7 +643,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Þú verður að fara á verkstæði."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"Ekki tekst að búa til andlitslíkan. Reyndu aftur."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Of bjart. Prófaðu mýkri lýsingu."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Prófaðu sterkari lýsingu"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"Færðu símann lengra frá"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Færðu símann nær"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Færðu símann hærra"</string> @@ -1251,8 +1257,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Ræsir forrit."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"Lýkur ræsingu."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Þú ýttir á aflrofann. Yfirleitt slekkur það á skjánum.\n\nPrófaðu að ýta laust þegar þú setur upp fingrafarið."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Ýttu til að slökkva á skjá"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Slökkva á skjá"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"Halda áfram að staðfesta fingrafarið?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"Þú ýttir á aflrofann. Yfirleitt slekkur það á skjánum.\n\nPrófaðu að ýta laust til að staðfesta fingrafarið þitt."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Slökkva á skjá"</string> diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml index 841d07d16c43..465f06a49ad9 100644 --- a/core/res/res/values-it/strings.xml +++ b/core/res/res/values-it/strings.xml @@ -51,6 +51,7 @@ <string name="needPuk2" msgid="7032612093451537186">"Digita il PUK2 per sbloccare la SIM."</string> <string name="enablePin" msgid="2543771964137091212">"Operazione non riuscita; attiva blocco SIM/RUIM."</string> <plurals name="pinpuk_attempts" formatted="false" msgid="1619867269012213584"> + <item quantity="many">You have <xliff:g id="NUMBER_1">%d</xliff:g> remaining attempts before SIM is locked.</item> <item quantity="other">Hai ancora <xliff:g id="NUMBER_1">%d</xliff:g> tentativi a disposizione prima che la SIM venga bloccata.</item> <item quantity="one">Hai ancora <xliff:g id="NUMBER_0">%d</xliff:g> tentativo a disposizione prima che la SIM venga bloccata.</item> </plurals> @@ -180,7 +181,7 @@ <string name="low_memory" product="watch" msgid="3479447988234030194">"La memoria dell\'orologio è piena. Elimina alcuni file per liberare spazio."</string> <string name="low_memory" product="tv" msgid="6663680413790323318">"Lo spazio di archiviazione del dispositivo Android TV è pieno. Elimina alcuni file per liberare spazio."</string> <string name="low_memory" product="default" msgid="2539532364144025569">"Spazio di archiviazione del telefono esaurito. Elimina alcuni file per liberare spazio."</string> - <string name="ssl_ca_cert_warning" msgid="7233573909730048571">"{count,plural, =1{Autorità di certificazione installata}other{Autorità di certificazione installate}}"</string> + <string name="ssl_ca_cert_warning" msgid="7233573909730048571">"{count,plural, =1{Autorità di certificazione installata}many{Autorità di certificazione installate}other{Autorità di certificazione installate}}"</string> <string name="ssl_ca_cert_noti_by_unknown" msgid="4961102218216815242">"Da una terza parte sconosciuta"</string> <string name="ssl_ca_cert_noti_by_administrator" msgid="4564941950768783879">"Dall\'amministratore del tuo profilo di lavoro"</string> <string name="ssl_ca_cert_noti_managed" msgid="217337232273211674">"Da <xliff:g id="MANAGING_DOMAIN">%s</xliff:g>"</string> @@ -254,7 +255,7 @@ <string name="bugreport_option_interactive_summary" msgid="8493795476325339542">"Utilizza questa opzione nella maggior parte dei casi. Ti consente di monitorare l\'avanzamento della segnalazione, di inserire maggiori dettagli relativi al problema e di acquisire screenshot. Potrebbero essere omesse alcune sezioni meno utilizzate il cui inserimento nella segnalazione richiede molto tempo."</string> <string name="bugreport_option_full_title" msgid="7681035745950045690">"Report completo"</string> <string name="bugreport_option_full_summary" msgid="1975130009258435885">"Utilizza questa opzione per ridurre al minimo l\'interferenza di sistema quando il dispositivo non risponde, è troppo lento oppure quando ti servono tutte le sezioni della segnalazione. Non puoi inserire altri dettagli o acquisire altri screenshot."</string> - <string name="bugreport_countdown" msgid="6418620521782120755">"{count,plural, =1{Lo screenshot per la segnalazione di bug verrà acquisito tra # secondo.}other{Lo screenshot per la segnalazione di bug verrà acquisito tra # secondi.}}"</string> + <string name="bugreport_countdown" msgid="6418620521782120755">"{count,plural, =1{Lo screenshot per la segnalazione di bug verrà acquisito tra # secondo.}many{Lo screenshot per la segnalazione di bug verrà acquisito tra # secondi.}other{Lo screenshot per la segnalazione di bug verrà acquisito tra # secondi.}}"</string> <string name="bugreport_screenshot_success_toast" msgid="7986095104151473745">"Screenshot con segnalazione di bug effettuato correttamente"</string> <string name="bugreport_screenshot_failure_toast" msgid="6736320861311294294">"Impossibile acquisire screenshot con segnalazione di bug"</string> <string name="global_action_toggle_silent_mode" msgid="8464352592860372188">"Modalità silenziosa"</string> @@ -586,13 +587,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Usa il blocco schermo"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Inserisci il blocco schermo per continuare"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Premi con decisione sul sensore"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Impossibile elaborare l\'impronta. Riprova."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Pulisci il sensore di impronte digitali e riprova"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Pulisci il sensore e riprova"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Premi con decisione sul sensore"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Movimento del dito troppo lento. Riprova."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Prova con un\'altra impronta"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Troppa luce"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Prova a regolare"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Cambia leggermente la posizione del dito ogni volta"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +608,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Volto autenticato, premi Conferma"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Hardware per l\'impronta non disponibile."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Impossibile configurare l\'impronta"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Timeout impronta. Riprova."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Operazione associata all\'impronta annullata."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Operazione di autenticazione dell\'impronta annullata dall\'utente."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Troppi tentativi. Riprova più tardi."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Troppi tentativi. Usa il blocco schermo."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Riprova."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Nessuna impronta digitale registrata."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Questo dispositivo non dispone di sensore di impronte."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Sensore temporaneamente disattivato."</string> @@ -638,7 +644,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Contatta un fornitore di servizi di riparazione."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"Impossibile creare il modello del volto. Riprova."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Troppa luce. Prova con una luce più soft."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Prova con più luce"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"Allontana il telefono"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Avvicina il telefono"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Sposta il telefono più in alto"</string> @@ -1088,7 +1095,7 @@ <string name="enable_explore_by_touch_warning_message" product="default" msgid="4312979647356179250">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> vuole attivare la funzione Esplora al tocco. Quando la funzione Esplora al tocco è attiva, puoi ascoltare o visualizzare le descrizioni di ciò che stai toccando oppure interagire con il telefono tramite gesti."</string> <string name="oneMonthDurationPast" msgid="4538030857114635777">"1 mese fa"</string> <string name="beforeOneMonthDurationPast" msgid="8315149541372065392">"Oltre 1 mese fa"</string> - <string name="last_num_days" msgid="2393660431490280537">"{count,plural, =1{Ultimo giorno}other{Ultimi # giorni}}"</string> + <string name="last_num_days" msgid="2393660431490280537">"{count,plural, =1{Ultimo giorno}many{Ultimi # giorni}other{Ultimi # giorni}}"</string> <string name="last_month" msgid="1528906781083518683">"Ultimo mese"</string> <string name="older" msgid="1645159827884647400">"Precedente"</string> <string name="preposition_for_date" msgid="2780767868832729599">"<xliff:g id="DATE">%s</xliff:g>"</string> @@ -1115,14 +1122,14 @@ <string name="duration_hours_shortest_future" msgid="2979276794547981674">"tra <xliff:g id="COUNT">%d</xliff:g> h"</string> <string name="duration_days_shortest_future" msgid="3392722163935571543">"tra <xliff:g id="COUNT">%d</xliff:g> g"</string> <string name="duration_years_shortest_future" msgid="5537464088352970388">"tra <xliff:g id="COUNT">%d</xliff:g> a"</string> - <string name="duration_minutes_relative" msgid="8620337701051015593">"{count,plural, =1{# minuto fa}other{# minuti fa}}"</string> - <string name="duration_hours_relative" msgid="4836449961693180253">"{count,plural, =1{# ora fa}other{# ore fa}}"</string> - <string name="duration_days_relative" msgid="621965767567258302">"{count,plural, =1{# giorno fa}other{# giorni fa}}"</string> - <string name="duration_years_relative" msgid="8731202348869424370">"{count,plural, =1{# anno fa}other{# anni fa}}"</string> - <string name="duration_minutes_relative_future" msgid="5259574171747708115">"{count,plural, =1{# minuto}other{# minuti}}"</string> - <string name="duration_hours_relative_future" msgid="6670440478481140565">"{count,plural, =1{# ora}other{# ore}}"</string> - <string name="duration_days_relative_future" msgid="8870658635774250746">"{count,plural, =1{# giorno}other{# giorni}}"</string> - <string name="duration_years_relative_future" msgid="8855853883925918380">"{count,plural, =1{# anno}other{# anni}}"</string> + <string name="duration_minutes_relative" msgid="8620337701051015593">"{count,plural, =1{# minuto fa}many{# minuti fa}other{# minuti fa}}"</string> + <string name="duration_hours_relative" msgid="4836449961693180253">"{count,plural, =1{# ora fa}many{# ore fa}other{# ore fa}}"</string> + <string name="duration_days_relative" msgid="621965767567258302">"{count,plural, =1{# giorno fa}many{# giorni fa}other{# giorni fa}}"</string> + <string name="duration_years_relative" msgid="8731202348869424370">"{count,plural, =1{# anno fa}many{# anni fa}other{# anni fa}}"</string> + <string name="duration_minutes_relative_future" msgid="5259574171747708115">"{count,plural, =1{# minuto}many{# minuti}other{# minuti}}"</string> + <string name="duration_hours_relative_future" msgid="6670440478481140565">"{count,plural, =1{# ora}many{# ore}other{# ore}}"</string> + <string name="duration_days_relative_future" msgid="8870658635774250746">"{count,plural, =1{# giorno}many{# giorni}other{# giorni}}"</string> + <string name="duration_years_relative_future" msgid="8855853883925918380">"{count,plural, =1{# anno}many{# anni}other{# anni}}"</string> <string name="VideoView_error_title" msgid="5750686717225068016">"Problemi video"</string> <string name="VideoView_error_text_invalid_progressive_playback" msgid="3782449246085134720">"Questo video non è valido per lo streaming su questo dispositivo."</string> <string name="VideoView_error_text_unknown" msgid="7658683339707607138">"Impossibile riprodurre il video."</string> @@ -1251,8 +1258,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Avvio app."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"Conclusione dell\'avvio."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Hai premuto il tasto di accensione; in genere questa azione disattiva lo schermo.\n\nProva a toccare leggermente il tasto di accensione durante la configurazione della tua impronta."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Tocca per disattivare lo schermo"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Disattiva lo schermo"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"Vuoi continuare a verificare l\'impronta?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"Hai premuto il tasto di accensione; in genere questa azione disattiva lo schermo.\n\nProva a toccare leggermente il tasto di accensione per verificare la tua impronta."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Disattiva lo schermo"</string> @@ -1509,7 +1518,7 @@ <string name="skip_button_label" msgid="3566599811326688389">"Salta"</string> <string name="no_matches" msgid="6472699895759164599">"Nessuna corrispondenza"</string> <string name="find_on_page" msgid="5400537367077438198">"Trova nella pagina"</string> - <string name="matches_found" msgid="2296462299979507689">"{count,plural, =1{# corrispondenza}other{# di {total}}}"</string> + <string name="matches_found" msgid="2296462299979507689">"{count,plural, =1{# corrispondenza}many{# di {total}}other{# di {total}}}"</string> <string name="action_mode_done" msgid="2536182504764803222">"Fine"</string> <string name="progress_erasing" msgid="6891435992721028004">"Cancellazione archivio condiviso…"</string> <string name="share" msgid="4157615043345227321">"Condividi"</string> @@ -1862,14 +1871,14 @@ <string name="data_saver_description" msgid="4995164271550590517">"Per contribuire a ridurre l\'utilizzo dei dati, la funzionalità Risparmio dati impedisce ad alcune app di inviare o ricevere dati in background. Un\'app in uso può accedere ai dati, ma potrebbe farlo con meno frequenza. Per esempio, è possibile che le immagini non vengano visualizzate finché non le tocchi."</string> <string name="data_saver_enable_title" msgid="7080620065745260137">"Attivare Risparmio dati?"</string> <string name="data_saver_enable_button" msgid="4399405762586419726">"Attiva"</string> - <string name="zen_mode_duration_minutes_summary" msgid="4555514757230849789">"{count,plural, =1{Per un minuto (fino alle ore {formattedTime})}other{Per # minuti (fino alle ore {formattedTime})}}"</string> - <string name="zen_mode_duration_minutes_summary_short" msgid="1187553788355486950">"{count,plural, =1{Per 1 min (fino alle ore {formattedTime})}other{Per # min (fino alle ore {formattedTime})}}"</string> - <string name="zen_mode_duration_hours_summary" msgid="3866333100793277211">"{count,plural, =1{Per 1 ora (fino alle ore {formattedTime})}other{Per # ore (fino alle ore {formattedTime})}}"</string> - <string name="zen_mode_duration_hours_summary_short" msgid="687919813833347945">"{count,plural, =1{Per 1 h (fino alle ore {formattedTime})}other{Per # h (fino alle ore {formattedTime})}}"</string> - <string name="zen_mode_duration_minutes" msgid="2340007982276569054">"{count,plural, =1{Per un minuto}other{Per # minuti}}"</string> - <string name="zen_mode_duration_minutes_short" msgid="2435756450204526554">"{count,plural, =1{Per 1 min}other{Per # min}}"</string> - <string name="zen_mode_duration_hours" msgid="7841806065034711849">"{count,plural, =1{Per 1 ora}other{Per # ore}}"</string> - <string name="zen_mode_duration_hours_short" msgid="3666949653933099065">"{count,plural, =1{Per 1 h}other{Per # h}}"</string> + <string name="zen_mode_duration_minutes_summary" msgid="4555514757230849789">"{count,plural, =1{Per un minuto (fino alle ore {formattedTime})}many{Per # minuti (fino alle ore {formattedTime})}other{Per # minuti (fino alle ore {formattedTime})}}"</string> + <string name="zen_mode_duration_minutes_summary_short" msgid="1187553788355486950">"{count,plural, =1{Per 1 min (fino alle ore {formattedTime})}many{Per # min (fino alle ore {formattedTime})}other{Per # min (fino alle ore {formattedTime})}}"</string> + <string name="zen_mode_duration_hours_summary" msgid="3866333100793277211">"{count,plural, =1{Per 1 ora (fino alle ore {formattedTime})}many{Per # ore (fino alle ore {formattedTime})}other{Per # ore (fino alle ore {formattedTime})}}"</string> + <string name="zen_mode_duration_hours_summary_short" msgid="687919813833347945">"{count,plural, =1{Per 1 h (fino alle ore {formattedTime})}many{Per # h (fino alle ore {formattedTime})}other{Per # h (fino alle ore {formattedTime})}}"</string> + <string name="zen_mode_duration_minutes" msgid="2340007982276569054">"{count,plural, =1{Per un minuto}many{Per # minuti}other{Per # minuti}}"</string> + <string name="zen_mode_duration_minutes_short" msgid="2435756450204526554">"{count,plural, =1{Per 1 min}many{Per # min}other{Per # min}}"</string> + <string name="zen_mode_duration_hours" msgid="7841806065034711849">"{count,plural, =1{Per 1 ora}many{Per # ore}other{Per # ore}}"</string> + <string name="zen_mode_duration_hours_short" msgid="3666949653933099065">"{count,plural, =1{Per 1 h}many{Per # h}other{Per # h}}"</string> <string name="zen_mode_until_next_day" msgid="1403042784161725038">"Fino a: <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> <string name="zen_mode_until" msgid="2250286190237669079">"Fino a <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> <string name="zen_mode_alarm" msgid="7046911727540499275">"Fino a <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (prossima sveglia)"</string> @@ -2000,7 +2009,7 @@ <string name="autofill_save_accessibility_title" msgid="1523225776218450005">"Salva per Compilazione automatica"</string> <string name="autofill_error_cannot_autofill" msgid="6528827648643138596">"Impossibile compilare automaticamente i contenuti"</string> <string name="autofill_picker_no_suggestions" msgid="1076022650427481509">"Nessun suggerimento di Compilazione automatica"</string> - <string name="autofill_picker_some_suggestions" msgid="5560549696296202701">"{count,plural, =1{Un suggerimento di compilazione automatica}other{# suggerimenti di compilazione automatica}}"</string> + <string name="autofill_picker_some_suggestions" msgid="5560549696296202701">"{count,plural, =1{Un suggerimento di compilazione automatica}many{# suggerimenti di compilazione automatica}other{# suggerimenti di compilazione automatica}}"</string> <string name="autofill_save_title" msgid="7719802414283739775">"Vuoi salvare su "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string> <string name="autofill_save_title_with_type" msgid="3002460014579799605">"Vuoi salvare la <xliff:g id="TYPE">%1$s</xliff:g> su "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string> <string name="autofill_save_title_with_2types" msgid="3783270967447869241">"Vuoi salvare <xliff:g id="TYPE_0">%1$s</xliff:g> e <xliff:g id="TYPE_1">%2$s</xliff:g> su "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string> @@ -2110,7 +2119,7 @@ <string name="mime_type_presentation_ext" msgid="8761049335564371468">"Presentazione <xliff:g id="EXTENSION">%1$s</xliff:g>"</string> <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"Il Bluetooth rimane attivo durante l\'uso della modalità aereo"</string> <string name="car_loading_profile" msgid="8219978381196748070">"Caricamento"</string> - <string name="file_count" msgid="3220018595056126969">"{count,plural, =1{{file_name} + # file}other{{file_name} + # file}}"</string> + <string name="file_count" msgid="3220018595056126969">"{count,plural, =1{{file_name} + # file}many{{file_name} + # file}other{{file_name} + # file}}"</string> <string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"Nessuna persona consigliata per la condivisione"</string> <string name="chooser_all_apps_button_label" msgid="3230427756238666328">"Elenco di app"</string> <string name="usb_device_resolve_prompt_warn" msgid="325871329788064199">"A questa app non è stata concessa l\'autorizzazione di registrazione, ma l\'app potrebbe acquisire l\'audio tramite questo dispositivo USB."</string> diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml index b8278415f1f9..b4a69d87aa43 100644 --- a/core/res/res/values-iw/strings.xml +++ b/core/res/res/values-iw/strings.xml @@ -588,13 +588,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"שימוש בנעילת מסך"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"יש לבטל את נעילת המסך כדי להמשיך"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"לוחצים לחיצה חזקה על החיישן"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"לא ניתן היה לעבד את טביעת האצבע. אפשר לנסות שוב."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"עליך לנקות את חיישן טביעות האצבע ולנסות שוב"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"עליך לנקות את החיישן ולנסות שוב"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"לוחצים לחיצה חזקה על החיישן"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"הזזת את האצבע לאט מדי. יש לנסות שוב."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"יש להשתמש בטביעת אצבע אחרת"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"בהיר מדי"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"יש לנסות ולשנות את תנוחת האצבע"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"צריך לשנות מעט את תנוחת האצבע בכל פעם"</string> <string-array name="fingerprint_acquired_vendor"> @@ -606,13 +609,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"זיהוי הפנים בוצע. יש ללחוץ על אישור"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"החומרה לזיהוי טביעות אצבעות אינה זמינה."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"לא ניתן להגדיר טביעת אצבע"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"נגמר הזמן הקצוב לטביעת אצבע. אפשר לנסות שוב."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"פעולת טביעת האצבע בוטלה."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"פעולת טביעת האצבע בוטלה על ידי המשתמש."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"יותר מדי ניסיונות. יש לנסות שוב מאוחר יותר."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"בוצעו יותר מדי ניסיונות. יש להשתמש בנעילת המסך במקום זאת."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"כדאי לנסות שוב."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"לא נסרקו טביעות אצבע."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"במכשיר הזה אין חיישן טביעות אצבע."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"החיישן מושבת באופן זמני."</string> @@ -640,7 +645,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"צריך ליצור קשר עם ספק תיקונים."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"לא ניתן ליצור את התבנית לזיהוי הפנים. יש לנסות שוב."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"בהירה מדי. צריך תאורה עדינה יותר."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"כדאי לנסות בתאורה חזקה יותר"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"צריך להרחיק את הטלפון"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"צריך לקרב את הטלפון"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"צריך להגביה את הטלפון"</string> @@ -1253,8 +1259,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"מתבצעת הפעלה של אפליקציות."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"תהליך האתחול בשלבי סיום."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"לחצת על לחצן ההפעלה – בדרך כלל הפעולה הזו מכבה את המסך.\n\nעליך לנסות להקיש בעדינות במהלך ההגדרה של טביעת האצבע שלך."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"יש להקיש כדי לכבות את המסך"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"כיבוי המסך"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"להמשיך לאמת את טביעת האצבע שלך?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"לחצת על לחצן ההפעלה – בדרך כלל הפעולה הזו מכבה את המסך.\n\nעליך לנסות להקיש בעדינות כדי לאמת את טביעת האצבע שלך."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"כיבוי המסך"</string> diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml index 9b651e2c4e6e..0adc48f5ffa4 100644 --- a/core/res/res/values-ja/strings.xml +++ b/core/res/res/values-ja/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"画面ロックの使用"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"続行するには画面ロックを入力してください"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"センサーにしっかりと押し当ててください"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"指紋を処理できませんでした。もう一度お試しください。"</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"指紋認証センサーの汚れを取り除いて、もう一度お試しください"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"センサーの汚れを取り除いて、もう一度お試しください"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"センサーにしっかりと押し当ててください"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"指の動きが遅すぎました。もう一度お試しください。"</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"別の指紋をお試しください"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"明るすぎます"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"調整してみてください"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"毎回、指を置く位置を少し変えてください"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"顔を認証しました。[確認] を押してください"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"指紋認証ハードウェアは使用できません。"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"指紋を設定できません"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"指紋の読み取りがタイムアウトになりました。もう一度お試しください。"</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"指紋の操作をキャンセルしました。"</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"指紋の操作がユーザーによりキャンセルされました。"</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"所定の回数以上間違えました。しばらくしてからもう一度お試しください。"</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"試行回数が上限を超えました。代わりに画面ロックを使用してください。"</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"もう一度お試しください。"</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"指紋が登録されていません。"</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"このデバイスには指紋認証センサーがありません。"</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"センサーが一時的に無効になっています。"</string> @@ -638,7 +643,7 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"修理業者に調整を依頼してください。"</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"顔モデルを作成できません。もう一度お試しください。"</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"明るすぎます。もっと暗い場所でお試しください。"</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"もっと明るい場所でお試しください"</string> + <string name="face_acquired_too_dark" msgid="8539853432479385326">"十分な光がありません"</string> <string name="face_acquired_too_close" msgid="4453646176196302462">"スマートフォンをもっと離してください"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"スマートフォンをもっと近づけてください"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"スマートフォンをもっと上げてください"</string> @@ -1251,8 +1256,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"アプリを起動しています。"</string> <string name="android_upgrading_complete" msgid="409800058018374746">"ブートを終了しています。"</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"電源ボタンを押しました。通常、この操作で画面が OFF になります。\n\n指紋を設定する場合は電源ボタンに軽く触れてみましょう。"</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"タップして画面を OFF にする"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"画面を OFF にする"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"指紋の確認を続行しますか?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"電源ボタンを押しました。通常、この操作で画面が OFF になります。\n\n指紋を確認するには、電源ボタンに軽く触れてみましょう。"</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"画面を OFF にする"</string> diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml index 1f18c905d166..eef6510be532 100644 --- a/core/res/res/values-ka/strings.xml +++ b/core/res/res/values-ka/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"გამოიყენეთ ეკრანის დაბლოკვა"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"გასაგრძელებლად შედით ეკრანის დაბლოკვაში"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"მაგრად დააჭირეთ სენსორს"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"თითის ანაბეჭდის დამუშავება ვერ მოხერხდა. გთხოვთ, ცადოთ ხელახლა."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"გაწმინდეთ თითის ანაბეჭდის სენსორი და ხელახლა ცადეთ"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"გაწმინდეთ სენსორი და ხელახლა ცადეთ"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"მაგრად დააჭირეთ სენსორს"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"თითის აღება მეტისმეტად ნელა მოხდა. გთხოვთ, სცადოთ ხელახლა."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"ცადეთ სხვა თითის ანაბეჭდი"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"ზედმეტად ნათელია"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"ცადეთ დარეგულირება"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"ოდნავ შეცვალეთ თითის დაჭერის ადგილი ყოველ ჯერზე"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"სახე ავტორიზებულია, დააჭირეთ დადასტურებას"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"თითის ანაბეჭდის აპარატურა არ არის ხელმისაწვდომი."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"თითის ანაბეჭდის დაყენება ვერ ხერხდება"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"თითის ანაბეჭდის ლოდინის დრო ამოიწურა. სცადეთ ხელახლა."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"თითის ანაბეჭდის აღების ოპერაცია გაუქმდა."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"თითის ანაბეჭდის ოპერაცია გააუქმა მომხმარებელმა."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"ძალიან ბევრი მცდელობა იყო. სცადეთ მოგვიანებით."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"მეტისმეტად ბევრი მცდელობა იყო. სანაცვლოდ გამოიყენეთ ეკრანის დაბლოკვა."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"ხელახლა სცადეთ"</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"თითის ანაბეჭდები რეგისტრირებული არ არის."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"ამ მოწყობილობას არ აქვს თითის ანაბეჭდის სენსორი."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"სენსორი დროებით გათიშულია."</string> @@ -638,7 +643,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"ეწვიეთ შეკეთების სერვისის პროვაიდერს."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"თქვენი სახის მოდელი ვერ იქმნება. ცადეთ ხელახლა."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"მეტისმეტად ნათელია. ცადეთ უფრო სუსტი განათება."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"ცადეთ უფრო ძლიერი განათება"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"გაწიეთ ტელეფონი უფრო შორს"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"მიიტანეთ ტელეფონი უფრო ახლოს"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"აწიეთ ტელეფონი ზემოთ"</string> @@ -1251,8 +1257,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"აპების ჩართვა"</string> <string name="android_upgrading_complete" msgid="409800058018374746">"ჩატვირთვის დასასრული."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"თქვენ დააჭირეთ ჩართვის ღილაკს — ჩვეულებრივ, ის ეკრანს გამორთავს.\n\nთქვენი თითის ანაბეჭდის დაყენებისას ცადეთ მსუბუქად შეხება."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"შეეხეთ ეკრანის გამოსართავად"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"ეკრანის გამორთვა"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"გსურთ ანაბეჭდის დადასტურების გაგრძელება?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"თქვენ დააჭირეთ ჩართვის ღილაკს — ჩვეულებრივ, ის ეკრანს გამორთავს.\n\nთქვენი თითის ანაბეჭდის დასადასტურებლად ცადეთ მსუბუქად შეხება."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"ეკრანის გამორთვა"</string> diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml index 1ba08e910065..ae13a1d8df31 100644 --- a/core/res/res/values-kk/strings.xml +++ b/core/res/res/values-kk/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Экран құлпын пайдалану"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Жалғастыру үшін экран құлпын енгізіңіз."</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Сканерді қатты басыңыз."</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Саусақ ізін өңдеу мүмкін емес. Әрекетті қайталаңыз."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Саусақ ізін оқу сканерін тазалап, әрекетті қайталаңыз."</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Сканерді тазалап, әрекетті қайталаңыз."</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Сканерді қатты басыңыз."</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Саусағыңызды тым баяу қозғалттыңыз. Әрекетті қайталап көріңіз."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Басқа саусақ ізін байқап көріңіз."</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Тым жарық."</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Дұрыстап қойып көріңіз."</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Саусағыңыздың қалпын аздап өзгертіп тұрыңыз."</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Бет танылды, \"Растау\" түймесін басыңыз"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Саусақ ізі жабдығы қолжетімді емес."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Саусақ ізін орнату мүмкін емес."</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Саусақ ізін күту уақыты бітті. Әрекетті қайталаңыз."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Саусақ ізі операциясынан бас тартылған."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Пайдаланушы саусақ ізі операциясынан бас тартты."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Талпыныстар тым көп. Кейінірек қайталап көріңіз."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Тым көп әрекет жасалды. Орнына экран құлпын пайдаланыңыз."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Әрекетті қайталаңыз."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Саусақ іздері тіркелмеген."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Бұл құрылғыда саусақ ізін оқу сканері жоқ."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Датчик уақытша өшірулі."</string> @@ -638,7 +643,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Жөндеу қызметіне барыңыз."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"Бет үлгісі жасалмады. Қайталап көріңіз."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Тым ашық. Күңгірттеу жарық керек."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Жарық деңгейін арттырыңыз."</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"Телефонды алшақ ұстаңыз."</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Телефонды жақынырақ ұстаңыз."</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Телефонды жоғарырақ ұстаңыз."</string> @@ -1251,8 +1257,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Қолданбалар іске қосылуда."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"Қосуды аяқтауда."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Қуат түймесін бастыңыз. Бұл әдетте экранды өшіреді.\n\nСаусақ ізін реттеу үшін, оны жайлап түртіп көріңіз."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Экранды өшіру үшін түртіңіз"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Экранды өшіру"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"Саусақ ізін растауды жалғастырасыз ба?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"Қуат түймесін бастыңыз. Бұл әдетте экранды өшіреді.\n\nСаусақ ізін растау үшін, оны жайлап түртіп көріңіз."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Экранды өшіру"</string> diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml index 38fb1d024cc8..38d8c80032b1 100644 --- a/core/res/res/values-km/strings.xml +++ b/core/res/res/values-km/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"ប្រើការចាក់សោអេក្រង់"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"បញ្ចូលការចាក់សោអេក្រង់របស់អ្នក ដើម្បីបន្ត"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"សង្កត់លើឧបករណ៍ចាប់សញ្ញាឱ្យណែន"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"មិនអាចដំណើរការស្នាមម្រាមដៃបានទេ។ សូមព្យាយាមម្តងទៀត។"</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"សម្អាតឧបករណ៍ចាប់ស្នាមម្រាមដៃ រួចព្យាយាមម្ដងទៀត"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"សម្អាតឧបករណ៍ចាប់សញ្ញា រួចព្យាយាមម្ដងទៀត"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"សង្កត់លើឧបករណ៍ចាប់សញ្ញាឱ្យណែន"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"ចលនាម្រាមដៃយឺតពេកហើយ។ សូមព្យាយាមម្តងទៀត។"</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"សាកល្បងប្រើស្នាមម្រាមដៃផ្សេងទៀត"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"ភ្លឺពេក"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"សាកល្បងកែតម្រូវ"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"ប្ដូរទីតាំងម្រាមដៃរបស់អ្នកតិចៗគ្រប់ពេល"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"បានផ្ទៀងផ្ទាត់មុខ សូមចុចបញ្ជាក់"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"ផ្នែករឹងស្នាមម្រាមដៃមិនមានទេ។"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"មិនអាចរៀបចំស្នាមម្រាមដៃបានទេ"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"ស្នាមម្រាមដៃបានអស់ម៉ោង។ សូមព្យាយាមម្តងទៀត។"</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"បានបោះបង់ប្រតិបត្តិការស្នាមម្រាមដៃ។"</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"ប្រតិបត្តិការស្នាមម្រាមដៃត្រូវបានបោះបង់ដោយអ្នកប្រើប្រាស់។"</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"ព្យាយាមចូលច្រើនពេកហើយ។ សូមព្យាយាមម្តងទៀតពេលក្រោយ។"</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"ព្យាយាមច្រើនដងពេក។ សូមប្រើការចាក់សោអេក្រង់ជំនួសវិញ។"</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"ព្យាយាមម្ដងទៀត។"</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"មិនមានការចុះឈ្មោះស្នាមម្រាមដៃទេ។"</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"ឧបករណ៍នេះមិនមានឧបករណ៍ចាប់ស្នាមម្រាមដៃទេ។"</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"បានបិទឧបករណ៍ចាប់សញ្ញាជាបណ្តោះអាសន្ន។"</string> @@ -638,7 +643,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"ទាក់ទងក្រុមហ៊ុនផ្ដល់ការជួសជុល។"</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"មិនអាចបង្កើតគំរូមុខរបស់អ្នកបានទេ។ សូមព្យាយាមម្ដងទៀត។"</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"ភ្លឺពេក។ សូមសាកល្បងប្រើពន្លឺស្រាលជាងនេះ។"</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"សាកល្បងប្រើពន្លឺភ្លឺជាងនេះ"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"ដាក់ទូរសព្ទឱ្យឆ្ងាយជាងមុន"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"ដាក់ទូរសព្ទឱ្យជិតជាងមុន"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"ដាក់ទូរសព្ទឱ្យខ្ពស់ជាងមុន"</string> @@ -1251,8 +1257,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"ចាប់ផ្ដើមកម្មវិធី។"</string> <string name="android_upgrading_complete" msgid="409800058018374746">"បញ្ចប់ការចាប់ផ្ដើម។"</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"អ្នកបានចុចប៊ូតុងថាមពល — ជាធម្មតាការធ្វើបែបនេះនឹងបិទអេក្រង់។\n\nសាកល្បងចុចថ្នមៗ ខណៈពេលកំពុងរៀបចំស្នាមម្រាមដៃរបស់អ្នក។"</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"ចុច ដើម្បីបិទអេក្រង់"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"បិទអេក្រង់"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"បន្តផ្ទៀងផ្ទាត់ស្នាមម្រាមដៃរបស់អ្នកឬ?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"អ្នកបានចុចប៊ូតុងថាមពល — ជាធម្មតាការធ្វើបែបនេះនឹងបិទអេក្រង់។\n\nសាកល្បងចុចថ្នមៗ ដើម្បីផ្ទៀងផ្ទាត់ស្នាមម្រាមដៃរបស់អ្នក។"</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"បិទអេក្រង់"</string> diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml index 11dc96b269ca..bccd3bfb5fd9 100644 --- a/core/res/res/values-kn/strings.xml +++ b/core/res/res/values-kn/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"ಸ್ಕ್ರೀನ್ ಲಾಕ್ ಬಳಸಿ"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"ಮುಂದುವರಿಯಲು ನಿಮ್ಮ ಸ್ಕ್ರೀನ್ ಲಾಕ್ ಅನ್ನು ನಮೂದಿಸಿ"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"ಸೆನ್ಸರ್ ಮೇಲೆ ದೃಢವಾಗಿ ಒತ್ತಿರಿ"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಅನ್ನು ಪ್ರಕ್ರಿಯೆಗೊಳಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ. ದಯವಿಟ್ಟು ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"ಫಿಂಗರ್ ಪ್ರಿಂಟ್ ಸೆನ್ಸರ್ ಸ್ವಚ್ಛಗೊಳಿಸಿ ಹಾಗೂ ಪುನಃ ಪ್ರಯತ್ನಿಸಿ"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"ಸೆನ್ಸರ್ ಸ್ವಚ್ಛಗೊಳಿಸಿ ಹಾಗೂ ಪುನಃ ಪ್ರಯತ್ನಿಸಿ"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"ಸೆನ್ಸರ್ ಮೇಲೆ ದೃಢವಾಗಿ ಒತ್ತಿರಿ"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"ಬೆರಳನ್ನು ತುಂಬಾ ನಿಧಾನವಾಗಿ ಸರಿಸಲಾಗಿದೆ. ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"ಮತ್ತೊಂದು ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಪ್ರಯತ್ನಿಸಿ"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"ತುಂಬಾ ಪ್ರಕಾಶಮಾನವಾಗಿದೆ"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"ಹೊಂದಿಸಲು ಪ್ರಯತ್ನಿಸಿ"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"ಪ್ರತಿ ಬಾರಿಯೂ ನಿಮ್ಮ ಬೆರಳಿನ ಸ್ಥಾನವನ್ನು ಸ್ವಲ್ಪ ಮಟ್ಟಿಗೆ ಬದಲಾಯಿಸಿ"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"ಮುಖವನ್ನು ದೃಢೀಕರಿಸಲಾಗಿದೆ, ದೃಢೀಕರಣವನ್ನು ಒತ್ತಿ"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಹಾರ್ಡ್ವೇರ್ ಲಭ್ಯವಿಲ್ಲ."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಅನ್ನು ಸೆಟಪ್ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಅವಧಿ ಮೀರಿದೆ. ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಕಾರ್ಯಾಚರಣೆಯನ್ನು ರದ್ದುಮಾಡಲಾಗಿದೆ."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"ಬಳಕೆದಾರರು ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಕಾರ್ಯಾಚರಣೆಯನ್ನು ರದ್ದುಪಡಿಸಿದ್ದಾರೆ."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"ಹಲವಾರು ಪ್ರಯತ್ನಗಳು. ನಂತರ ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"ಹಲವು ಬಾರಿ ಪ್ರಯತ್ನಿಸಿದ್ದೀರಿ. ಬದಲಾಗಿ ಪರದೆಲಾಕ್ ಬಳಸಿ."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"ಯಾವುದೇ ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಅನ್ನು ನೋಂದಣಿ ಮಾಡಿಲ್ಲ."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"ಈ ಸಾಧನವು ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಸೆನ್ಸರ್ ಅನ್ನು ಹೊಂದಿಲ್ಲ."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"ಸೆನ್ಸಾರ್ ಅನ್ನು ತಾತ್ಕಾಲಿಕವಾಗಿ ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ."</string> @@ -638,7 +643,7 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"ರಿಪೇರಿ ಮಾಡುವವರನ್ನು ಸಂಪರ್ಕಿಸಿ."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"ಫೇಸ್ ಮಾಡೆಲ್ ರಚಿಸಲು ಸಾಧ್ಯವಿಲ್ಲ. ಪುನಃ ಪ್ರಯತ್ನಿಸಿ."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"ತುಂಬಾ ಪ್ರಕಾಶಮಾನವಾಗಿದೆ ಮಂದ ಪ್ರಕಾಶಮಾನವಿರುವ ಲೈಟ್ ಬಳಸಿ"</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"ಪ್ರಕಾಶಮಾನವಾದ ಲೈಟಿಂಗ್ ಬಳಸಿ"</string> + <string name="face_acquired_too_dark" msgid="8539853432479385326">"ಸಾಕಷ್ಟು ಬೆಳಕು ಇಲ್ಲ"</string> <string name="face_acquired_too_close" msgid="4453646176196302462">"ಫೋನ್ ಅನ್ನು ದೂರಕ್ಕೆ ಸರಿಸಿ"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"ಫೋನ್ ಅನ್ನು ಸಮೀಪಕ್ಕೆ ತನ್ನಿ"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"ಫೋನ್ ಅನ್ನು ಮೇಲಕ್ಕೆ ಎತ್ತಿ ಹಿಡಿಯಿರಿ."</string> @@ -1251,8 +1256,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"ಅಪ್ಲಿಕೇಶನ್ಗಳನ್ನು ಪ್ರಾರಂಭಿಸಲಾಗುತ್ತಿದೆ."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"ಬೂಟ್ ಪೂರ್ಣಗೊಳಿಸಲಾಗುತ್ತಿದೆ."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"ನೀವು ಪವರ್ ಬಟನ್ ಒತ್ತಿದ್ದೀರಿ — ಇದು ಸಾಮಾನ್ಯವಾಗಿ ಸ್ಕ್ರೀನ್ ಅನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸುತ್ತದೆ.\n\nನಿಮ್ಮ ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಅನ್ನು ಹೊಂದಿಸುವಾಗ ಲಘುವಾಗಿ ಟ್ಯಾಪ್ ಮಾಡಲು ಪ್ರಯತ್ನಿಸಿ."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"ಸ್ಕ್ರೀನ್ ಆಫ್ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"ಸ್ಕ್ರೀನ್ ಆಫ್ ಮಾಡಿ"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಪರಿಶೀಲನೆ ಮುಂದುವರಿಸುವುದೇ?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"ನೀವು ಪವರ್ ಬಟನ್ ಒತ್ತಿದ್ದೀರಿ — ಇದು ಸಾಮಾನ್ಯವಾಗಿ ಸ್ಕ್ರೀನ್ ಅನ್ನು ನಿಷ್ಕ್ರಿಯಗೊಳಿಸುತ್ತದೆ.\n\nನಿಮ್ಮ ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಅನ್ನು ಪರಿಶೀಲಿಸಲು ಲಘುವಾಗಿ ಟ್ಯಾಪ್ ಮಾಡಲು ಪ್ರಯತ್ನಿಸಿ."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"ಸ್ಕ್ರೀನ್ ಆಫ್ ಮಾಡಿ"</string> diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml index bc04d1e13339..1b0c3916d61a 100644 --- a/core/res/res/values-ko/strings.xml +++ b/core/res/res/values-ko/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"화면 잠금 사용"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"계속하려면 화면 잠금용 사용자 인증 정보를 입력하세요"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"센서 위에 손가락을 좀 더 오래 올려놓으세요."</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"지문을 인식할 수 없습니다. 다시 시도해 주세요."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"지문 센서를 닦은 후 다시 시도해 보세요."</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"센서를 닦은 후 다시 시도해 보세요."</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"센서 위에 손가락을 좀 더 오래 올려놓으세요."</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"손가락을 너무 느리게 움직였습니다. 다시 시도해 주세요."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"다른 지문으로 시도"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"너무 밝음"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"조정 시도"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"지문을 등록할 때마다 손가락을 조금씩 이동하세요"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"얼굴이 인증되었습니다. 확인을 누르세요"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"지문 인식 하드웨어를 사용할 수 없습니다."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"지문을 설정할 수 없음"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"지문 인식 시간이 초과되었습니다. 다시 시도하세요."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"지문 인식 작업이 취소되었습니다."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"사용자가 지문 인식 작업을 취소했습니다."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"시도 횟수가 너무 많습니다. 나중에 다시 시도하세요."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"시도 횟수가 너무 많습니다. 화면 잠금을 대신 사용하세요."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"다시 시도해 보세요."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"등록된 지문이 없습니다."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"기기에 지문 센서가 없습니다."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"센서가 일시적으로 사용 중지되었습니다."</string> @@ -638,7 +643,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"수리업체에 방문하세요."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"얼굴 모델을 만들 수 없습니다. 다시 시도해 주세요."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"너무 밝습니다. 조명 밝기를 조금 낮춰보세요."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"조명을 밝게 해 보세요."</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"휴대전화를 얼굴에서 더 멀리 떨어뜨려 주세요."</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"휴대전화를 얼굴에 더 가까이 가져와 주세요."</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"휴대전화를 위로 이동하세요"</string> @@ -1251,8 +1257,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"앱을 시작하는 중입니다."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"부팅 완료"</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"전원 버튼을 눌렀습니다. 이러면 보통 화면이 꺼집니다.\n\n지문 설정 중에 가볍게 탭하세요."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"탭하여 화면 끄기"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"화면 끄기"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"지문 인증을 계속할까요?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"전원 버튼을 눌렀습니다. 이러면 보통 화면이 꺼집니다.\n\n지문을 인식하려면 화면을 가볍게 탭하세요."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"화면 끄기"</string> diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml index 483b8c968412..707f6f582d94 100644 --- a/core/res/res/values-ky/strings.xml +++ b/core/res/res/values-ky/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Экран кулпусун колдонуу"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Улантуу үчүн экрандын кулпусун киргизиңиз"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Сенсорду катуу басыңыз"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Манжа изи иштелбей койду. Кайталап көрүңүз."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Манжа изинин сенсорун тазалап, кайра аракет кылыңыз"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Сенсорду тазалап, кайра аракет кылыңыз"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Сенсорду катуу басыңыз"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Манжа өтө жай жылды. Кайталап көрүңүз."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Башка манжа изин байкап көрүңүз"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Өтө жарык"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Тууралап көрүңүз"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Манжаңыздын абалын ар жолкусунда бир аз өзгөртүп туруңуз"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Жүздүн аныктыгы текшерилди, эми \"Ырастоону\" басыңыз"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Манжа изинин аппараттык камсыздоосу жеткиликтүү эмес."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Манжа изи жөндөлбөй жатат"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Манжа изин күтүү мөөнөтү бүттү. Кайталап көрүңүз."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Манжа изи иш-аракети жокко чыгарылды."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Манжа изи операциясын колдонуучу жокко чыгарды."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Аракеттер өтө көп болду. Бир аздан кийин кайталап көрүңүз."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Өтө көп жолу аракет кылдыңыз. Экранды кулпулоо функциясын колдонуңуз."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Кайра бир аракеттениңиз."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Бир да манжа изи катталган эмес."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Бул түзмөктө манжа изинин сенсору жок."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Сенсор убактылуу өчүрүлгөн."</string> @@ -638,7 +643,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Тейлөө кызматына кайрылыңыз."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"Жүзүңүздүн үлгүсү түзүлгөн жок. Кайталаңыз."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Өтө жарык. Жарыктыкты азайтып көрүңүз."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Жарыгыраак жерге туруңуз"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"Телефонду алыстатыңыз"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Телефонду жакындатыңыз"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Телефонду жогору жылдырыңыз"</string> @@ -1251,8 +1257,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Колдонмолорду иштетип баштоо"</string> <string name="android_upgrading_complete" msgid="409800058018374746">"Жүктөлүүдө"</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Кубат баскычын бастыңыз — адатта, бул экранды өчүрөт.\n\nМанжаңыздын изин жөндөп жатканда аны акырын басып көрүңүз."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Экранды өчүрүү үчүн таптаңыз"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Экранды өчүрүү"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"Манжаңыздын изин ырастоону улантасызбы?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"Кубат баскычын бастыңыз — адатта, бул экранды өчүрөт.\n\nМанжаңыздын изин ырастоо үчүн аны акырын басып көрүңүз."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Экранды өчүрүү"</string> diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml index 54d6af48feb2..0f44f56e9631 100644 --- a/core/res/res/values-lo/strings.xml +++ b/core/res/res/values-lo/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"ໃຊ້ການລັອກໜ້າຈໍ"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"ໃສ່ການລັອກໜ້າຈໍຂອງທ່ານເພື່ອສືບຕໍ່"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"ກົດຢູ່ເຊັນເຊີໃຫ້ແໜ້ນ"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"ບໍ່ສາມາດດຳເນີນການລາຍນີ້ວມືໄດ້. ກະລຸນາລອງໃໝ່ອີກ."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"ໃຫ້ອະນາໄມເຊັນເຊີລາຍນິ້ວມືແລ້ວລອງໃໝ່"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"ໃຫ້ອະນາໄມເຊັນເຊີແລ້ວລອງໃໝ່"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"ກົດຢູ່ເຊັນເຊີໃຫ້ແໜ້ນ"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"ຍ້າຍນີ້ວມືໄປຊ້າເກີນໄປ. ກະລຸນາລອງໃໝ່ອີກ."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"ລອງໃຊ້ລາຍນິ້ວມືອື່ນ"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"ແຈ້ງເກີນໄປ"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"ກະລຸນາລອງປັບແກ້"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"ປ່ຽນຕຳແໜ່ງຂອງນິ້ວມືຂອງທ່ານເລັກນ້ອຍໃນແຕ່ລະເທື່ອ"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"ພິສູດຢືນຢັນໃບໜ້າແລ້ວ, ກະລຸນາກົດຢືນຢັນ"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"ບໍ່ມີຮາດແວລາຍນີ້ວມືໃຫ້ຢູ່."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"ບໍ່ສາມາດຕັ້ງຄ່າລາຍນິ້ວມືໄດ້"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"ເວລາລາຍນີ້ວມືບໍ່ເຂົ້າເຖິງໄດ້. ລອງໃໝ່ອີກ."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"ຍົກເລີກການດຳເນີນການລາຍນີ້ວມືແລ້ວ."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"ຜູ້ໃຊ້ໄດ້ຍົກເລີກຄຳສັ່ງລາຍນິ້ວມືແລ້ວ."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"ມີຄວາມພະຍາຍາມຫຼາຍຄັ້ງເກີນໄປ. ລອງໃໝ່ພາຍຫຼັງ."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"ພະຍາຍາມຫຼາຍເທື່ອເກີນໄປ. ກະລຸນາໃຊ້ການລອກໜ້າຈໍແທນ."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"ລອງໃໝ່ອີກຄັ້ງ."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"ບໍ່ມີການລົງທະບຽນລາຍນິ້ວມື."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"ອຸປະກອນນີ້ບໍ່ມີເຊັນເຊີລາຍນິ້ວມື."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"ປິດການເຮັດວຽກຂອງເຊັນເຊີໄວ້ຊົ່ວຄາວແລ້ວ."</string> @@ -638,7 +643,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"ກະລຸນາໄປຫາຜູ້ໃຫ້ບໍລິການສ້ອມແປງ."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"ບໍ່ສາມາດສ້າງຮູບແບບໃບໜ້າຂອງທ່ານໄດ້. ກະລຸນາລອງໃໝ່."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"ແຈ້ງເກີນໄປ. ລອງຄ່ອຍແສງໄຟລົງ."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"ກະລຸນາລອງໃຊ້ສະພາບແສງທີ່ແຈ້ງຂຶ້ນ"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"ເລື່ອນໂທລະສັບອອກໄປໄກຂຶ້ນ"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"ເລື່ອນໂທລະສັບເຂົ້າໄປໃກ້ຂຶ້ນ"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"ຍົກໂທລະສັບໃຫ້ສູງຂຶ້ນ"</string> @@ -1251,8 +1257,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"ກຳລັງເປີດແອັບຯ."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"ກຳລັງສຳເລັດການເປີດລະບົບ."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"ທ່ານກົດປຸ່ມເປີດປິດ, ປົກກະຕິນີ້ຈະປິດໜ້າຈໍ.\n\nລອງແຕະຄ່ອຍໆໃນລະຫວ່າງຕັ້ງຄ່າລາຍນິ້ວມືຂອງທ່ານ."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"ແຕະເພື່ອປິດໜ້າຈໍ"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"ປິດໜ້າຈໍ"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"ສືບຕໍ່ການຢັ້ງຢືນລາຍນິ້ວມືຂອງທ່ານບໍ?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"ທ່ານກົດປຸ່ມເປີດປິດ, ປົກກະຕິນີ້ຈະເປັນການປິດໜ້າຈໍ.\n\nໃຫ້ລອງແຕະຄ່ອຍໆເພື່ອຢັ້ງຢືນລາຍນິ້ວມືຂອງທ່ານ."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"ປິດໜ້າຈໍ"</string> diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml index 319ae1518a3d..c36d5c860e7b 100644 --- a/core/res/res/values-lt/strings.xml +++ b/core/res/res/values-lt/strings.xml @@ -588,13 +588,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Naudoti ekrano užraktą"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Jei norite tęsti, įveskite ekrano užraktą"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Tvirtai paspauskite jutiklį"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Nepavyko apdoroti piršto antspaudo. Bandykite dar kartą."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Nuvalykite kontrolinio kodo jutiklį ir bandykite dar kartą"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Nuvalykite jutiklį ir bandykite dar kartą"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Tvirtai paspauskite jutiklį"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Per lėtai judinate pirštą. Bandykite dar kartą."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Pabandykite kitą kontrolinį kodą"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Per šviesu"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Pabandykite koreguoti"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Kaskart šiek tiek pakeiskite piršto poziciją"</string> <string-array name="fingerprint_acquired_vendor"> @@ -606,13 +609,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Veidas autentifikuotas, paspauskite patvirtinimo mygtuką"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Piršto antspaudo aparatinė įranga nepasiekiama."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Nepavyko nustatyti kontrolinio kodo"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Baigėsi piršto antspaudo nustatymo skirtasis laikas. Bandykite dar kartą."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Piršto antspaudo operacija atšaukta."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Piršto antspaudo operaciją atšaukė naudotojas."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Per daug bandymų. Vėliau bandykite dar kartą."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Per daug bandymų. Naudokite ekrano užraktą."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Bandykite dar kartą."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Neužregistruota jokių kontrolinių kodų."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Šiame įrenginyje nėra kontrolinio kodo jutiklio."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Jutiklis laikinai išjungtas."</string> @@ -640,7 +645,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Apsilankykite pas taisymo paslaugos teikėją."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"Nepavyko sukurti veido modelio. Band. dar kartą."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Per šviesu. Išbandykite mažesnį apšvietimą."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Išbandykite šviesesnį apšvietimą"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"Laikykite telefoną toliau"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Laikykite telefoną arčiau"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Laikykite telefoną aukščiau"</string> @@ -1253,8 +1259,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Paleidžiamos programos."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"Užbaigiamas paleidimas."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Paspaudėte maitinimo mygtuką, taip paprastai išjungiamas ekranas.\n\nNustatydami kontrolinį kodą, pabandykite jį švelniai paliesti."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Palieskite, kad išjungtumėte ekraną"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Išjungti ekraną"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"Tęsti kontrolinio kodo patvirtinimą?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"Paspaudėte maitinimo mygtuką, taip paprastai išjungiamas ekranas.\n\nNorėdami patvirtinti kontrolinį kodą, pabandykite jį švelniai paliesti."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Išjungti ekraną"</string> diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml index e8c973900fe4..8f2a60aa6a1b 100644 --- a/core/res/res/values-lv/strings.xml +++ b/core/res/res/values-lv/strings.xml @@ -587,13 +587,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Ekrāna bloķēšanas metodes izmantošana"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Lai turpinātu, ievadiet ekrāna bloķēšanas informāciju"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Stingri spiediet pirkstu pie sensora"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Nevarēja apstrādāt pirksta nospiedumu. Lūdzu, mēģiniet vēlreiz."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Notīriet pirkstu nospiedumu sensoru un mēģiniet vēlreiz"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Notīriet sensoru un mēģiniet vēlreiz"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Stingri spiediet pirkstu pie sensora"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Pārāk lēna pirksta kustība. Lūdzu, mēģiniet vēlreiz."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Izmēģiniet citu pirksta nospiedumu"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Pārāk spilgts"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Mēģiniet mainīt pozīciju"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Katru reizi mazliet mainiet pirksta pozīciju."</string> <string-array name="fingerprint_acquired_vendor"> @@ -605,13 +608,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Seja ir autentificēta. Nospiediet pogu Apstiprināt."</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Nospieduma aparatūra nav pieejama."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Nevar iestatīt pirksta nospiedumu"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Pirkstu nospiedumu nolasīšanas aparatūras noildze. Mēģiniet vēlreiz."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Nospieduma darbība neizdevās."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Lietotājs atcēla pirksta nospieduma darbību."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Pārāk daudz mēģinājumu. Vēlāk mēģiniet vēlreiz."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Pārāk daudz mēģinājumu. Izmantojiet ekrāna bloķēšanu."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Mēģiniet vēlreiz."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Nav reģistrēts neviens pirksta nospiedums."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Šajā ierīcē nav pirksta nospieduma sensora."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Sensors ir īslaicīgi atspējots."</string> @@ -639,7 +644,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Sazinieties ar remonta pakalpojumu sniedzēju."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"Nevar izveidot sejas modeli. Mēģiniet vēlreiz."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Pārāk spilgts. Izmēģiniet maigāku apgaismojumu."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Izmēģiniet spožāku apgaismojumu"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"Pārvietojiet tālruni tālāk."</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Pārvietojiet tālruni tuvāk."</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Paceliet tālruni augstāk."</string> @@ -1252,8 +1258,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Notiek lietotņu palaišana."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"Tiek pabeigta sāknēšana."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Jūs nospiedāt barošanas pogu — tādējādi parasti tiek izslēgts ekrāns.\n\nMēģiniet viegli pieskarties, iestatot pirksta nospiedumu."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Pieskarieties, lai izslēgtu ekrānu"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Izslēgt ekrānu"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"Vai apstiprināt pirksta nospiedumu?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"Jūs nospiedāt barošanas pogu — tādējādi parasti tiek izslēgts ekrāns.\n\nMēģiniet viegli pieskarties, lai apstiprinātu pirksta nospiedumu."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Izslēgt ekrānu"</string> diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml index 2439bd5be235..6fddb60528a8 100644 --- a/core/res/res/values-mk/strings.xml +++ b/core/res/res/values-mk/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Користи заклучување екран"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Внесете го заклучувањето на екранот за да продолжите"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Цврсто притиснете на сензорот"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Отпечатокот не може да се обработи. Обидете се повторно."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Исчистете го сензорот за отпечатоци и обидете се повторно"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Исчистете го сензорот и обидете се повторно"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Цврсто притиснете на сензорот"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Прстот се движеше премногу бавно. Обидете се повторно."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Пробајте со друг отпечаток"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Премногу светло"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Пробајте да го приспособите прстот"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Менувајте ја положбата на прстот по малку секој пат"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Лицето е проверено, притиснете го копчето „Потврди“"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Хардверот за отпечатоци не е достапен."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Не може да се постави отпечаток"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Се достигна времето на истекување на отпечатокот. Обидете се повторно."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Операцијата со отпечаток се откажа."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Корисникот ја откажа потврдата со отпечаток."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Премногу обиди. Обидете се повторно подоцна."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Премногу обиди. Користете заклучување екран."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Обидете се повторно."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Не се запишани отпечатоци."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Уредов нема сензор за отпечатоци."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Сензорот е привремено оневозможен."</string> @@ -638,7 +643,7 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Однесете го на поправка."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"Не може да создаде модел на лик. Обидете се пак."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Премногу светла. Пробајте со послабо осветлување."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Пробајте со посилно осветлување"</string> + <string name="face_acquired_too_dark" msgid="8539853432479385326">"Нема доволно светлина"</string> <string name="face_acquired_too_close" msgid="4453646176196302462">"Оддалечете го телефонот"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Доближете го телефонот"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Кренете го телефонот погоре"</string> @@ -1251,8 +1256,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Се стартуваат апликациите."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"Подигањето завршува."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Го притиснавте копчето за вклучување — така обично се исклучува екранот.\n\nДопрете лесно додека го поставувате отпечатокот."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Допрете за да го исклучите екранот"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Исклучи го екранот"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"Да продолжи потврдувањето на отпечаток?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"Го притиснавте копчето за вклучување — така обично се исклучува екранот.\n\nДопрете лесно за да го потврдите отпечатокот."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Исклучи го екранот"</string> diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml index cb6903f85d75..cda64c973607 100644 --- a/core/res/res/values-ml/strings.xml +++ b/core/res/res/values-ml/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"സ്ക്രീൻ ലോക്ക് ഉപയോഗിക്കുക"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"തുടരാൻ നിങ്ങളുടെ സ്ക്രീൻ ലോക്ക് നൽകുക"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"സെൻസറിന് മുകളിൽ ശക്തിയായി അമർത്തുക"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"ഫിംഗർപ്രിന്റ് പ്രോസസ് ചെയ്യാനായില്ല. വീണ്ടും ശ്രമിക്കുക."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"ഫിംഗർപ്രിന്റ് സെൻസർ വൃത്തിയാക്കിയ ശേഷം വീണ്ടും ശ്രമിക്കുക"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"സെൻസർ വൃത്തിയാക്കിയ ശേഷം വീണ്ടും ശ്രമിക്കുക"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"സെൻസറിന് മുകളിൽ ശക്തിയായി അമർത്തുക"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"വിരൽ വളരെ പതുക്കെ നീക്കി. വീണ്ടും ശ്രമിക്കുക."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"മറ്റൊരു ഫിംഗർപ്രിന്റ് ഉപയോഗിച്ച് നോക്കുക"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"തെളിച്ചം വളരെയധികമാണ്"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"അൽപ്പം നീക്കി നോക്കൂ"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"ഓരോ തവണയും നിങ്ങളുടെ വിരലിന്റെ സ്ഥാനം ചെറുതായി മാറ്റുക"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"മുഖം പരിശോധിച്ചുറപ്പിച്ചു, സ്ഥിരീകരിക്കുക അമർത്തുക"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"ഫിംഗർപ്രിന്റ് ഹാർഡ്വെയർ ലഭ്യമല്ല."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"ഫിംഗർപ്രിന്റ് സജ്ജീകരിക്കാനാകില്ല"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"ഫിംഗർപ്രിന്റ് നൽകേണ്ട സമയം കഴിഞ്ഞു. വീണ്ടും ശ്രമിക്കുക."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"ഫിംഗർപ്രിന്റ് പ്രവർത്തനം റദ്ദാക്കി."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"ഉപയോക്താവ് റദ്ദാക്കിയ ഫിംഗർപ്രിന്റ് പ്രവർത്തനം."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"നിരവധി തവണ ശ്രമിച്ചു. പിന്നീട് വീണ്ടും ശ്രമിക്കുക."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"നിരവധി ശ്രമങ്ങൾ. പകരം സ്ക്രീൻ ലോക്ക് ഉപയോഗിക്കുക."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"വീണ്ടും ശ്രമിക്കൂ."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"വിരലടയാളങ്ങൾ എൻറോൾ ചെയ്തിട്ടില്ല."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"ഈ ഉപകരണത്തിൽ ഫിംഗർപ്രിന്റ് സെൻസറില്ല."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"സെൻസർ താൽക്കാലികമായി പ്രവർത്തനരഹിതമാക്കി."</string> @@ -638,7 +643,7 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"റിപ്പയർ കേന്ദ്രം സന്ദർശിക്കുക."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"മുഖ മോഡൽ സൃഷ്ടിക്കാനാകുന്നില്ല. വീണ്ടും ശ്രമിക്കൂ."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"വളരെയധികം തെളിച്ചം. സൗമ്യതയേറിയ പ്രകാശം ശ്രമിക്കൂ."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"കൂടുതൽ വെളിച്ചമുള്ളയിടത്ത് പരീക്ഷിച്ച് നോക്കൂ"</string> + <string name="face_acquired_too_dark" msgid="8539853432479385326">"വേണ്ടത്ര പ്രകാശമില്ല"</string> <string name="face_acquired_too_close" msgid="4453646176196302462">"ഫോൺ കൂടുതൽ ദൂരേയ്ക്ക് നീക്കുക"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"ഫോൺ അടുത്തേക്ക് നീക്കുക"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"ഫോൺ മുകളിലേക്ക് ഉയർത്തുക"</string> @@ -1251,8 +1256,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"അപ്ലിക്കേഷനുകൾ ആരംഭിക്കുന്നു."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"ബൂട്ട് ചെയ്യൽ പൂർത്തിയാകുന്നു."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"നിങ്ങൾ പവർ ബട്ടൺ അമർത്തി — സാധാരണയായി ഇത് സ്ക്രീൻ ഓഫാകുന്നതിന് കാരണമാകും.\n\nനിങ്ങളുടെ ഫിംഗർപ്രിന്റ് സജ്ജീകരിക്കുമ്പോൾ മൃദുവായി ടാപ്പ് ചെയ്ത് നോക്കുക."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"സ്ക്രീൻ ഓഫാക്കാൻ ടാപ്പ് ചെയ്യുക"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"സ്ക്രീൻ ഓഫാക്കുക"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"ഫിംഗർപ്രിന്റ് പരിശോധിച്ചുറപ്പിക്കൽ തുടരണോ?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"നിങ്ങൾ പവർ ബട്ടൺ അമർത്തി — സാധാരണയായി ഇത് സ്ക്രീൻ ഓഫാകുന്നതിന് കാരണമാകും.\n\nനിങ്ങളുടെ ഫിംഗർപ്രിന്റ് പരിശോധിച്ചുറപ്പിക്കാൻ മൃദുവായി ടാപ്പ് ചെയ്ത് നോക്കുക."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"സ്ക്രീൻ ഓഫാക്കുക"</string> diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml index 9777619701f0..1b88291d73d3 100644 --- a/core/res/res/values-mn/strings.xml +++ b/core/res/res/values-mn/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Дэлгэцийн түгжээг ашиглах"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Үргэлжлүүлэхийн тулд дэлгэцийн түгжээгээ оруулна уу"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Мэдрэгч дээр чанга дарна уу"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Хурууны хээ боловсруулж чадахгүй байна. Дахин оролдоно уу."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Хурууны хээ мэдрэгчийг цэвэрлээд, дахин оролдоно уу"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Мэдрэгчийг цэвэрлээд, дахин оролдоно уу"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Мэдрэгч дээр чанга дарна уу"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Хуруу хэт удаан хөдөлгөсөн байна. Дахин оролдоно уу."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Өөр хурууны хээ туршина уу"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Хэт гэрэлтэй байна"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Тохируулж үзнэ үү"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Хурууныхаа байрлалыг тухай бүрд бага зэрэг өөрчилнө үү"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Царайг баталгаажууллаа. Баталгаажуулах товчлуурыг дарна уу"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Хурууны хээний төхөөрөмж бэлэн бус байна."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Хурууны хээ тохируулах боломжгүй"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Хурууны хээ оруулах хугацаа өнгөрсөн байна. Дахин оруулна уу."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Хурууны хээний бүртгэл амжилтгүй боллоо."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Хэрэглэгч хурууны хээний баталгаажуулалтыг цуцалсан байна."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Хэтэрхий олон оролдлоо. Түр хүлээгээд дахин оролдоно уу."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Хэт олон удаа оролдлоо. Оронд нь дэлгэцийн түгжээ ашиглана уу."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Дахин оролдно уу."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Бүртгүүлсэн хурууны хээ алга."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Энэ төхөөрөмжид хурууны хээ мэдрэгч алга."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Мэдрэгчийг түр хугацаанд идэвхгүй болгосон."</string> @@ -638,7 +643,7 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Засварын үйлчилгээ үзүүлэгчид зочилно уу."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"Нүүрний загвар үүсгэж чадсангүй. Дахин оролдоно уу."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Хэт цайвар байна. Гэрэл багатай газар оролдоно уу."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Гэрэлтэй орчинд туршина уу"</string> + <string name="face_acquired_too_dark" msgid="8539853432479385326">"Гэрэл хангалтгүй байна"</string> <string name="face_acquired_too_close" msgid="4453646176196302462">"Утсаа холдуулна уу"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Утсаа ойртуулна уу"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Утсаа дээшлүүлнэ үү"</string> @@ -1251,8 +1256,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Апп-г эхлүүлж байна."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"Эхлэлийг дуусгаж байна."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Та асаах/унтраах товчийг дарсан байна — энэ нь ихэвчлэн дэлгэцийг унтраадаг.\n\nХурууны хээгээ тохируулж байх үедээ зөөлөн товшиж үзнэ үү."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Дэлгэцийг унтраахын тулд товшино уу"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Дэлгэцийг унтраах"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"Хурууны хээгээ үргэлжлүүлэн баталгаажуулах уу?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"Та асаах/унтраах товчийг дарсан байна — энэ нь ихэвчлэн дэлгэцийг унтраадаг.\n\nХурууны хээгээ баталгаажуулахын тулд зөөлөн товшиж үзнэ үү."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Дэлгэцийг унтраах"</string> diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml index a464f8440ee1..85452e7d30ea 100644 --- a/core/res/res/values-mr/strings.xml +++ b/core/res/res/values-mr/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"स्क्रीन लॉक वापरा"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"पुढे सुरू ठेवण्यासाठी तुमचे स्क्रीन लॉक एंटर करा"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"सेन्सरवर जोरात दाबा"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"फिंगरप्रिंटवर प्रक्रिया करणे शक्य झाले नाही. कृपया पुन्हा प्रयत्न करा."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"फिंगरप्रिंट सेन्सर स्वच्छ करा आणि पुन्हा प्रयत्न करा"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"सेन्सर स्वच्छ करा आणि पुन्हा प्रयत्न करा"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"सेन्सरवर जोरात दाबा"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"बोट खूप सावकाश हलविले. कृपया पुन्हा प्रयत्न करा."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"दुसरी फिंगरप्रिंट वापरून पहा"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"खूप प्रखर"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"अॅडजस्ट करण्याचा प्रयत्न करा"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"तुमच्या बोटाची स्थिती प्रत्येक वेळी थोडीशी बदला"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"चेहरा ऑथेंटिकेशन केलेला आहे, कृपया कंफर्म दाबा"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"फिंगरप्रिंट हार्डवेअर उपलब्ध नाही."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"फिंगरप्रिंट सेट करता आली नाही"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"फिंगरप्रिंट टाइमआउट झाले. पुन्हा प्रयत्न करा."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"फिंगरप्रिंट ऑपरेशन रद्द झाले."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"वापरकर्त्याने फिंगरप्रिंट ऑपरेशन रद्द केले."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"खूप प्रयत्न केले. नंतर पुन्हा प्रयत्न करा."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"खूप जास्त प्रयत्न. त्याऐवजी स्क्रीन लॉक वापरा."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"पुन्हा प्रयत्न करा."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"कोणत्याही फिंगरप्रिंटची नोंद झाली नाही"</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"या डिव्हाइसमध्ये फिंगरप्रिंट सेन्सर नाही."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"सेन्सर तात्पुरता बंद केला आहे."</string> @@ -638,7 +643,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"दुरुस्तीच्या सेवा पुरवठादाराला भेट द्या."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"फेस मॉडेल तयार करू शकत नाही. पुन्हा प्रयत्न करा."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"खूप प्रखर. आणखी सौम्य प्रकाश वापरून पहा."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"आणखी प्रखर प्रकाश वापरून पहा"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"फोन आणखी दूर हलवा"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"फोन आणखी जवळ हलवा"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"फोन आणखी वर हलवा"</string> @@ -1251,8 +1257,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"अॅप्स सुरू करत आहे."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"बूट समाप्त होत आहे."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"तुम्ही पॉवर बटण दाबले — हे सहसा स्क्रीन बंद करते.\n\nतुमचे फिंगरप्रिंट सेट करताना हलके टॅप करून पहा."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"स्क्रीन बंद करण्यासाठी टॅप करा"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"स्क्रीन बंद करा"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"फिंगरप्रिंट पडताळणी सुरू ठेवायची का?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"तुम्ही पॉवर बटण दाबले — हे सहसा स्क्रीन बंद करते.\n\nतुमच्या फिंगरप्रिंटची पडताळणी करण्यासाठी हलके टॅप करून पहा."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"स्क्रीन बंद करा"</string> diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml index c9d9cad11228..b810e601039e 100644 --- a/core/res/res/values-ms/strings.xml +++ b/core/res/res/values-ms/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Gunakan kunci skrin"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Masukkan kunci skrin untuk teruskan"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Tekan dengan kuat pada penderia"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Tidak dapat memproses cap jari. Sila cuba lagi."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Bersihkan penderia cap jari dan cuba lagi"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Bersihkan penderia dan cuba lagi"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Tekan dengan kuat pada penderia"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Jari digerakkan terlalu perlahan. Sila cuba lagi."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Cuba cap jari lain"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Terlalu terang"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Cuba selaraskan"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Tukar sedikit kedudukan jari anda setiap kali pergerakan dilakukan"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Wajah disahkan, sila tekan sahkan"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Perkakasan cap jari tidak tersedia."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Tidak dapat menyediakan cap jari"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Sudah tamat masa untuk cap jari. Cuba lagi"</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Pengendalian cap jari dibatalkan."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Pengendalian cap jari dibatalkan oleh pengguna."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Terlalu banyak percubaan. Cuba sebentar lagi."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Terlalu banyak percubaan. Gunakan kunci skrin."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Cuba lagi."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Tiada cap jari didaftarkan."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Peranti ini tiada penderia cap jari."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Penderia dilumpuhkan sementara."</string> @@ -638,7 +643,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Lawati penyedia pembaikan."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"Tidak dapat membuat model wajah anda. Cuba lagi."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Terlalu terang. Cuba pencahayaan yang lebih lembut."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Cuba pencahayaan yang lebih cerah"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"Jauhkan telefon"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Dekatkan telefon"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Tinggikan lagi telefon"</string> @@ -1251,8 +1257,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Memulakan apl."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"But akhir."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Anda menekan butang kuasa — tindakan ini biasanya mematikan skrin.\n\nCuba ketik dengan perlahan semasa menetapkan cap jari anda."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Ketik untuk mematikan skrin"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Matikan skrin"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"Terus mengesahkan cap jari anda?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"Anda menekan butang kuasa — tindakan ini biasanya mematikan skrin.\n\nCuba ketik dengan perlahan untuk mengesahkan cap jari anda."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Matikan skrin"</string> diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml index 160ede02c9a7..2dd476fd0ac4 100644 --- a/core/res/res/values-my/strings.xml +++ b/core/res/res/values-my/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"ဖန်သားပြင်လော့ခ်ချခြင်းကို သုံးခြင်း"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"ရှေ့ဆက်ရန် သင်၏ဖန်သားပြင် လော့ခ်ချခြင်းကို ထည့်ပါ"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"အာရုံခံကိရိယာပေါ်တွင် သေချာဖိပါ"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"လက်ဗွေယူ၍ မရပါ။ ထပ်စမ်းကြည့်ပါ။"</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"လက်ဗွေ အာရုံခံကိရိယာကို သန့်ရှင်းပြီး ထပ်စမ်းကြည့်ပါ"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"အာရုံခံကိရိယာကို သန့်ရှင်းပြီး ထပ်စမ်းကြည့်ပါ"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"အာရုံခံကိရိယာပေါ်တွင် သေချာဖိပါ"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"လက်ညှိုးအလွန်နှေးကွေးစွာ ရွေ့ခဲ့သည်။ ကျေးဇူးပြု၍ ထပ်မံကြိုးစားပါ။"</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"အခြားလက်ဗွေဖြင့် စမ်းကြည့်ပါ"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"အလွန် လင်းသည်"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"ပြင်ဆင်ကြည့်ပါ"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"အကြိမ်တိုင်း သင့်လက်ချောင်း၏ အနေအထားကို အနည်းငယ်ပြောင်းပါ"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"မျက်နှာ အထောက်အထားစိစစ်ပြီးပြီ၊ အတည်ပြုရန်ကို နှိပ်ပါ"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"လက်ဗွေ စက်ပစ္စည်းမရနိုင်ပါ။"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"လက်ဗွေကို စနစ်ထည့်သွင်း၍ မရပါ"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"လက်ဗွေယူချိန်ကုန် သွားပါသည်။ ထပ်စမ်းကြည့်ပါ။"</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"လက်ဗွေယူခြင်း ပယ်ဖျက်လိုက်သည်။"</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"လက်ဗွေဖြင့် အထောက်အထားစိစစ်ခြင်းကို အသုံးပြုသူက ပယ်ဖျက်ထားသည်။"</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"ကြိုးစာမှု အကြိမ်များနေ၏။ နောက်မှ ထပ်မံကြိုးစားပါ။"</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"ကြိုးပမ်းမှုအကြိမ်ရေ များလွန်းသည်။ ဖန်သားပြင်လော့ခ်ချခြင်းကို အစားထိုးသုံးပါ။"</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"ပြန်ကြိုးစားပါ"</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"မည်သည့် လက်ဗွေကိုမျှ ထည့်သွင်းမထားပါ။"</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"ဤစက်တွင် လက်ဗွေအာရုံခံကိရိယာ မရှိပါ။"</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"အာရုံခံကိရိယာကို ယာယီပိတ်ထားသည်။"</string> @@ -638,7 +643,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"ပြုပြင်ရေး ဝန်ဆောင်မှုပေးသူထံသို့ သွားပါ။"</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"သင့်မျက်နှာနမူနာ ပြုလုပ်၍မရပါ။ ထပ်စမ်းကြည့်ပါ။"</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"အလွန် လင်းသည်။ အလင်းလျှော့ကြည့်ပါ။"</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"ပိုလင်းအောင် လုပ်ကြည့်ပါ"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"ဖုန်းကို အဝေးသို့ခွာပါ"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"ဖုန်းကို အနားသို့ပိုတိုးပါ"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"ဖုန်းကို ပိုမြှင့်လိုက်ပါ"</string> @@ -1251,8 +1257,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"အက်ပ်များကို စတင်နေ"</string> <string name="android_upgrading_complete" msgid="409800058018374746">"လုပ်ငန်းစနစ်ထည့်သွင်း၍ ပြန်လည်စတင်ရန် ပြီးပါပြီ"</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"ဖွင့်ပိတ်ခလုတ်ကို သင်နှိပ်ခဲ့သည် — ၎င်းက ပုံမှန်အားဖြင့် စခရင်ကို ပိတ်စေသည်။\n\nသင့်လက်ဗွေကို ထည့်သွင်းသောအခါ ဖွဖွတို့ကြည့်ပါ။"</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"ဖန်သားပြင်ပိတ်ရန် တို့ပါ"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"ဖန်သားပြင် ပိတ်ရန်"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"သင့်လက်ဗွေကို ဆက်၍ အတည်ပြုမလား။"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"ဖွင့်ပိတ်ခလုတ်ကို သင်နှိပ်ခဲ့သည် — ၎င်းက ပုံမှန်အားဖြင့် စခရင်ကို ပိတ်စေသည်။\n\nသင့်လက်ဗွေကို အတည်ပြုရန် ဖွဖွတို့ကြည့်ပါ။"</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"စခရင် ပိတ်ရန်"</string> diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml index c0eb64cc450a..6579ee720a3a 100644 --- a/core/res/res/values-nb/strings.xml +++ b/core/res/res/values-nb/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Bruk skjermlås"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Skriv inn skjermlåsen for å fortsette"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Trykk godt på sensoren"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Kunne ikke registrere fingeravtrykket. Prøv på nytt."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Rengjør fingeravtrykkssensoren og prøv igjen"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Rengjør sensoren og prøv igjen"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Trykk godt på sensoren"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Du flyttet fingeren for sakte. Prøv på nytt."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Prøv et annet fingeravtrykk"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"For lyst"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Prøv å justere"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Endre posisjonen til fingeren litt hver gang"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Ansiktet er autentisert. Trykk på Bekreft"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Maskinvare for fingeravtrykk er ikke tilgjengelig."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Kan ikke konfigurere fingeravtrykk"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Tidsavbrudd for fingeravtrykk er nådd. Prøv på nytt."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Fingeravtrykk-operasjonen ble avbrutt."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Fingeravtrykk-operasjonen ble avbrutt av brukeren."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"For mange forsøk. Prøv på nytt senere."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"For mange forsøk. Bruk skjermlås i stedet."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Prøv på nytt."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Ingen fingeravtrykk er registrert."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Denne enheten har ikke fingeravtrykkssensor."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Sensoren er midlertidig slått av."</string> @@ -638,7 +643,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Gå til en reparasjonsleverandør."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"Kan ikke lage ansiktsmodell. Prøv på nytt."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"For lyst. Prøv svakere belysning."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Prøv sterkere belysning"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"Flytt telefonen lengre unna"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Flytt telefonen nærmere"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Flytt telefonen høyere"</string> @@ -1251,8 +1257,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Starter apper."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"Ferdigstiller oppstart."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Du har trykket på av/på-knappen – dette slår vanligvis av skjermen.\n\nPrøv å trykke lett mens du konfigurerer fingeravtrykket ditt."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Trykk for å slå av skjermen"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Slå av skjermen"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"Fortsett bekreftelse av fingeravtrykket?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"Du har trykket på av/på-knappen – dette slår vanligvis av skjermen.\n\nPrøv å trykke lett for å bekrefte fingeravtrykket ditt."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Slå av skjermen"</string> diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml index 1a40845d027c..1d396a08b9cb 100644 --- a/core/res/res/values-ne/strings.xml +++ b/core/res/res/values-ne/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"स्क्रिन लक प्रयोग गर्नुहोस्"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"जारी राख्न आफ्नो स्क्रिन लक हाल्नुहोस्"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"सेन्सरमा बेसरी थिच्नुहोस्"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"फिंगरप्रिन्ट प्रशोधन गर्न सकिएन। कृपया फेरि प्रयास गर्नुहोस्।"</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"फिंगरप्रिन्ट सेन्सर सफा गरेर फेरि प्रयास गर्नुहोस्"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"सेन्सर सफा गरेर फेरि प्रयास गर्नुहोस्"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"सेन्सरमा बेसरी थिच्नुहोस्"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"औंला निकै सुस्त सारियो। कृपया फेरि प्रयास गर्नुहोस्।"</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"अर्को फिंगरप्रिन्ट प्रयोग गरी हेर्नुहोस्"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"ज्यादै उज्यालो छ"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"सेन्सरमा सही तरिकाले औँला राखेर हेर्नुहोस्"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"हरेक पटक आफ्नो औँला थोरै यताउता सार्नुहोस्"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"अनुहार प्रमाणीकरण गरियो, कृपया पुष्टि गर्नुहोस् थिच्नुहोस्"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"औँठाछाप हार्डवेयर उपलब्ध छैन।"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"फिंगरप्रिन्ट सेटअप गर्न सकिएन"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"फिंगरप्रिन्ट समय सकिएको छ। फेरि प्रयास गर्नुहोस्।"</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"फिंगरप्रिन्ट सञ्चालन रद्द गरियो।"</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"प्रयोगकर्ताले फिंगरप्रिन्टसम्बन्धी कारबाही रद्द गर्नुभयो।"</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"धेरै प्रयासहरू। केहि समय पछि पुन: प्रयास गर्नुहोला"</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"निकै धेरै पटक प्रयास गरिसकिएको छ। बरु स्क्रिन लक प्रयोग गर्नुहोस्।"</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"पुन: प्रयास गर्नुहोला।"</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"कुनै पनि फिंगरप्रिन्ट दर्ता गरिएको छैन।"</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"यो डिभाइसमा कुनै पनि फिंगरप्रिन्ट सेन्सर छैन।"</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"केही समयका लागि सेन्सर असक्षम पारियो।"</string> @@ -638,7 +643,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"फिंगरप्रिन्ट सेन्सर मर्मत गर्ने सेवा प्रदायक कम्पनीमा सम्पर्क गर्नुहोस्।"</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"तपाईंको फेस मोडेल सिर्जना गर्न सकिएन। फेरि प्रयास गर्नुहोस्।"</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"ज्यादै चम्किलो। अझ मधुरो प्रकाश प्रयोग गरी हेर्नु…"</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"अझ उज्यालो ठाउँमा गएर फोटो खिची हेर्नुहोस्"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"फोन अझै पर सार्नुहोस्"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"फोन अझै नजिक सार्नुहोस्"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"फोन अझ माथि उठाउनुहोस्"</string> @@ -1251,8 +1257,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"सुरुवात एपहरू।"</string> <string name="android_upgrading_complete" msgid="409800058018374746">"बुट पुरा हुँदै।"</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"तपाईंले पावर बटन थिच्नुभयो — सामान्यतया स्क्रिन अफ गर्न यो बटन थिच्ने गरिन्छ।\n\nफिंगरप्रिन्ट सेटअप भइन्जेल हल्का तरिकाले यो बटन ट्याप गर्नुहोस्।"</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"स्क्रिन अफ गर्न ट्याप गर्नुहोस्"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"स्क्रिन अफ गर्नुहोस्"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"फिंगरप्रिन्ट पुष्टि गर्ने क्रम जारी राख्ने हो?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"तपाईंले पावर बटन थिच्नुभयो — सामान्यतया स्क्रिन अफ गर्न यो बटन थिच्ने गरिन्छ।\n\nतपाईं आफ्नो फिंगरप्रिन्ट पुष्टि गर्न चाहनुहुन्छ भने हल्का तरिकाले यो बटन ट्याप गरी हेर्नुहोस्।"</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"स्क्रिन अफ गर्नुहोस्"</string> diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml index ad2bd53e9652..e11a7299df15 100644 --- a/core/res/res/values-nl/strings.xml +++ b/core/res/res/values-nl/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Schermvergrendeling gebruiken"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Voer je schermvergrendeling in om door te gaan"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Druk stevig op de sensor"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Kan vingerafdruk niet verwerken. Probeer het opnieuw."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Reinig de vingerafdruksensor en probeer het opnieuw"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Reinig de sensor en probeer het opnieuw"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Druk stevig op de sensor"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Vinger te langzaam bewogen. Probeer het opnieuw."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Probeer een andere vingerafdruk"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Te veel licht"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Verplaats je vinger"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Verander de positie van je vinger steeds een beetje"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Gezicht geverifieerd. Druk op Bevestigen."</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Hardware voor vingerafdruk niet beschikbaar."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Kan vingerafdruk niet instellen"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Time-out bereikt voor vingerafdruk. Probeer het opnieuw."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Vingerafdrukbewerking geannuleerd."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Vingerafdrukverificatie geannuleerd door gebruiker."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Te veel pogingen. Probeer het later opnieuw."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Te veel pogingen. Gebruik in plaats daarvan de schermvergrendeling."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Probeer het opnieuw."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Geen vingerafdrukken geregistreerd."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Dit apparaat heeft geen vingerafdruksensor."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Sensor staat tijdelijk uit."</string> @@ -638,7 +643,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Ga naar een reparateur."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"Kan gezichtsmodel niet maken. Probeer het opnieuw."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Overbelicht. Probeer een minder felle belichting."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Probeer fellere verlichting"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"Houd de telefoon verder weg"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Houd de telefoon dichterbij"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Houd de telefoon hoger"</string> @@ -1251,8 +1257,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Apps starten."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"Opstarten afronden."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Je hebt op de aan/uit-knop gedrukt. Zo zet je meestal het scherm uit.\n\nRaak de knop voorzichtig aan terwijl je je vingerafdruk instelt."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Tik om het scherm uit te zetten"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Scherm uitzetten"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"Doorgaan met verificatie van je vingerafdruk?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"Je hebt op de aan/uit-knop gedrukt. Zo zet je meestal het scherm uit.\n\nRaak de knop voorzichtig aan om je vingerafdruk te verifiëren."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Scherm uitzetten"</string> diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml index f0b60b68f05b..02f691053359 100644 --- a/core/res/res/values-or/strings.xml +++ b/core/res/res/values-or/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"ସ୍କ୍ରିନ୍ ଲକ୍ ବ୍ୟବହାର କରନ୍ତୁ"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"ଜାରି ରଖିବାକୁ ଆପଣଙ୍କ ସ୍କ୍ରିନ୍ ଲକ୍ ଏଣ୍ଟର୍ କରନ୍ତୁ"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"ସେନ୍ସର ଉପରେ ଦୃଢ଼ ଭାବେ ଦବାନ୍ତୁ"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"ଟିପଚିହ୍ନ ପ୍ରୋସେସ୍ କରାଯାଇପାରିଲା ନାହିଁ। ଦୟାକରି ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"ଟିପଚିହ୍ନ ସେନ୍ସରକୁ ପରିଷ୍କାର କରି ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"ସେନ୍ସରକୁ ପରିଷ୍କାର କରି ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"ସେନ୍ସର ଉପରେ ଦୃଢ଼ ଭାବେ ଦବାନ୍ତୁ"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"ଆଙ୍ଗୁଠି ଖୁବ୍ ଧୀରେ ନିଆଗଲା। ଦୟାକରି ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"ଅନ୍ୟ ଏକ ଟିପଚିହ୍ନ ବ୍ୟବହାର କରି ଦେଖନ୍ତୁ"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"ବହୁତ ଉଜ୍ଜ୍ୱଳ"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"ଆଡଜଷ୍ଟ କରି ଦେଖନ୍ତୁ"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"ପ୍ରତି ଥର ଆପଣଙ୍କ ଆଙ୍ଗୁଠିର ସ୍ଥାନ ସାମାନ୍ୟ ପରିବର୍ତ୍ତନ କରନ୍ତୁ"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"ମୁହଁ ଚିହ୍ନଟ ହୋଇଛି, ଦୟାକରି ସୁନିଶ୍ଚିତ ଦବାନ୍ତୁ"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"ଟିପଚିହ୍ନ ହାର୍ଡୱେର୍ ଉପଲବ୍ଧ ନାହିଁ।"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"ଟିପଚିହ୍ନକୁ ସେଟ୍ ଅପ୍ କରାଯାଇପାରିବ ନାହିଁ"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"ଟିପଚିହ୍ନର ସମୟ ଶେଷ ହେଲା । ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"ଟିପଚିହ୍ନ କାର୍ଯ୍ୟ ବାତିଲ୍ କରାଗଲା।"</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"ଉପଯୋଗକର୍ତ୍ତା ଟିପଚିହ୍ନ କାର୍ଯ୍ୟ ବାତିଲ୍ କରିଛନ୍ତି।"</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"ବହୁତ ପ୍ରୟାସ କରାଗଲା। ପରେ ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"ଅନେକଗୁଡ଼ିଏ ପ୍ରଚେଷ୍ଟା। ଏହା ପରିବର୍ତ୍ତେ ସ୍କ୍ରିନ ଲକ ବ୍ୟବହାର କରନ୍ତୁ।"</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"ପୁଣି ଚେଷ୍ଟା କରନ୍ତୁ।"</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"କୌଣସି ଆଙ୍ଗୁଠି ଚିହ୍ନ ପଞ୍ଜୀକୃତ ହୋଇନାହିଁ।"</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"ଏହି ଡିଭାଇସ୍ରେ ଟିପଚିହ୍ନ ସେନ୍ସର୍ ନାହିଁ।"</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"ସେନ୍ସରକୁ ଅସ୍ଥାୟୀ ଭାବେ ଅକ୍ଷମ କରାଯାଇଛି।"</string> @@ -638,7 +643,7 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"ଏକ ମରାମତି କେନ୍ଦ୍ରକୁ ଭିଜିଟ୍ କରନ୍ତୁ।"</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"ଫେସର ମଡେଲ ତିଆରି କରାଯାଇପାରିବ ନାହିଁ। ପୁଣି ଚେଷ୍ଟା କର।"</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"ଅତ୍ୟଧିକ ଉଜ୍ଵଳ। କମ୍ ଉଜ୍ବଳକରଣରେ ଚେଷ୍ଟା କରନ୍ତୁ।"</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"ଉଜ୍ଜ୍ୱଳ ଲାଇଟ ବ୍ୟବହାର କରି ଦେଖନ୍ତୁ"</string> + <string name="face_acquired_too_dark" msgid="8539853432479385326">"ଯଥେଷ୍ଟ ଆଲୋକ ନାହିଁ"</string> <string name="face_acquired_too_close" msgid="4453646176196302462">"ଫୋନକୁ ଟିକେ ଦୂରକୁ ନିଅନ୍ତୁ"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"ଫୋନକୁ ପାଖକୁ ଆଣନ୍ତୁ"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"ଫୋନକୁ ଉପରକୁ ମୁଭ କରନ୍ତୁ"</string> @@ -1251,8 +1256,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"ଆପ୍ ଆରମ୍ଭ କରାଯାଉଛି।"</string> <string name="android_upgrading_complete" msgid="409800058018374746">"ବୁଟ୍ ସମାପ୍ତ କରୁଛି।"</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"ଆପଣ ପାୱାର ବଟନ ଦବାଇଛନ୍ତି — ଏହା ସାଧାରଣତଃ ଆପଣଙ୍କ ସ୍କ୍ରିନକୁ ବନ୍ଦ କରିଥାଏ।\n\nଆପଣଙ୍କ ଟିପଚିହ୍ନ ସେଟ ଅପ କରିବା ସମୟରେ ଧୀରେ ଟାପ କରିବାକୁ ଚେଷ୍ଟା କରନ୍ତୁ।"</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"ସ୍କ୍ରିନ ବନ୍ଦ କରିବା ପାଇଁ ଟାପ କରନ୍ତୁ"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"ସ୍କ୍ରିନ ବନ୍ଦ କରନ୍ତୁ"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"ଆପଣଙ୍କ ଟିପଚିହ୍ନ ଯାଞ୍ଚ କରିବା ଜାରି ରଖିବେ?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"ଆପଣ ପାୱାର ବଟନ ଦବାଇଛନ୍ତି — ଏହା ସାଧାରଣତଃ ଆପଣଙ୍କ ସ୍କ୍ରିନକୁ ବନ୍ଦ କରିଥାଏ।\n\nଆପଣଙ୍କ ଟିପଚିହ୍ନ ଯାଞ୍ଚ କରିବା ପାଇଁ ଧୀରେ ଟାପ କରିବାକୁ ଚେଷ୍ଟା କରନ୍ତୁ।"</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"ସ୍କ୍ରିନ ବନ୍ଦ କରନ୍ତୁ"</string> @@ -2044,7 +2051,7 @@ <string name="shortcut_restore_signature_mismatch" msgid="579345304221605479">"ଶର୍ଟକଟ୍ ରିଷ୍ଟୋର୍ କରିହେଲା ନାହିଁ, କାରଣ ଏହି ଆପ୍ର ସ୍ୱାକ୍ଷର ମେଳ ହେଉନାହିଁ"</string> <string name="shortcut_restore_unknown_issue" msgid="2478146134395982154">"ଶର୍ଟକଟ୍ ରିଷ୍ଟୋର୍ କରିହେଲା ନାହିଁ"</string> <string name="shortcut_disabled_reason_unknown" msgid="753074793553599166">"ଶର୍ଟକଟ୍ ଅକ୍ଷମ କରାଯାଇଛି"</string> - <string name="harmful_app_warning_uninstall" msgid="6472912975664191772">"ଅନଇନଷ୍ଟଲ୍ କରନ୍ତୁ"</string> + <string name="harmful_app_warning_uninstall" msgid="6472912975664191772">"ଅନଇନଷ୍ଟଲ କରନ୍ତୁ"</string> <string name="harmful_app_warning_open_anyway" msgid="5963657791740211807">"କୌଣସିମତେ ଖୋଲନ୍ତୁ"</string> <string name="harmful_app_warning_title" msgid="8794823880881113856">"ହାନିକାରକ ଆପ୍ ଚିହ୍ନଟ ହୋଇଛି"</string> <string name="log_access_confirmation_title" msgid="2343578467290592708">"ସମସ୍ତ ଡିଭାଇସ ଲଗକୁ ଆକ୍ସେସ କରିବା ପାଇଁ <xliff:g id="LOG_ACCESS_APP_NAME">%s</xliff:g>କୁ ଅନୁମତି ଦେବେ?"</string> diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml index 53a7807519b7..14227ad57052 100644 --- a/core/res/res/values-pa/strings.xml +++ b/core/res/res/values-pa/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"ਸਕ੍ਰੀਨ ਲਾਕ ਦੀ ਵਰਤੋਂ ਕਰੋ"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"ਜਾਰੀ ਰੱਖਣ ਲਈ ਆਪਣਾ ਸਕ੍ਰੀਨ ਲਾਕ ਦਾਖਲ ਕਰੋ"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"ਸੈਂਸਰ ਨੂੰ ਜ਼ੋਰ ਨਾਲ ਦਬਾਓ"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"ਫਿੰਗਰਪ੍ਰਿੰਟ \'ਤੇ ਪ੍ਰਕਿਰਿਆ ਨਹੀਂ ਹੋ ਸਕੀ। ਕਿਰਪਾ ਕਰਕੇ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਸੈਂਸਰ ਨੂੰ ਸਾਫ਼ ਕਰੋ ਅਤੇ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"ਸੈਂਸਰ ਨੂੰ ਸਾਫ਼ ਕਰੋ ਅਤੇ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"ਸੈਂਸਰ ਨੂੰ ਜ਼ੋਰ ਨਾਲ ਦਬਾਓ"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"ਉਂਗਲ ਕਾਫ਼ੀ ਹੌਲੀ ਮੂਵ ਹੋਈ। ਕਿਰਪਾ ਕਰਕੇ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"ਕੋਈ ਹੋਰ ਫਿੰਗਰਪ੍ਰਿੰਟ ਵਰਤ ਕੇ ਦੇਖੋ"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"ਬਹੁਤ ਜ਼ਿਆਦਾ ਚਮਕ"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"ਵਿਵਸਥਿਤ ਕਰਕੇ ਦੇਖੋ"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"ਹਰ ਵਾਰ ਆਪਣੀ ਉਂਗਲ ਨੂੰ ਥੋੜ੍ਹਾ ਹਿਲਾਓ"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"ਚਿਹਰਾ ਪੁਸ਼ਟੀਕਰਨ, ਕਿਰਪਾ ਕਰਕੇ \'ਪੁਸ਼ਟੀ ਕਰੋ\' ਦਬਾਓ"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਹਾਰਡਵੇਅਰ ਉਪਲਬਧ ਨਹੀਂ ਹੈ।"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਦਾ ਸੈੱਟਅੱਪ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਦਾ ਸਮਾਂ ਸਮਾਪਤ ਹੋ ਗਿਆ ਹੈ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਓਪਰੇਸ਼ਨ ਰੱਦ ਕੀਤਾ ਗਿਆ।"</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"ਫਿੰਗਰਪ੍ਰਿੰਟ ਓਪਰੇਸ਼ਨ ਵਰਤੋਂਕਾਰ ਵੱਲੋਂ ਰੱਦ ਕੀਤਾ ਗਿਆ।"</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"ਬਹੁਤ ਸਾਰੀਆਂ ਕੋਸ਼ਿਸ਼ਾਂ. ਬਾਅਦ ਵਿੱਚ ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"ਬਹੁਤ ਸਾਰੀਆਂ ਕੋਸ਼ਿਸ਼ਾਂ। ਇਸਦੀ ਬਜਾਏ ਸਕ੍ਰੀਨ ਲਾਕ ਵਰਤੋ।"</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"ਕੋਈ ਫਿੰਗਰਪ੍ਰਿੰਟ ਦਰਜ ਨਹੀਂ ਕੀਤੇ ਗਏ।"</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"ਇਸ ਡੀਵਾਈਸ ਵਿੱਚ ਫਿੰਗਰਪ੍ਰਿੰਟ ਸੈਂਸਰ ਨਹੀਂ ਹੈ।"</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"ਸੈਂਸਰ ਅਸਥਾਈ ਤੌਰ \'ਤੇ ਬੰਦ ਕੀਤਾ ਗਿਆ।"</string> @@ -638,7 +643,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"ਮੁਰੰਮਤ ਪ੍ਰਦਾਨਕ \'ਤੇ ਜਾਓ।"</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"ਤੁਹਾਡੇ ਚਿਹਰੇ ਦਾ ਮਾਡਲ ਨਹੀਂ ਬਣਿਆ। ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"ਬਹੁਤ ਜ਼ਿਆਦਾ ਚਮਕ। ਹਲਕੀ ਚਮਕ ਵਰਤ ਕੇ ਦੇਖੋ।"</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"ਤੇਜ਼ ਰੋਸ਼ਨੀ ਕਰ ਕੇ ਦੇਖੋ"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"ਫ਼ੋਨ ਨੂੰ ਦੂਰ ਲਿਜਾਓ"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"ਫ਼ੋਨ ਨੇੜੇ ਲਿਜਾਓ"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"ਫ਼ੋਨ ਨੂੰ ਥੋੜ੍ਹਾ ਉੱਤੇ ਲਿਜਾਓ"</string> @@ -1251,8 +1257,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"ਐਪਸ ਚਾਲੂ ਕਰ ਰਿਹਾ ਹੈ।"</string> <string name="android_upgrading_complete" msgid="409800058018374746">"ਬੂਟ ਪੂਰਾ ਕਰ ਰਿਹਾ ਹੈ।"</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"ਤੁਸੀਂ ਪਾਵਰ ਬਟਨ ਨੂੰ ਦਬਾਇਆ ਹੈ — ਇਹ ਆਮ ਤੌਰ \'ਤੇ ਸਕ੍ਰੀਨ ਨੂੰ ਬੰਦ ਕਰ ਦਿੰਦਾ ਹੈ।\n\nਆਪਣੇ ਫਿੰਗਰਪ੍ਰਿੰਟ ਦਾ ਸੈੱਟਅੱਪ ਕਰਦੇ ਸਮੇਂ ਹਲਕਾ ਜਿਹਾ ਟੈਪ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"ਸਕ੍ਰੀਨ ਬੰਦ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"ਸਕ੍ਰੀਨ ਬੰਦ ਕਰੋ"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"ਕੀ ਆਪਣੇ ਫਿੰਗਰਪ੍ਰਿੰਟ ਦੀ ਪੁਸ਼ਟੀ ਕਰਨਾ ਜਾਰੀ ਰੱਖਣਾ ਹੈ?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"ਤੁਸੀਂ ਪਾਵਰ ਬਟਨ ਨੂੰ ਦਬਾਇਆ ਹੈ — ਇਹ ਆਮ ਤੌਰ \'ਤੇ ਸਕ੍ਰੀਨ ਨੂੰ ਬੰਦ ਕਰ ਦਿੰਦਾ ਹੈ।\n\nਆਪਣੇ ਫਿੰਗਰਪ੍ਰਿੰਟ ਦੀ ਪੁਸ਼ਟੀ ਕਰਨ ਲਈ ਹਲਕਾ ਜਿਹਾ ਟੈਪ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰੋ।"</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"ਸਕ੍ਰੀਨ ਬੰਦ ਕਰੋ"</string> diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml index 386627312f59..0f7ffc582016 100644 --- a/core/res/res/values-pl/strings.xml +++ b/core/res/res/values-pl/strings.xml @@ -588,13 +588,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Używaj blokady ekranu"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Użyj blokady ekranu, aby kontynuować"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Mocno naciśnij czujnik"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Nie udało się przetworzyć odcisku palca. Spróbuj ponownie."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Wyczyść czytnik linii papilarnych i spróbuj ponownie"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Wyczyść czujnik i spróbuj ponownie"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Mocno naciśnij czujnik"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Palec został obrócony zbyt wolno. Spróbuj ponownie."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Użyj odcisku innego palca"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Zbyt jasno"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Popraw"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Za każdym razem lekko zmieniaj ułożenie palca"</string> <string-array name="fingerprint_acquired_vendor"> @@ -606,13 +609,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Twarz rozpoznana, kliknij Potwierdź"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Czytnik linii papilarnych nie jest dostępny."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Nie można skonfigurować odcisku palca"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Osiągnięto limit czasu odczytu odcisków palców. Spróbuj ponownie."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Odczyt odcisku palca został anulowany."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Odczyt odcisku palca został anulowany przez użytkownika."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Zbyt wiele prób. Spróbuj ponownie później."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Zbyt wiele prób. Użyj blokady ekranu."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Spróbuj ponownie."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Nie zarejestrowano odcisków palców."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"To urządzenie nie jest wyposażone w czytnik linii papilarnych."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Czujnik jest tymczasowo wyłączony."</string> @@ -640,7 +645,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Odwiedź serwis."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"Nie można utworzyć modelu twarzy. Spróbuj ponownie."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Zbyt jasno. Spróbuj przy słabszym świetle."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Spróbuj w jaśniejszym świetle"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"Odsuń telefon"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Przybliż telefon"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Przesuń telefon wyżej"</string> @@ -1253,8 +1259,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Uruchamianie aplikacji."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"Kończenie uruchamiania."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Naciśnięto przycisk zasilania — zwykle powoduje to wyłączenie ekranu.\n\nKlikaj delikatnie podczas konfigurowania odcisku palca."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Kliknij, aby wyłączyć ekran"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Wyłącz ekran"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"Kontynuować weryfikację odcisku palca?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"Naciśnięto przycisk zasilania — zwykle powoduje to wyłączenie ekranu.\n\nKliknij delikatnie, aby zweryfikować odcisk palca."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Wyłącz ekran"</string> diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml index cf577551a695..3abf2b353177 100644 --- a/core/res/res/values-pt-rBR/strings.xml +++ b/core/res/res/values-pt-rBR/strings.xml @@ -52,6 +52,7 @@ <string name="enablePin" msgid="2543771964137091212">"Falha. Ative o bloqueio do chip/R-UIM."</string> <plurals name="pinpuk_attempts" formatted="false" msgid="1619867269012213584"> <item quantity="one">Tentativas restantes: <xliff:g id="NUMBER_1">%d</xliff:g>. Caso o código correto não seja digitado, o chip será bloqueado.</item> + <item quantity="many">You have <xliff:g id="NUMBER_1">%d</xliff:g> remaining attempts before SIM is locked.</item> <item quantity="other">Tentativas restantes: <xliff:g id="NUMBER_1">%d</xliff:g>. Caso o código correto não seja digitado, o chip será bloqueado.</item> </plurals> <string name="imei" msgid="2157082351232630390">"IMEI"</string> @@ -180,7 +181,7 @@ <string name="low_memory" product="watch" msgid="3479447988234030194">"Armazenamento do relógio cheio. Exclua alguns arquivos para liberar espaço."</string> <string name="low_memory" product="tv" msgid="6663680413790323318">"O armazenamento do dispositivo Android TV está cheio. Exclua alguns arquivos para liberar espaço."</string> <string name="low_memory" product="default" msgid="2539532364144025569">"O armazenamento do telefone está cheio. Exclua alguns arquivos para liberar espaço."</string> - <string name="ssl_ca_cert_warning" msgid="7233573909730048571">"{count,plural, =1{Autoridade certificadora instalada}one{Autoridade certificadora instalada}other{Autoridades certificadoras instaladas}}"</string> + <string name="ssl_ca_cert_warning" msgid="7233573909730048571">"{count,plural, =1{Autoridade certificadora instalada}one{Autoridade certificadora instalada}many{Autoridades certificadoras instaladas}other{Autoridades certificadoras instaladas}}"</string> <string name="ssl_ca_cert_noti_by_unknown" msgid="4961102218216815242">"Por terceiros desconhecidos"</string> <string name="ssl_ca_cert_noti_by_administrator" msgid="4564941950768783879">"Pelo administrador do seu perfil de trabalho"</string> <string name="ssl_ca_cert_noti_managed" msgid="217337232273211674">"Por <xliff:g id="MANAGING_DOMAIN">%s</xliff:g>"</string> @@ -254,7 +255,7 @@ <string name="bugreport_option_interactive_summary" msgid="8493795476325339542">"Use este recurso na maioria das circunstâncias. Ele permite que você acompanhe o progresso do relatório, informe mais detalhes sobre o problema e faça capturas de tela. É possível que ele omita algumas seções menos utilizadas que levam muito tempo na emissão dos relatórios."</string> <string name="bugreport_option_full_title" msgid="7681035745950045690">"Relatório completo"</string> <string name="bugreport_option_full_summary" msgid="1975130009258435885">"Use esta opção para ter o mínimo de interferência do sistema quando seu dispositivo não estiver respondendo ou estiver muito lento, ou quando você precisar de todas as seções de relatórios. Ela não permite que você informe mais detalhes ou faça capturas de tela adicionais."</string> - <string name="bugreport_countdown" msgid="6418620521782120755">"{count,plural, =1{Capturas de tela para o relatório do bug vão ser feitas em # segundo.}one{Capturas de tela para o relatório do bug vão ser feitas em # segundo.}other{Capturas de tela para o relatório do bug vão ser feitas em # segundos.}}"</string> + <string name="bugreport_countdown" msgid="6418620521782120755">"{count,plural, =1{Capturas de tela para o relatório do bug vão ser feitas em # segundo.}one{Capturas de tela para o relatório do bug vão ser feitas em # segundo.}many{Capturas de tela para o relatório do bug vão ser feitas em # segundos.}other{Capturas de tela para o relatório do bug vão ser feitas em # segundos.}}"</string> <string name="bugreport_screenshot_success_toast" msgid="7986095104151473745">"Captura de tela com o relatório do bug concluída"</string> <string name="bugreport_screenshot_failure_toast" msgid="6736320861311294294">"Falha ao capturar a tela com o relatório do bug"</string> <string name="global_action_toggle_silent_mode" msgid="8464352592860372188">"Modo silencioso"</string> @@ -586,13 +587,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Usar bloqueio de tela"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Insira seu bloqueio de tela para continuar"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Pressione o sensor com firmeza"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Não foi possível processar a impressão digital. Tente novamente."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Limpe o sensor de impressão digital e tente novamente"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Limpe o sensor e tente novamente"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Pressione o sensor com firmeza"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"O movimento do dedo está muito lento. Tente novamente."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Use outra impressão digital"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Claro demais"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Ajuste a posição do dedo"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Mude a posição do dedo ligeiramente a cada momento"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +608,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Rosto autenticado, pressione \"Confirmar\""</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Hardware de impressão digital não disponível."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Não foi possível configurar a impressão digital"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Tempo máximo para captura da impressão digital atingido. Tente novamente."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Operação de impressão digital cancelada."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Operação de impressão digital cancelada pelo usuário."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Excesso de tentativas. Tente novamente mais tarde."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Excesso de tentativas. Use o bloqueio de tela."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Tente novamente."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Nenhuma impressão digital registrada."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Este dispositivo não tem um sensor de impressão digital."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Sensor desativado temporariamente."</string> @@ -638,7 +644,7 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Entre em contato com uma assistência técnica."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"Falha ao criar o modelo de rosto. Tente de novo."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Muito iluminado. Diminua a iluminação."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Use uma iluminação mais intensa"</string> + <string name="face_acquired_too_dark" msgid="8539853432479385326">"Não há luz suficiente"</string> <string name="face_acquired_too_close" msgid="4453646176196302462">"Afaste o smartphone"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Aproxime o smartphone do seu rosto"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Mova o smartphone para cima"</string> @@ -1088,7 +1094,7 @@ <string name="enable_explore_by_touch_warning_message" product="default" msgid="4312979647356179250">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> quer ativar o Explorar por toque. Com ele, você pode ouvir ou ver descrições do que está sob seu dedo e interagir com o telefone por gestos."</string> <string name="oneMonthDurationPast" msgid="4538030857114635777">"1 mês atrás"</string> <string name="beforeOneMonthDurationPast" msgid="8315149541372065392">"Antes de 1 mês atrás"</string> - <string name="last_num_days" msgid="2393660431490280537">"{count,plural, =1{No último # dia}one{No último # dia}other{Nos últimos # dias}}"</string> + <string name="last_num_days" msgid="2393660431490280537">"{count,plural, =1{No último # dia}one{No último # dia}many{Nos últimos # dias}other{Nos últimos # dias}}"</string> <string name="last_month" msgid="1528906781083518683">"Mês passado"</string> <string name="older" msgid="1645159827884647400">"Mais antigos"</string> <string name="preposition_for_date" msgid="2780767868832729599">"em <xliff:g id="DATE">%s</xliff:g>"</string> @@ -1115,14 +1121,14 @@ <string name="duration_hours_shortest_future" msgid="2979276794547981674">"em <xliff:g id="COUNT">%d</xliff:g>h"</string> <string name="duration_days_shortest_future" msgid="3392722163935571543">"em <xliff:g id="COUNT">%d</xliff:g> dias"</string> <string name="duration_years_shortest_future" msgid="5537464088352970388">"em <xliff:g id="COUNT">%d</xliff:g>a"</string> - <string name="duration_minutes_relative" msgid="8620337701051015593">"{count,plural, =1{# minuto atrás}one{# minuto atrás}other{# minutos atrás}}"</string> - <string name="duration_hours_relative" msgid="4836449961693180253">"{count,plural, =1{# hora atrás}one{# hora atrás}other{# horas atrás}}"</string> - <string name="duration_days_relative" msgid="621965767567258302">"{count,plural, =1{# dia atrás}one{# dia atrás}other{# dias atrás}}"</string> - <string name="duration_years_relative" msgid="8731202348869424370">"{count,plural, =1{# ano atrás}one{# ano atrás}other{# anos atrás}}"</string> - <string name="duration_minutes_relative_future" msgid="5259574171747708115">"{count,plural, =1{# minuto}one{# minuto}other{# minutos}}"</string> - <string name="duration_hours_relative_future" msgid="6670440478481140565">"{count,plural, =1{# hora}one{# hora}other{# horas}}"</string> - <string name="duration_days_relative_future" msgid="8870658635774250746">"{count,plural, =1{# dia}one{# dia}other{# dias}}"</string> - <string name="duration_years_relative_future" msgid="8855853883925918380">"{count,plural, =1{# ano}one{# ano}other{# anos}}"</string> + <string name="duration_minutes_relative" msgid="8620337701051015593">"{count,plural, =1{# minuto atrás}one{# minuto atrás}many{# minutos atrás}other{# minutos atrás}}"</string> + <string name="duration_hours_relative" msgid="4836449961693180253">"{count,plural, =1{# hora atrás}one{# hora atrás}many{# horas atrás}other{# horas atrás}}"</string> + <string name="duration_days_relative" msgid="621965767567258302">"{count,plural, =1{# dia atrás}one{# dia atrás}many{# dias atrás}other{# dias atrás}}"</string> + <string name="duration_years_relative" msgid="8731202348869424370">"{count,plural, =1{# ano atrás}one{# ano atrás}many{# anos atrás}other{# anos atrás}}"</string> + <string name="duration_minutes_relative_future" msgid="5259574171747708115">"{count,plural, =1{# minuto}one{# minuto}many{# minutos}other{# minutos}}"</string> + <string name="duration_hours_relative_future" msgid="6670440478481140565">"{count,plural, =1{# hora}one{# hora}many{# horas}other{# horas}}"</string> + <string name="duration_days_relative_future" msgid="8870658635774250746">"{count,plural, =1{# dia}one{# dia}many{# dias}other{# dias}}"</string> + <string name="duration_years_relative_future" msgid="8855853883925918380">"{count,plural, =1{# ano}one{# ano}many{# anos}other{# anos}}"</string> <string name="VideoView_error_title" msgid="5750686717225068016">"Problema com o vídeo"</string> <string name="VideoView_error_text_invalid_progressive_playback" msgid="3782449246085134720">"Este vídeo não é válido para transmissão neste dispositivo."</string> <string name="VideoView_error_text_unknown" msgid="7658683339707607138">"Não é possível reproduzir este vídeo."</string> @@ -1251,8 +1257,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Iniciando apps."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"Concluindo a inicialização."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Você pressionou o botão liga/desliga. Normalmente, essa ação desliga a tela.\n\nToque levemente na tela durante a configuração da impressão digital."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Toque para desligar a tela"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Desligar a tela"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"Continuar a verificação da digital?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"Você pressionou o botão liga/desliga. Normalmente, essa ação desliga a tela.\n\nToque levemente na tela para verificar sua impressão digital."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Desligar a tela"</string> @@ -1509,7 +1517,7 @@ <string name="skip_button_label" msgid="3566599811326688389">"Pular"</string> <string name="no_matches" msgid="6472699895759164599">"Não encontrado"</string> <string name="find_on_page" msgid="5400537367077438198">"Localizar na página"</string> - <string name="matches_found" msgid="2296462299979507689">"{count,plural, =1{# correspondência}one{# de {total}}other{# de {total}}}"</string> + <string name="matches_found" msgid="2296462299979507689">"{count,plural, =1{# correspondência}one{# de {total}}many{# de {total}}other{# de {total}}}"</string> <string name="action_mode_done" msgid="2536182504764803222">"Concluído"</string> <string name="progress_erasing" msgid="6891435992721028004">"Limpando armazenamento compartilhado…"</string> <string name="share" msgid="4157615043345227321">"Compartilhar"</string> @@ -1862,14 +1870,14 @@ <string name="data_saver_description" msgid="4995164271550590517">"Para ajudar a reduzir o uso de dados, a Economia de dados impede que alguns apps enviem ou recebam dados em segundo plano. Um app que você está usando no momento pode acessar dados, mas com menos frequência. Isso pode fazer com que imagens não apareçam até você tocar nelas."</string> <string name="data_saver_enable_title" msgid="7080620065745260137">"Ativar a Economia de dados?"</string> <string name="data_saver_enable_button" msgid="4399405762586419726">"Ativar"</string> - <string name="zen_mode_duration_minutes_summary" msgid="4555514757230849789">"{count,plural, =1{Por um minuto (até {formattedTime})}one{Por # minuto (até {formattedTime})}other{Por # minutos (até {formattedTime})}}"</string> - <string name="zen_mode_duration_minutes_summary_short" msgid="1187553788355486950">"{count,plural, =1{Por 1min (até {formattedTime})}one{Por #min (até {formattedTime})}other{Por #min (até {formattedTime})}}"</string> - <string name="zen_mode_duration_hours_summary" msgid="3866333100793277211">"{count,plural, =1{Por 1 hora (até {formattedTime})}one{Por # hora (até {formattedTime})}other{Por # horas (até {formattedTime})}}"</string> - <string name="zen_mode_duration_hours_summary_short" msgid="687919813833347945">"{count,plural, =1{Por 1h (até {formattedTime})}one{Por #h (até {formattedTime})}other{Por #h (até {formattedTime})}}"</string> - <string name="zen_mode_duration_minutes" msgid="2340007982276569054">"{count,plural, =1{Por um minuto}one{Por # minuto}other{Por # minutos}}"</string> - <string name="zen_mode_duration_minutes_short" msgid="2435756450204526554">"{count,plural, =1{Por 1min}one{Por #min}other{Por #min}}"</string> - <string name="zen_mode_duration_hours" msgid="7841806065034711849">"{count,plural, =1{Por 1 hora}one{Por # hora}other{Por # horas}}"</string> - <string name="zen_mode_duration_hours_short" msgid="3666949653933099065">"{count,plural, =1{Por 1h}one{Por #h}other{Por #h}}"</string> + <string name="zen_mode_duration_minutes_summary" msgid="4555514757230849789">"{count,plural, =1{Por um minuto (até {formattedTime})}one{Por # minuto (até {formattedTime})}many{Por # minutos (até {formattedTime})}other{Por # minutos (até {formattedTime})}}"</string> + <string name="zen_mode_duration_minutes_summary_short" msgid="1187553788355486950">"{count,plural, =1{Por 1min (até {formattedTime})}one{Por #min (até {formattedTime})}many{Por #min (até {formattedTime})}other{Por #min (até {formattedTime})}}"</string> + <string name="zen_mode_duration_hours_summary" msgid="3866333100793277211">"{count,plural, =1{Por 1 hora (até {formattedTime})}one{Por # hora (até {formattedTime})}many{Por # horas (até {formattedTime})}other{Por # horas (até {formattedTime})}}"</string> + <string name="zen_mode_duration_hours_summary_short" msgid="687919813833347945">"{count,plural, =1{Por 1h (até {formattedTime})}one{Por #h (até {formattedTime})}many{Por #h (até {formattedTime})}other{Por #h (até {formattedTime})}}"</string> + <string name="zen_mode_duration_minutes" msgid="2340007982276569054">"{count,plural, =1{Por um minuto}one{Por # minuto}many{Por # minutos}other{Por # minutos}}"</string> + <string name="zen_mode_duration_minutes_short" msgid="2435756450204526554">"{count,plural, =1{Por 1min}one{Por #min}many{Por #min}other{Por #min}}"</string> + <string name="zen_mode_duration_hours" msgid="7841806065034711849">"{count,plural, =1{Por 1 hora}one{Por # hora}many{Por # horas}other{Por # horas}}"</string> + <string name="zen_mode_duration_hours_short" msgid="3666949653933099065">"{count,plural, =1{Por 1h}one{Por #h}many{Por #h}other{Por #h}}"</string> <string name="zen_mode_until_next_day" msgid="1403042784161725038">"Até <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> <string name="zen_mode_until" msgid="2250286190237669079">"Até às <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> <string name="zen_mode_alarm" msgid="7046911727540499275">"Até <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (próximo alarme)"</string> @@ -2000,7 +2008,7 @@ <string name="autofill_save_accessibility_title" msgid="1523225776218450005">"Salvar no Preenchimento automático"</string> <string name="autofill_error_cannot_autofill" msgid="6528827648643138596">"Não é possível preencher os conteúdos automaticamente"</string> <string name="autofill_picker_no_suggestions" msgid="1076022650427481509">"Sem sugestões de preenchimento automático"</string> - <string name="autofill_picker_some_suggestions" msgid="5560549696296202701">"{count,plural, =1{Uma sugestão de preenchimento automático}one{# sugestão de preenchimento automático}other{# sugestões de preenchimento automático}}"</string> + <string name="autofill_picker_some_suggestions" msgid="5560549696296202701">"{count,plural, =1{Uma sugestão de preenchimento automático}one{# sugestão de preenchimento automático}many{# sugestões de preenchimento automático}other{# sugestões de preenchimento automático}}"</string> <string name="autofill_save_title" msgid="7719802414283739775">"Salvar em "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string> <string name="autofill_save_title_with_type" msgid="3002460014579799605">"Salvar <xliff:g id="TYPE">%1$s</xliff:g> em "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string> <string name="autofill_save_title_with_2types" msgid="3783270967447869241">"Salvar <xliff:g id="TYPE_0">%1$s</xliff:g> e <xliff:g id="TYPE_1">%2$s</xliff:g> em "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string> @@ -2110,7 +2118,7 @@ <string name="mime_type_presentation_ext" msgid="8761049335564371468">"Apresentação em <xliff:g id="EXTENSION">%1$s</xliff:g>"</string> <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"O Bluetooth permanecerá ativado no modo avião"</string> <string name="car_loading_profile" msgid="8219978381196748070">"Carregando"</string> - <string name="file_count" msgid="3220018595056126969">"{count,plural, =1{{file_name} + # arquivo}one{{file_name} + # arquivo}other{{file_name} + # arquivos}}"</string> + <string name="file_count" msgid="3220018595056126969">"{count,plural, =1{{file_name} + # arquivo}one{{file_name} + # arquivo}many{{file_name} + # arquivos}other{{file_name} + # arquivos}}"</string> <string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"Não há sugestões de pessoas para compartilhar"</string> <string name="chooser_all_apps_button_label" msgid="3230427756238666328">"Lista de apps"</string> <string name="usb_device_resolve_prompt_warn" msgid="325871329788064199">"Este app não tem permissão de gravação, mas pode capturar áudio pelo dispositivo USB."</string> diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml index 00d9aa2605b4..95fe874b1ba5 100644 --- a/core/res/res/values-pt-rPT/strings.xml +++ b/core/res/res/values-pt-rPT/strings.xml @@ -51,6 +51,7 @@ <string name="needPuk2" msgid="7032612093451537186">"Introduza o PUK2 para desbloquear o cartão SIM."</string> <string name="enablePin" msgid="2543771964137091212">"Ação sem êxito. Ative o bloqueio do SIM/RUIM."</string> <plurals name="pinpuk_attempts" formatted="false" msgid="1619867269012213584"> + <item quantity="many">You have <xliff:g id="NUMBER_1">%d</xliff:g> remaining attempts before SIM is locked.</item> <item quantity="other">Tem mais <xliff:g id="NUMBER_1">%d</xliff:g> tentativas antes de o cartão SIM ficar bloqueado.</item> <item quantity="one">Tem mais <xliff:g id="NUMBER_0">%d</xliff:g> tentativa antes de o cartão SIM ficar bloqueado.</item> </plurals> @@ -180,7 +181,7 @@ <string name="low_memory" product="watch" msgid="3479447988234030194">"O armazenamento de visualizações está cheio. Elimine alguns ficheiros para libertar espaço."</string> <string name="low_memory" product="tv" msgid="6663680413790323318">"O armazenamento do dispositivo Android TV está cheio. Elimine alguns ficheiros para libertar espaço."</string> <string name="low_memory" product="default" msgid="2539532364144025569">"O armazenamento do telemóvel está cheio. Elimine alguns ficheiros para libertar espaço."</string> - <string name="ssl_ca_cert_warning" msgid="7233573909730048571">"{count,plural, =1{Autoridade de certificação instalada}other{Autoridades de certificação instaladas}}"</string> + <string name="ssl_ca_cert_warning" msgid="7233573909730048571">"{count,plural, =1{Autoridade de certificação instalada}many{Autoridades de certificação instaladas}other{Autoridades de certificação instaladas}}"</string> <string name="ssl_ca_cert_noti_by_unknown" msgid="4961102218216815242">"Por um terceiro desconhecido"</string> <string name="ssl_ca_cert_noti_by_administrator" msgid="4564941950768783879">"Pelo gestor do seu perfil de trabalho"</string> <string name="ssl_ca_cert_noti_managed" msgid="217337232273211674">"Por <xliff:g id="MANAGING_DOMAIN">%s</xliff:g>"</string> @@ -254,7 +255,7 @@ <string name="bugreport_option_interactive_summary" msgid="8493795476325339542">"Utilize esta opção na maioria das circunstâncias. Permite monitorizar o progresso do relatório, introduzir mais detalhes acerca do problema e tirar capturas de ecrã. Pode omitir algumas secções menos utilizadas que demoram muito tempo a comunicar."</string> <string name="bugreport_option_full_title" msgid="7681035745950045690">"Relatório completo"</string> <string name="bugreport_option_full_summary" msgid="1975130009258435885">"Utilize esta opção para uma interferência mínima do sistema quando o dispositivo não responder ou estiver demasiado lento, ou quando precisar de todas as secções de relatório. Não permite introduzir mais detalhes ou tirar capturas de ecrã adicionais."</string> - <string name="bugreport_countdown" msgid="6418620521782120755">"{count,plural, =1{A fazer uma captura de ecrã do relatório de erro dentro de # segundo.}other{A fazer uma captura de ecrã do relatório de erro dentro de # segundos.}}"</string> + <string name="bugreport_countdown" msgid="6418620521782120755">"{count,plural, =1{A fazer uma captura de ecrã do relatório de erro dentro de # segundo.}many{A fazer uma captura de ecrã do relatório de erro dentro de # segundos.}other{A fazer uma captura de ecrã do relatório de erro dentro de # segundos.}}"</string> <string name="bugreport_screenshot_success_toast" msgid="7986095104151473745">"Captura de ecrã tirada com o relatório de erro."</string> <string name="bugreport_screenshot_failure_toast" msgid="6736320861311294294">"Falha ao fazer captura de ecrã com o relatório de erro."</string> <string name="global_action_toggle_silent_mode" msgid="8464352592860372188">"Modo silencioso"</string> @@ -586,13 +587,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Utilizar o bloqueio de ecrã"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Introduza o bloqueio de ecrã para continuar"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Prima firmemente o sensor"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Não foi possível processar a impressão digital. Tente novamente."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Limpe o sensor de impressões digitais e tente novamente"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Limpe o sensor e tente novamente"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Prima firmemente o sensor"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Moveu o dedo demasiado lentamente. Tente novamente."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Experimente outra impressão digital"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Está demasiado claro"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Experimente ajustar"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Altere a posição do seu dedo ligeiramente de cada vez"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +608,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Rosto autenticado. Prima Confirmar."</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Hardware de impressão digital não disponível."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Não é possível configurar a impressão digital"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Foi atingido o limite de tempo da impressão digital. Tente novamente."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Operação de impressão digital cancelada."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Operação de impressão digital cancelada pelo utilizador."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Demasiadas tentativas. Tente novamente mais tarde."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Demasiadas tentativas. Em alternativa, use o bloqueio de ecrã."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Tente novamente."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Nenhuma impressão digital registada."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Este dispositivo não tem sensor de impressões digitais."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Sensor temporariamente desativado."</string> @@ -638,7 +644,7 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Visite um fornecedor de serviços de reparação."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"Impossível criar modelo de rosto. Tente novamente."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Demasiado clara. Experimente uma luz mais suave."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Experimente um local com mais luz"</string> + <string name="face_acquired_too_dark" msgid="8539853432479385326">"Não há luz suficiente"</string> <string name="face_acquired_too_close" msgid="4453646176196302462">"Afaste ainda mais o telemóvel"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Aproxime o telemóvel do rosto"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Mova o telemóvel mais para cima"</string> @@ -1088,7 +1094,7 @@ <string name="enable_explore_by_touch_warning_message" product="default" msgid="4312979647356179250">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> pretende ativar a funcionalidade Explorar Através do Toque. Quando a funcionalidade Explorar Através do Toque estiver ativada, pode ouvir ou visualizar descrições sobre o que está por baixo do seu dedo ou executar gestos para interagir com o telemóvel."</string> <string name="oneMonthDurationPast" msgid="4538030857114635777">"Há 1 mês"</string> <string name="beforeOneMonthDurationPast" msgid="8315149541372065392">"Há mais de 1 mês"</string> - <string name="last_num_days" msgid="2393660431490280537">"{count,plural, =1{# dia anterior}other{# dias anteriores}}"</string> + <string name="last_num_days" msgid="2393660431490280537">"{count,plural, =1{# dia anterior}many{# dias anteriores}other{# dias anteriores}}"</string> <string name="last_month" msgid="1528906781083518683">"Último mês"</string> <string name="older" msgid="1645159827884647400">"Mais antiga"</string> <string name="preposition_for_date" msgid="2780767868832729599">"a <xliff:g id="DATE">%s</xliff:g>"</string> @@ -1115,14 +1121,14 @@ <string name="duration_hours_shortest_future" msgid="2979276794547981674">"em <xliff:g id="COUNT">%d</xliff:g> h"</string> <string name="duration_days_shortest_future" msgid="3392722163935571543">"em <xliff:g id="COUNT">%d</xliff:g> d"</string> <string name="duration_years_shortest_future" msgid="5537464088352970388">"em <xliff:g id="COUNT">%d</xliff:g> a"</string> - <string name="duration_minutes_relative" msgid="8620337701051015593">"{count,plural, =1{Há # minuto}other{Há # minutos}}"</string> - <string name="duration_hours_relative" msgid="4836449961693180253">"{count,plural, =1{Há # hora}other{Há # horas}}"</string> - <string name="duration_days_relative" msgid="621965767567258302">"{count,plural, =1{Há # dia}other{Há # dias}}"</string> - <string name="duration_years_relative" msgid="8731202348869424370">"{count,plural, =1{Há # ano}other{Há # anos}}"</string> - <string name="duration_minutes_relative_future" msgid="5259574171747708115">"{count,plural, =1{# minuto}other{# minutos}}"</string> - <string name="duration_hours_relative_future" msgid="6670440478481140565">"{count,plural, =1{# hora}other{# horas}}"</string> - <string name="duration_days_relative_future" msgid="8870658635774250746">"{count,plural, =1{# dia}other{# dias}}"</string> - <string name="duration_years_relative_future" msgid="8855853883925918380">"{count,plural, =1{# ano}other{# anos}}"</string> + <string name="duration_minutes_relative" msgid="8620337701051015593">"{count,plural, =1{Há # minuto}many{Há # minutos}other{Há # minutos}}"</string> + <string name="duration_hours_relative" msgid="4836449961693180253">"{count,plural, =1{Há # hora}many{Há # horas}other{Há # horas}}"</string> + <string name="duration_days_relative" msgid="621965767567258302">"{count,plural, =1{Há # dia}many{Há # dias}other{Há # dias}}"</string> + <string name="duration_years_relative" msgid="8731202348869424370">"{count,plural, =1{Há # ano}many{Há # anos}other{Há # anos}}"</string> + <string name="duration_minutes_relative_future" msgid="5259574171747708115">"{count,plural, =1{# minuto}many{# minutos}other{# minutos}}"</string> + <string name="duration_hours_relative_future" msgid="6670440478481140565">"{count,plural, =1{# hora}many{# horas}other{# horas}}"</string> + <string name="duration_days_relative_future" msgid="8870658635774250746">"{count,plural, =1{# dia}many{# dias}other{# dias}}"</string> + <string name="duration_years_relative_future" msgid="8855853883925918380">"{count,plural, =1{# ano}many{# anos}other{# anos}}"</string> <string name="VideoView_error_title" msgid="5750686717225068016">"Problema com o vídeo"</string> <string name="VideoView_error_text_invalid_progressive_playback" msgid="3782449246085134720">"Este vídeo não é válido para transmissão neste aparelho."</string> <string name="VideoView_error_text_unknown" msgid="7658683339707607138">"Não é possível reproduzir este vídeo."</string> @@ -1251,8 +1257,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"A iniciar aplicações"</string> <string name="android_upgrading_complete" msgid="409800058018374746">"A concluir o arranque."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Premiu o botão ligar/desligar. Geralmente, esta ação desliga o ecrã.\n\nExperimente tocar levemente ao configurar a sua impressão digital."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Toque para desligar o ecrã"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Desligar ecrã"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"Continuar a validar a impressão digital?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"Premiu o botão ligar/desligar. Geralmente, esta ação desliga o ecrã.\n\nExperimente tocar levemente para validar a sua impressão digital."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Desligar ecrã"</string> @@ -1509,7 +1517,7 @@ <string name="skip_button_label" msgid="3566599811326688389">"Ignorar"</string> <string name="no_matches" msgid="6472699895759164599">"Sem correspondências"</string> <string name="find_on_page" msgid="5400537367077438198">"Localizar na página"</string> - <string name="matches_found" msgid="2296462299979507689">"{count,plural, =1{# correspondência}other{# de {total}}}"</string> + <string name="matches_found" msgid="2296462299979507689">"{count,plural, =1{# correspondência}many{# de {total}}other{# de {total}}}"</string> <string name="action_mode_done" msgid="2536182504764803222">"Concluído"</string> <string name="progress_erasing" msgid="6891435992721028004">"A apagar o armazenamento partilhado…"</string> <string name="share" msgid="4157615043345227321">"Partilhar"</string> @@ -1862,14 +1870,14 @@ <string name="data_saver_description" msgid="4995164271550590517">"Para ajudar a reduzir a utilização de dados, a Poupança de dados impede que algumas apps enviem ou recebam dados em segundo plano. Uma determinada app que esteja a utilizar atualmente pode aceder aos dados, mas é possível que o faça com menos frequência. Isto pode significar, por exemplo, que as imagens não são apresentadas até que toque nas mesmas."</string> <string name="data_saver_enable_title" msgid="7080620065745260137">"Ativar a Poupança de dados?"</string> <string name="data_saver_enable_button" msgid="4399405762586419726">"Ativar"</string> - <string name="zen_mode_duration_minutes_summary" msgid="4555514757230849789">"{count,plural, =1{Durante um minuto (até à[s] {formattedTime})}other{Durante # minutos (até à[s] {formattedTime})}}"</string> - <string name="zen_mode_duration_minutes_summary_short" msgid="1187553788355486950">"{count,plural, =1{Durante 1 min (até à[s] {formattedTime})}other{Durante # min (até à[s] {formattedTime})}}"</string> - <string name="zen_mode_duration_hours_summary" msgid="3866333100793277211">"{count,plural, =1{Durante 1 hora (até à[s] {formattedTime})}other{Durante # horas (até à[s] {formattedTime})}}"</string> - <string name="zen_mode_duration_hours_summary_short" msgid="687919813833347945">"{count,plural, =1{Durante 1 h (até à[s] {formattedTime})}other{Durante # h (até à[s] {formattedTime})}}"</string> - <string name="zen_mode_duration_minutes" msgid="2340007982276569054">"{count,plural, =1{Durante um minuto}other{Durante # minutos}}"</string> - <string name="zen_mode_duration_minutes_short" msgid="2435756450204526554">"{count,plural, =1{Durante 1 min}other{Durante # min}}"</string> - <string name="zen_mode_duration_hours" msgid="7841806065034711849">"{count,plural, =1{Durante 1 hora}other{Durante # horas}}"</string> - <string name="zen_mode_duration_hours_short" msgid="3666949653933099065">"{count,plural, =1{Durante 1 h}other{Durante # h}}"</string> + <string name="zen_mode_duration_minutes_summary" msgid="4555514757230849789">"{count,plural, =1{Durante um minuto (até à[s] {formattedTime})}many{Durante # minutos (até à[s] {formattedTime})}other{Durante # minutos (até à[s] {formattedTime})}}"</string> + <string name="zen_mode_duration_minutes_summary_short" msgid="1187553788355486950">"{count,plural, =1{Durante 1 min (até à[s] {formattedTime})}many{Durante # min (até à[s] {formattedTime})}other{Durante # min (até à[s] {formattedTime})}}"</string> + <string name="zen_mode_duration_hours_summary" msgid="3866333100793277211">"{count,plural, =1{Durante 1 hora (até à[s] {formattedTime})}many{Durante # horas (até à[s] {formattedTime})}other{Durante # horas (até à[s] {formattedTime})}}"</string> + <string name="zen_mode_duration_hours_summary_short" msgid="687919813833347945">"{count,plural, =1{Durante 1 h (até à[s] {formattedTime})}many{Durante # h (até à[s] {formattedTime})}other{Durante # h (até à[s] {formattedTime})}}"</string> + <string name="zen_mode_duration_minutes" msgid="2340007982276569054">"{count,plural, =1{Durante um minuto}many{Durante # minutos}other{Durante # minutos}}"</string> + <string name="zen_mode_duration_minutes_short" msgid="2435756450204526554">"{count,plural, =1{Durante 1 min}many{Durante # min}other{Durante # min}}"</string> + <string name="zen_mode_duration_hours" msgid="7841806065034711849">"{count,plural, =1{Durante 1 hora}many{Durante # horas}other{Durante # horas}}"</string> + <string name="zen_mode_duration_hours_short" msgid="3666949653933099065">"{count,plural, =1{Durante 1 h}many{Durante # h}other{Durante # h}}"</string> <string name="zen_mode_until_next_day" msgid="1403042784161725038">"Até <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> <string name="zen_mode_until" msgid="2250286190237669079">"Até às <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> <string name="zen_mode_alarm" msgid="7046911727540499275">"Até <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (próximo alarme)"</string> @@ -2000,7 +2008,7 @@ <string name="autofill_save_accessibility_title" msgid="1523225776218450005">"Guardar para o Preenchimento automático"</string> <string name="autofill_error_cannot_autofill" msgid="6528827648643138596">"Não é possível preencher automaticamente o conteúdo"</string> <string name="autofill_picker_no_suggestions" msgid="1076022650427481509">"Sem sugestões do preenchimento automático"</string> - <string name="autofill_picker_some_suggestions" msgid="5560549696296202701">"{count,plural, =1{Uma sugestão do preenchimento automático}other{# sugestões de preenchimento automático}}"</string> + <string name="autofill_picker_some_suggestions" msgid="5560549696296202701">"{count,plural, =1{Uma sugestão do preenchimento automático}many{# sugestões de preenchimento automático}other{# sugestões de preenchimento automático}}"</string> <string name="autofill_save_title" msgid="7719802414283739775">"Pretende guardar em "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string> <string name="autofill_save_title_with_type" msgid="3002460014579799605">"Pretende guardar <xliff:g id="TYPE">%1$s</xliff:g> em "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string> <string name="autofill_save_title_with_2types" msgid="3783270967447869241">"Pretende guardar <xliff:g id="TYPE_0">%1$s</xliff:g> e <xliff:g id="TYPE_1">%2$s</xliff:g> em "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string> @@ -2110,7 +2118,7 @@ <string name="mime_type_presentation_ext" msgid="8761049335564371468">"Apresentação <xliff:g id="EXTENSION">%1$s</xliff:g>"</string> <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"O Bluetooth continuará ativado durante o modo de avião."</string> <string name="car_loading_profile" msgid="8219978381196748070">"A carregar…"</string> - <string name="file_count" msgid="3220018595056126969">"{count,plural, =1{{file_name} + # ficheiro}other{{file_name} + # ficheiros}}"</string> + <string name="file_count" msgid="3220018595056126969">"{count,plural, =1{{file_name} + # ficheiro}many{{file_name} + # ficheiros}other{{file_name} + # ficheiros}}"</string> <string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"Não existem pessoas recomendadas com quem partilhar"</string> <string name="chooser_all_apps_button_label" msgid="3230427756238666328">"Lista de aplicações"</string> <string name="usb_device_resolve_prompt_warn" msgid="325871329788064199">"Esta app não recebeu autorização de gravação, mas pode capturar áudio através deste dispositivo USB."</string> diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml index cf577551a695..3abf2b353177 100644 --- a/core/res/res/values-pt/strings.xml +++ b/core/res/res/values-pt/strings.xml @@ -52,6 +52,7 @@ <string name="enablePin" msgid="2543771964137091212">"Falha. Ative o bloqueio do chip/R-UIM."</string> <plurals name="pinpuk_attempts" formatted="false" msgid="1619867269012213584"> <item quantity="one">Tentativas restantes: <xliff:g id="NUMBER_1">%d</xliff:g>. Caso o código correto não seja digitado, o chip será bloqueado.</item> + <item quantity="many">You have <xliff:g id="NUMBER_1">%d</xliff:g> remaining attempts before SIM is locked.</item> <item quantity="other">Tentativas restantes: <xliff:g id="NUMBER_1">%d</xliff:g>. Caso o código correto não seja digitado, o chip será bloqueado.</item> </plurals> <string name="imei" msgid="2157082351232630390">"IMEI"</string> @@ -180,7 +181,7 @@ <string name="low_memory" product="watch" msgid="3479447988234030194">"Armazenamento do relógio cheio. Exclua alguns arquivos para liberar espaço."</string> <string name="low_memory" product="tv" msgid="6663680413790323318">"O armazenamento do dispositivo Android TV está cheio. Exclua alguns arquivos para liberar espaço."</string> <string name="low_memory" product="default" msgid="2539532364144025569">"O armazenamento do telefone está cheio. Exclua alguns arquivos para liberar espaço."</string> - <string name="ssl_ca_cert_warning" msgid="7233573909730048571">"{count,plural, =1{Autoridade certificadora instalada}one{Autoridade certificadora instalada}other{Autoridades certificadoras instaladas}}"</string> + <string name="ssl_ca_cert_warning" msgid="7233573909730048571">"{count,plural, =1{Autoridade certificadora instalada}one{Autoridade certificadora instalada}many{Autoridades certificadoras instaladas}other{Autoridades certificadoras instaladas}}"</string> <string name="ssl_ca_cert_noti_by_unknown" msgid="4961102218216815242">"Por terceiros desconhecidos"</string> <string name="ssl_ca_cert_noti_by_administrator" msgid="4564941950768783879">"Pelo administrador do seu perfil de trabalho"</string> <string name="ssl_ca_cert_noti_managed" msgid="217337232273211674">"Por <xliff:g id="MANAGING_DOMAIN">%s</xliff:g>"</string> @@ -254,7 +255,7 @@ <string name="bugreport_option_interactive_summary" msgid="8493795476325339542">"Use este recurso na maioria das circunstâncias. Ele permite que você acompanhe o progresso do relatório, informe mais detalhes sobre o problema e faça capturas de tela. É possível que ele omita algumas seções menos utilizadas que levam muito tempo na emissão dos relatórios."</string> <string name="bugreport_option_full_title" msgid="7681035745950045690">"Relatório completo"</string> <string name="bugreport_option_full_summary" msgid="1975130009258435885">"Use esta opção para ter o mínimo de interferência do sistema quando seu dispositivo não estiver respondendo ou estiver muito lento, ou quando você precisar de todas as seções de relatórios. Ela não permite que você informe mais detalhes ou faça capturas de tela adicionais."</string> - <string name="bugreport_countdown" msgid="6418620521782120755">"{count,plural, =1{Capturas de tela para o relatório do bug vão ser feitas em # segundo.}one{Capturas de tela para o relatório do bug vão ser feitas em # segundo.}other{Capturas de tela para o relatório do bug vão ser feitas em # segundos.}}"</string> + <string name="bugreport_countdown" msgid="6418620521782120755">"{count,plural, =1{Capturas de tela para o relatório do bug vão ser feitas em # segundo.}one{Capturas de tela para o relatório do bug vão ser feitas em # segundo.}many{Capturas de tela para o relatório do bug vão ser feitas em # segundos.}other{Capturas de tela para o relatório do bug vão ser feitas em # segundos.}}"</string> <string name="bugreport_screenshot_success_toast" msgid="7986095104151473745">"Captura de tela com o relatório do bug concluída"</string> <string name="bugreport_screenshot_failure_toast" msgid="6736320861311294294">"Falha ao capturar a tela com o relatório do bug"</string> <string name="global_action_toggle_silent_mode" msgid="8464352592860372188">"Modo silencioso"</string> @@ -586,13 +587,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Usar bloqueio de tela"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Insira seu bloqueio de tela para continuar"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Pressione o sensor com firmeza"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Não foi possível processar a impressão digital. Tente novamente."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Limpe o sensor de impressão digital e tente novamente"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Limpe o sensor e tente novamente"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Pressione o sensor com firmeza"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"O movimento do dedo está muito lento. Tente novamente."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Use outra impressão digital"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Claro demais"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Ajuste a posição do dedo"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Mude a posição do dedo ligeiramente a cada momento"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +608,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Rosto autenticado, pressione \"Confirmar\""</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Hardware de impressão digital não disponível."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Não foi possível configurar a impressão digital"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Tempo máximo para captura da impressão digital atingido. Tente novamente."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Operação de impressão digital cancelada."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Operação de impressão digital cancelada pelo usuário."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Excesso de tentativas. Tente novamente mais tarde."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Excesso de tentativas. Use o bloqueio de tela."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Tente novamente."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Nenhuma impressão digital registrada."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Este dispositivo não tem um sensor de impressão digital."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Sensor desativado temporariamente."</string> @@ -638,7 +644,7 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Entre em contato com uma assistência técnica."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"Falha ao criar o modelo de rosto. Tente de novo."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Muito iluminado. Diminua a iluminação."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Use uma iluminação mais intensa"</string> + <string name="face_acquired_too_dark" msgid="8539853432479385326">"Não há luz suficiente"</string> <string name="face_acquired_too_close" msgid="4453646176196302462">"Afaste o smartphone"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Aproxime o smartphone do seu rosto"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Mova o smartphone para cima"</string> @@ -1088,7 +1094,7 @@ <string name="enable_explore_by_touch_warning_message" product="default" msgid="4312979647356179250">"<xliff:g id="ACCESSIBILITY_SERVICE_NAME">%1$s</xliff:g> quer ativar o Explorar por toque. Com ele, você pode ouvir ou ver descrições do que está sob seu dedo e interagir com o telefone por gestos."</string> <string name="oneMonthDurationPast" msgid="4538030857114635777">"1 mês atrás"</string> <string name="beforeOneMonthDurationPast" msgid="8315149541372065392">"Antes de 1 mês atrás"</string> - <string name="last_num_days" msgid="2393660431490280537">"{count,plural, =1{No último # dia}one{No último # dia}other{Nos últimos # dias}}"</string> + <string name="last_num_days" msgid="2393660431490280537">"{count,plural, =1{No último # dia}one{No último # dia}many{Nos últimos # dias}other{Nos últimos # dias}}"</string> <string name="last_month" msgid="1528906781083518683">"Mês passado"</string> <string name="older" msgid="1645159827884647400">"Mais antigos"</string> <string name="preposition_for_date" msgid="2780767868832729599">"em <xliff:g id="DATE">%s</xliff:g>"</string> @@ -1115,14 +1121,14 @@ <string name="duration_hours_shortest_future" msgid="2979276794547981674">"em <xliff:g id="COUNT">%d</xliff:g>h"</string> <string name="duration_days_shortest_future" msgid="3392722163935571543">"em <xliff:g id="COUNT">%d</xliff:g> dias"</string> <string name="duration_years_shortest_future" msgid="5537464088352970388">"em <xliff:g id="COUNT">%d</xliff:g>a"</string> - <string name="duration_minutes_relative" msgid="8620337701051015593">"{count,plural, =1{# minuto atrás}one{# minuto atrás}other{# minutos atrás}}"</string> - <string name="duration_hours_relative" msgid="4836449961693180253">"{count,plural, =1{# hora atrás}one{# hora atrás}other{# horas atrás}}"</string> - <string name="duration_days_relative" msgid="621965767567258302">"{count,plural, =1{# dia atrás}one{# dia atrás}other{# dias atrás}}"</string> - <string name="duration_years_relative" msgid="8731202348869424370">"{count,plural, =1{# ano atrás}one{# ano atrás}other{# anos atrás}}"</string> - <string name="duration_minutes_relative_future" msgid="5259574171747708115">"{count,plural, =1{# minuto}one{# minuto}other{# minutos}}"</string> - <string name="duration_hours_relative_future" msgid="6670440478481140565">"{count,plural, =1{# hora}one{# hora}other{# horas}}"</string> - <string name="duration_days_relative_future" msgid="8870658635774250746">"{count,plural, =1{# dia}one{# dia}other{# dias}}"</string> - <string name="duration_years_relative_future" msgid="8855853883925918380">"{count,plural, =1{# ano}one{# ano}other{# anos}}"</string> + <string name="duration_minutes_relative" msgid="8620337701051015593">"{count,plural, =1{# minuto atrás}one{# minuto atrás}many{# minutos atrás}other{# minutos atrás}}"</string> + <string name="duration_hours_relative" msgid="4836449961693180253">"{count,plural, =1{# hora atrás}one{# hora atrás}many{# horas atrás}other{# horas atrás}}"</string> + <string name="duration_days_relative" msgid="621965767567258302">"{count,plural, =1{# dia atrás}one{# dia atrás}many{# dias atrás}other{# dias atrás}}"</string> + <string name="duration_years_relative" msgid="8731202348869424370">"{count,plural, =1{# ano atrás}one{# ano atrás}many{# anos atrás}other{# anos atrás}}"</string> + <string name="duration_minutes_relative_future" msgid="5259574171747708115">"{count,plural, =1{# minuto}one{# minuto}many{# minutos}other{# minutos}}"</string> + <string name="duration_hours_relative_future" msgid="6670440478481140565">"{count,plural, =1{# hora}one{# hora}many{# horas}other{# horas}}"</string> + <string name="duration_days_relative_future" msgid="8870658635774250746">"{count,plural, =1{# dia}one{# dia}many{# dias}other{# dias}}"</string> + <string name="duration_years_relative_future" msgid="8855853883925918380">"{count,plural, =1{# ano}one{# ano}many{# anos}other{# anos}}"</string> <string name="VideoView_error_title" msgid="5750686717225068016">"Problema com o vídeo"</string> <string name="VideoView_error_text_invalid_progressive_playback" msgid="3782449246085134720">"Este vídeo não é válido para transmissão neste dispositivo."</string> <string name="VideoView_error_text_unknown" msgid="7658683339707607138">"Não é possível reproduzir este vídeo."</string> @@ -1251,8 +1257,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Iniciando apps."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"Concluindo a inicialização."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Você pressionou o botão liga/desliga. Normalmente, essa ação desliga a tela.\n\nToque levemente na tela durante a configuração da impressão digital."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Toque para desligar a tela"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Desligar a tela"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"Continuar a verificação da digital?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"Você pressionou o botão liga/desliga. Normalmente, essa ação desliga a tela.\n\nToque levemente na tela para verificar sua impressão digital."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Desligar a tela"</string> @@ -1509,7 +1517,7 @@ <string name="skip_button_label" msgid="3566599811326688389">"Pular"</string> <string name="no_matches" msgid="6472699895759164599">"Não encontrado"</string> <string name="find_on_page" msgid="5400537367077438198">"Localizar na página"</string> - <string name="matches_found" msgid="2296462299979507689">"{count,plural, =1{# correspondência}one{# de {total}}other{# de {total}}}"</string> + <string name="matches_found" msgid="2296462299979507689">"{count,plural, =1{# correspondência}one{# de {total}}many{# de {total}}other{# de {total}}}"</string> <string name="action_mode_done" msgid="2536182504764803222">"Concluído"</string> <string name="progress_erasing" msgid="6891435992721028004">"Limpando armazenamento compartilhado…"</string> <string name="share" msgid="4157615043345227321">"Compartilhar"</string> @@ -1862,14 +1870,14 @@ <string name="data_saver_description" msgid="4995164271550590517">"Para ajudar a reduzir o uso de dados, a Economia de dados impede que alguns apps enviem ou recebam dados em segundo plano. Um app que você está usando no momento pode acessar dados, mas com menos frequência. Isso pode fazer com que imagens não apareçam até você tocar nelas."</string> <string name="data_saver_enable_title" msgid="7080620065745260137">"Ativar a Economia de dados?"</string> <string name="data_saver_enable_button" msgid="4399405762586419726">"Ativar"</string> - <string name="zen_mode_duration_minutes_summary" msgid="4555514757230849789">"{count,plural, =1{Por um minuto (até {formattedTime})}one{Por # minuto (até {formattedTime})}other{Por # minutos (até {formattedTime})}}"</string> - <string name="zen_mode_duration_minutes_summary_short" msgid="1187553788355486950">"{count,plural, =1{Por 1min (até {formattedTime})}one{Por #min (até {formattedTime})}other{Por #min (até {formattedTime})}}"</string> - <string name="zen_mode_duration_hours_summary" msgid="3866333100793277211">"{count,plural, =1{Por 1 hora (até {formattedTime})}one{Por # hora (até {formattedTime})}other{Por # horas (até {formattedTime})}}"</string> - <string name="zen_mode_duration_hours_summary_short" msgid="687919813833347945">"{count,plural, =1{Por 1h (até {formattedTime})}one{Por #h (até {formattedTime})}other{Por #h (até {formattedTime})}}"</string> - <string name="zen_mode_duration_minutes" msgid="2340007982276569054">"{count,plural, =1{Por um minuto}one{Por # minuto}other{Por # minutos}}"</string> - <string name="zen_mode_duration_minutes_short" msgid="2435756450204526554">"{count,plural, =1{Por 1min}one{Por #min}other{Por #min}}"</string> - <string name="zen_mode_duration_hours" msgid="7841806065034711849">"{count,plural, =1{Por 1 hora}one{Por # hora}other{Por # horas}}"</string> - <string name="zen_mode_duration_hours_short" msgid="3666949653933099065">"{count,plural, =1{Por 1h}one{Por #h}other{Por #h}}"</string> + <string name="zen_mode_duration_minutes_summary" msgid="4555514757230849789">"{count,plural, =1{Por um minuto (até {formattedTime})}one{Por # minuto (até {formattedTime})}many{Por # minutos (até {formattedTime})}other{Por # minutos (até {formattedTime})}}"</string> + <string name="zen_mode_duration_minutes_summary_short" msgid="1187553788355486950">"{count,plural, =1{Por 1min (até {formattedTime})}one{Por #min (até {formattedTime})}many{Por #min (até {formattedTime})}other{Por #min (até {formattedTime})}}"</string> + <string name="zen_mode_duration_hours_summary" msgid="3866333100793277211">"{count,plural, =1{Por 1 hora (até {formattedTime})}one{Por # hora (até {formattedTime})}many{Por # horas (até {formattedTime})}other{Por # horas (até {formattedTime})}}"</string> + <string name="zen_mode_duration_hours_summary_short" msgid="687919813833347945">"{count,plural, =1{Por 1h (até {formattedTime})}one{Por #h (até {formattedTime})}many{Por #h (até {formattedTime})}other{Por #h (até {formattedTime})}}"</string> + <string name="zen_mode_duration_minutes" msgid="2340007982276569054">"{count,plural, =1{Por um minuto}one{Por # minuto}many{Por # minutos}other{Por # minutos}}"</string> + <string name="zen_mode_duration_minutes_short" msgid="2435756450204526554">"{count,plural, =1{Por 1min}one{Por #min}many{Por #min}other{Por #min}}"</string> + <string name="zen_mode_duration_hours" msgid="7841806065034711849">"{count,plural, =1{Por 1 hora}one{Por # hora}many{Por # horas}other{Por # horas}}"</string> + <string name="zen_mode_duration_hours_short" msgid="3666949653933099065">"{count,plural, =1{Por 1h}one{Por #h}many{Por #h}other{Por #h}}"</string> <string name="zen_mode_until_next_day" msgid="1403042784161725038">"Até <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> <string name="zen_mode_until" msgid="2250286190237669079">"Até às <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string> <string name="zen_mode_alarm" msgid="7046911727540499275">"Até <xliff:g id="FORMATTEDTIME">%1$s</xliff:g> (próximo alarme)"</string> @@ -2000,7 +2008,7 @@ <string name="autofill_save_accessibility_title" msgid="1523225776218450005">"Salvar no Preenchimento automático"</string> <string name="autofill_error_cannot_autofill" msgid="6528827648643138596">"Não é possível preencher os conteúdos automaticamente"</string> <string name="autofill_picker_no_suggestions" msgid="1076022650427481509">"Sem sugestões de preenchimento automático"</string> - <string name="autofill_picker_some_suggestions" msgid="5560549696296202701">"{count,plural, =1{Uma sugestão de preenchimento automático}one{# sugestão de preenchimento automático}other{# sugestões de preenchimento automático}}"</string> + <string name="autofill_picker_some_suggestions" msgid="5560549696296202701">"{count,plural, =1{Uma sugestão de preenchimento automático}one{# sugestão de preenchimento automático}many{# sugestões de preenchimento automático}other{# sugestões de preenchimento automático}}"</string> <string name="autofill_save_title" msgid="7719802414283739775">"Salvar em "<b>"<xliff:g id="LABEL">%1$s</xliff:g>"</b>"?"</string> <string name="autofill_save_title_with_type" msgid="3002460014579799605">"Salvar <xliff:g id="TYPE">%1$s</xliff:g> em "<b>"<xliff:g id="LABEL">%2$s</xliff:g>"</b>"?"</string> <string name="autofill_save_title_with_2types" msgid="3783270967447869241">"Salvar <xliff:g id="TYPE_0">%1$s</xliff:g> e <xliff:g id="TYPE_1">%2$s</xliff:g> em "<b>"<xliff:g id="LABEL">%3$s</xliff:g>"</b>"?"</string> @@ -2110,7 +2118,7 @@ <string name="mime_type_presentation_ext" msgid="8761049335564371468">"Apresentação em <xliff:g id="EXTENSION">%1$s</xliff:g>"</string> <string name="bluetooth_airplane_mode_toast" msgid="2066399056595768554">"O Bluetooth permanecerá ativado no modo avião"</string> <string name="car_loading_profile" msgid="8219978381196748070">"Carregando"</string> - <string name="file_count" msgid="3220018595056126969">"{count,plural, =1{{file_name} + # arquivo}one{{file_name} + # arquivo}other{{file_name} + # arquivos}}"</string> + <string name="file_count" msgid="3220018595056126969">"{count,plural, =1{{file_name} + # arquivo}one{{file_name} + # arquivo}many{{file_name} + # arquivos}other{{file_name} + # arquivos}}"</string> <string name="chooser_no_direct_share_targets" msgid="1511722103987329028">"Não há sugestões de pessoas para compartilhar"</string> <string name="chooser_all_apps_button_label" msgid="3230427756238666328">"Lista de apps"</string> <string name="usb_device_resolve_prompt_warn" msgid="325871329788064199">"Este app não tem permissão de gravação, mas pode capturar áudio pelo dispositivo USB."</string> diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml index b4c2c32b7db5..721a745758da 100644 --- a/core/res/res/values-ro/strings.xml +++ b/core/res/res/values-ro/strings.xml @@ -587,13 +587,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Folosiți blocarea ecranului"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Introduceți blocarea ecranului ca să continuați"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Apăsați ferm pe senzor"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Amprenta nu a putut fi procesată. Încercați din nou."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Curățați senzorul de amprentă și încercați din nou"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Curățați senzorul și încercați din nou"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Apăsați ferm pe senzor"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Ați mișcat degetul prea lent. Încercați din nou."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Încercați altă amprentă"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Prea luminos"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Încercați să ajustați"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Schimbați ușor poziția degetului de fiecare dată"</string> <string-array name="fingerprint_acquired_vendor"> @@ -605,13 +608,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Chip autentificat, apăsați Confirmați"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Hardware-ul pentru amprentă nu este disponibil."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Nu se poate configura amprenta"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Timpul pentru amprentare a expirat. Încercați din nou."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Operațiunea privind amprenta a fost anulată."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Operațiunea privind amprenta a fost anulată de utilizator."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Prea multe încercări. Încercați din nou mai târziu."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Prea multe încercări. Folosește blocarea ecranului."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Încercați din nou."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Nu au fost înregistrate amprente."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Dispozitivul nu are senzor de amprentă."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Senzorul este dezactivat temporar."</string> @@ -639,7 +644,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Vizitați un furnizor de servicii de reparații."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"Nu se poate crea modelul facial. Reîncercați."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Prea luminos. Încercați o lumină mai slabă."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Încercați o lumină mai puternică"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"Mutați telefonul mai departe"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Mutați telefonul mai aproape"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Mutați telefonul mai sus"</string> @@ -1252,8 +1258,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Se pornesc aplicațiile."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"Se finalizează pornirea."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Ați apăsat butonul de pornire. De obicei, această acțiune dezactivează ecranul.\n\nAtingeți ușor când vă configurați amprenta."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Atinge pentru a dezactiva ecranul"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Dezactivează ecranul"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"Continuați cu verificarea amprentei?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"Ați apăsat butonul de pornire. De obicei, această acțiune dezactivează ecranul.\n\nAtingeți ușor pentru verificarea amprentei."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Dezactivați ecranul"</string> diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml index 290fba782a73..9e5cab6f033f 100644 --- a/core/res/res/values-ru/strings.xml +++ b/core/res/res/values-ru/strings.xml @@ -588,13 +588,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Использовать блокировку экрана"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Чтобы продолжить, разблокируйте экран."</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Плотно прижмите палец к сканеру."</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Не удалось распознать отпечаток. Повторите попытку."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Очистите сканер отпечатков пальцев и повторите попытку."</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Очистите сканер и повторите попытку."</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Плотно прижмите палец к сканеру."</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Вы перемещали палец слишком медленно. Повторите попытку."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Попробуйте сохранить отпечаток другого пальца."</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Слишком светло."</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Попробуйте изменить положение пальца."</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Каждый раз немного меняйте положение пальца."</string> <string-array name="fingerprint_acquired_vendor"> @@ -606,13 +609,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Лицо распознано, нажмите кнопку \"Подтвердить\""</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Сканер недоступен"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Не удалось сохранить отпечаток."</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Превышено время ожидания. Повторите попытку."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Операция с отпечатком отменена."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Операция с отпечатком пальца отменена пользователем."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Слишком много попыток. Повторите позже."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Слишком много попыток. Используйте другой способ разблокировки экрана."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Повторите попытку."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Нет отсканированных отпечатков пальцев"</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"На этом устройстве нет сканера отпечатков пальцев."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Сканер отпечатков пальцев временно отключен."</string> @@ -640,7 +645,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Обратитесь в сервисный центр."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"Невозможно создать модель лица. Повторите попытку."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Слишком светло. Сделайте освещение менее ярким."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Сделайте освещение ярче"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"Переместите телефон дальше от лица"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Переместите телефон ближе к лицу"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Переместите телефон выше"</string> @@ -1253,8 +1259,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Запуск приложений."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"Окончание загрузки..."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Вы нажали кнопку питания. Обычно это приводит к отключению экрана.\n\nПри добавлении отпечатка пальца слегка прикоснитесь к кнопке."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Нажмите, чтобы отключить экран"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Отключить экран"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"Продолжить сканирование отпечатка?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"Вы нажали кнопку питания. Обычно это приводит к отключению экрана.\n\nЧтобы отсканировать отпечаток пальца, слегка прикоснитесь к кнопке."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Отключить экран"</string> diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml index 9bbdebef2065..f629f4544cd2 100644 --- a/core/res/res/values-si/strings.xml +++ b/core/res/res/values-si/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"තිර අගුල භාවිත කරන්න"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"ඉදිරියට යාමට ඔබගේ තිර අගුල ඇතුළත් කරන්න"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"සංවේදකය මත තදින් ඔබන්න"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"ඇඟිලි සලකුණ පිරිසැකසීමට නොහැකි විය. කරුණාකර නැවත උත්සාහ කරන්න."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"ඇඟිලි සලකුණු සංවේදකය පිරිසිදු කර නැවත උත්සාහ කරන්න"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"සංවේදකය පිරිසිදු කර නැවත උත්සාහ කරන්න"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"සංවේදකය මත තදින් ඔබන්න"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"ඇඟිල්ල වඩා සෙමෙන් ගෙන යන ලදි. කරුණාකර නැවත උත්සාහ කරන්න."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"තවත් ඇඟිලි සලකුණක් උත්සාහ කරන්න"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"දීප්තිය වැඩියි"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"සීරුමාරු කිරීම උත්සාහ කරන්න"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"එක් එක් අවස්ථාවේ ඔබගේ ඇඟිල්ලේ පිහිටීම මදක් වෙනස් කරන්න"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"මුහුණ සත්යාපනය කරන ලදී, කරුණාකර තහවුරු කරන්න ඔබන්න"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"ඇඟිලි සලකුණු දෘඪාංගය ලද නොහැකිය."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"ඇඟිලි සලකුණ පිහිටුවිය නොහැකිය"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"ඇඟිලි සලකුණු කාල නිමාව ළඟා විය. නැවත උත්සාහ කරන්න."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"ඇඟිලි සලකුණු මෙහෙයුම අවලංගු කරන ලදී."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"පරිශීලක විසින් ඇඟිලි සලකුණු මෙහෙයුම අවසන් කරන ලදී."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"උත්සාහයන් ඉතා වැඩි ගණනකි. කරුණාකර පසුව නැවත උත්සාහ කරන්න."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"උත්සාහ ගණන ඉතා වැඩියි. ඒ වෙනුවට තිර අගුල භාවිත කරන්න."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"නැවත උත්සාහ කරන්න."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"ඇඟිලි සලකුණු ඇතුළත් කර නොමැත."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"මෙම උපාංගයේ ඇඟිලි සලකුණු සංවේදකයක් නොමැත."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"සංවේදකය තාවකාලිකව අබල කර ඇත."</string> @@ -638,7 +643,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"අළුත්වැඩියා සැපයුම්කරුවෙකු බලන්න."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"ඔබගේ මුහුණු ආකෘතිය තැනිය නොහැකිය. නැවත උත්සාහ කරන්න."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"දීප්තිය වැඩියි. තවත් මඳ ආලෝකය උත්සාහ කරන්න."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"තවත් දීප්තිමත් ආලෝකය උත්සාහ කරන්න"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"දුරකථනය තවත් ඈතට ගෙන යන්න"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"දුරකථනය තවත් සමීපයට ගෙන එන්න"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"දුරකථනය තවත් ඉහළට ගෙන යන්න"</string> @@ -1251,8 +1257,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"යෙදුම් ආරම්භ කරමින්."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"ඇරඹුම අවසාන කරමින්."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"ඔබ බල බොත්තම එබුවේය — සාමාන්යයෙන් මෙය තිරය ක්රියාවිරහිත කරයි.\n\nඔබගේ ඇඟිලි සලකුණ පිහිටුවන අතරතුර සැහැල්ලුවෙන් තට්ටු කිරීමට උත්සාහ කරන්න."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"තිරය අක්රිය කිරීමට තට්ටු කරන්න"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"තිරය අක්රිය කරන්න"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"ඔබගේ ඇඟිලි සලකුණ සත්යාපනය දිගටම කරන්නද?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"ඔබ බල බොත්තම එබුවේය — සාමාන්යයෙන් මෙය තිරය ක්රියාවිරහිත කරයි.\n\nඔබගේ ඇඟිලි සලකුණ සත්යාපනය කිරීමට සැහැල්ලුවෙන් තට්ටු කිරීමට උත්සාහ කරන්න."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"තිරය අක්රිය කරන්න"</string> diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml index aaaf573412ff..8093cd2801b7 100644 --- a/core/res/res/values-sk/strings.xml +++ b/core/res/res/values-sk/strings.xml @@ -588,13 +588,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Použiť zámku obrazovky"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Pokračujte zadaním zámky obrazovky"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Pevne pridržte senzor"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Odtlačok prsta sa nepodarilo spracovať. Skúste to znova."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Vyčistite senzor odtlačkov prstov a skúste to znova"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Vyčistite senzor a skúste to znova"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Pevne pridržte senzor"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Pohli ste prstom príliš pomaly. Skúste to znova."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Vyskúšajte iný odtlačok prsta"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Príliš jasno"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Vyskúšajte upraviť"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Zakaždým trocha zmeňte pozíciu prsta"</string> <string-array name="fingerprint_acquired_vendor"> @@ -606,13 +609,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Tvár bola overená, stlačte tlačidlo potvrdenia"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Hardvér na snímanie odtlačku prsta nie je k dispozícii"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Odtlačok prsta sa nedá nastaviť"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Časový limit rozpoznania odtlačku prsta vypršal. Skúste to znova."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Operácia týkajúca sa odtlačku prsta bola zrušená"</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Overenie odtlačku prsta zrušil používateľ."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Príliš veľa pokusov. Skúste to neskôr."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Príliš veľa pokusov. Použite radšej zámku obrazovky."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Skúste to znova"</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Neregistrovali ste žiadne odtlačky prstov."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Toto zariadenie nemá senzor odtlačkov prstov."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Senzor je dočasne vypnutý."</string> @@ -640,7 +645,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Navštívte poskytovateľa opráv."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"Model tváre sa nedá vytvoriť. Skúste to znova."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Príliš veľa svetla. Skúste jemnejšie osvetlenie."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Skúste lepšie osvetlenie"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"Oddiaľte telefón"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Priblížte telefón"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Posuňte telefón vyššie"</string> @@ -1253,8 +1259,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Prebieha spúšťanie aplikácií."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"Prebieha dokončovanie spúšťania."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Stlačili ste vypínač. Obvykle tým vypnete obrazovku.\n\nPri nastavovaní odtlačku prsta skúste klepnúť jemne."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Klepnutím vypnite obrazovku"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Vypnúť obrazovku"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"Pokračovať v overovaní odtlačku prsta?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"Stlačili ste vypínač. Obvykle tým vypnete obrazovku.\n\nAk chcete overiť odtlačok prsta, skúste klepnúť jemne."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Vypnúť obrazovku"</string> diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml index c0f0b0d0c036..3b9557d378c0 100644 --- a/core/res/res/values-sl/strings.xml +++ b/core/res/res/values-sl/strings.xml @@ -588,13 +588,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Uporaba odklepanja s poverilnico"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Odklenite zaslon, če želite nadaljevati."</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Prst dobro pridržite na tipalu."</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Prstnega odtisa ni bilo mogoče obdelati. Poskusite znova."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Očistite tipalo prstnih odtisov in poskusite znova."</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Očistite tipalo in poskusite znova."</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Prst dobro pridržite na tipalu."</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Prepočasen premik prsta. Poskusite znova."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Poskusite z drugim prstnim odtisom."</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Presvetlo je."</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Poskusite popraviti položaj prsta."</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Vsakič nekoliko spremenite položaj prsta."</string> <string-array name="fingerprint_acquired_vendor"> @@ -606,13 +609,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Pristnost obraza je preverjena. Pritisnite gumb »Potrdi«."</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Strojna oprema za prstne odtise ni na voljo."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Prstnega odtisa ni mogoče nastaviti."</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Dosežena časovna omejitev za prstni odtis. Poskusite znova."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Dejanje s prstnim odtisom je bilo preklicano."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Dejanje s prstnim odtisom je preklical uporabnik."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Preveč poskusov. Poskusite znova pozneje."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Preveč poskusov. Odklenite z zaklepanjem zaslona."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Poskusite znova."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Ni registriranih prstnih odtisov."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Ta naprava nima tipala prstnih odtisov."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Tipalo je začasno onemogočeno."</string> @@ -640,7 +645,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Obiščite ponudnika popravil."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"Modela obraza ni mogoče ustvariti. Poskusite znova."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Presvetlo. Poskusite z blažjo osvetlitvijo."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Poskusite z močnejšo osvetlitvijo."</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"Telefon nekoliko odmaknite."</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Bolj približajte telefon."</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Telefon premaknite višje."</string> @@ -1253,8 +1259,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Zagon aplikacij."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"Dokončevanje zagona."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Pritisnili ste gumb za vklop, s čimer običajno izklopite zaslon.\n\nPoskusite se narahlo dotakniti med nastavljanjem prstnega odtisa."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Dotaknite se za izklop zaslona"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Izklopi zaslon"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"Želite nadaljevati preverjanje prstnega odtisa?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"Pritisnili ste gumb za vklop, s čimer običajno izklopite zaslon.\n\nZa preverjanje prstnega odtisa se poskusite narahlo dotakniti."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Izklopi zaslon"</string> diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml index 68380bc318bc..a2dac967c10f 100644 --- a/core/res/res/values-sq/strings.xml +++ b/core/res/res/values-sq/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Përdor kyçjen e ekranit"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Fut kyçjen e ekranit për të vazhduar"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Shtyp fort te sensori"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Gjurma e gishtit nuk mund të përpunohej. Provo përsëri."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Pastro sensorin e gjurmës së gishtit dhe provo sërish"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Pastro sensorin dhe provo sërish"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Shtyp fort te sensori"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Gishti lëvizi shumë ngadalë. Provo përsëri."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Provo një gjurmë gishti tjetër"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Me shumë ndriçim"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Provo ta rregullosh"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Ndrysho pak pozicionin e gishtit çdo herë"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Fytyra u vërtetua, shtyp \"Konfirmo\""</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Hardueri i gjurmës së gishtit nuk mundësohet."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Nuk mund të konfigurohet gjurma e gishtit"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Koha e veprimit për gjurmën e gishtit skadoi. Provo përsëri."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Operacioni i gjurmës së gishtit u anulua."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Veprimi i gjurmës së gishtit u anulua nga përdoruesi."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Keni bërë shumë tentativa. Provo përsëri më vonë."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Shumë përpjekje. Përdor më mirë kyçjen e ekranit."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Provo përsëri."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Nuk ka asnjë gjurmë gishti të regjistruar."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Kjo pajisje nuk ka sensor të gjurmës së gishtit."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Sensori është çaktivizuar përkohësisht."</string> @@ -638,7 +643,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Vizito një ofrues të shërbimit të riparimit."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"Modeli i fytyrës nuk krijohet. Provo sërish."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Me shumë ndriçim. Provo një ndriçim më të butë."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Provo një ndriçim më të fortë"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"Lëvize telefonin më larg"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Lëvize telefonin më afër"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Lëvize telefonin më lart"</string> @@ -1251,8 +1257,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Aplikacionet e fillimit."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"Po përfundon nisjen."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Shtype butonin e energjisë — zakonisht, kjo e fik ekranin.\n\nProvo të trokasësh lehtë ndërkohë që konfiguron gjurmën e gishtit."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Trokit për ta fikur ekranin"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Fik ekranin"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"Të vazhdohet verifikimi i gjurmës?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"Shtype butonin e energjisë — zakonisht, kjo e fik ekranin.\n\nProvo të trokasësh lehtë për të verifikuar gjurmën e gishtit."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Fik ekranin"</string> diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml index 368bf1e24a7e..64a8535220f6 100644 --- a/core/res/res/values-sr/strings.xml +++ b/core/res/res/values-sr/strings.xml @@ -587,13 +587,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Користите закључавање екрана"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Употребите закључавање екрана да бисте наставили"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Јако притисните сензор"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Није успела обрада отиска прста. Пробајте поново."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Обришите сензор за отисак прста и пробајте поново"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Обришите сензор и пробајте поново"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Јако притисните сензор"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Превише споро сте померили прст. Пробајте поново."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Пробајте са другим отиском прста"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Превише је светло"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Пробајте да прилагодите"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Сваки пут помало промените положај прста"</string> <string-array name="fingerprint_acquired_vendor"> @@ -605,13 +608,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Лице је потврђено. Притисните Потврди"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Хардвер за отиске прстију није доступан."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Подешавање отиска прста није успело"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Временско ограничење за отисак прста је истекло. Пробајте поново."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Радња са отиском прста је отказана."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Корисник је отказао радњу са отиском прста."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Превише покушаја. Пробајте поново касније."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Превише покушаја. Користите закључавање екрана уместо тога."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Пробајте поново."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Није регистрован ниједан отисак прста."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Овај уређај нема сензор за отисак прста."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Сензор је привремено онемогућен."</string> @@ -639,7 +644,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Посетите добављача за поправке."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"Прављење модела лица није успело. Пробајте поново."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Превише је светло. Пробајте са слабијим осветљењем."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Пробајте са јачим осветљењем"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"Удаљите телефон"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Приближите телефон"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Померите телефон нагоре"</string> @@ -1252,8 +1258,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Покретање апликација."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"Завршавање покретања."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Притиснули сте дугме за укључивање – тиме обично искључујете екран.\n\nПробајте лагано да додирнете док подешавате отисак прста."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Додирните да бисте искључили екран"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Искључи екран"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"Настављате верификацију отиска прста?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"Притиснули сте дугме за укључивање – тиме обично искључујете екран.\n\nПробајте лагано да додирнете да бисте верификовали отисак прста."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Искључи екран"</string> diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml index 7a90fed4a8fc..ab51d6dd391f 100644 --- a/core/res/res/values-sv/strings.xml +++ b/core/res/res/values-sv/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Använd skärmlåset"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Fortsätt med hjälp av ditt skärmlås"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Tryck på sensorn med ett stadigt tryck"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Det gick inte att bearbeta fingeravtrycket. Försök igen."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Rengör fingeravtryckssensorn och försök igen"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Rengör sensorn och försök igen"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Tryck hårt på sensorn"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Du rörde fingret för långsamt. Försök igen."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Testa ett annat fingeravtryck"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Det är för ljust"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Testa att justera fingeravtrycket"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Flytta fingret lite varje gång"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Ansiktet har autentiserats. Tryck på Bekräfta"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Det finns ingen maskinvara för fingeravtryck."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Det gick inte att konfigurera fingeravtryck"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Tidsgränsen för fingeravtrycket har uppnåtts. Försök igen."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Fingeravtrycksåtgärden avbröts."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Fingeravtrycksåtgärden avbröts av användaren."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Du har gjort för många försök. Försök igen senare."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"För många försök. Använd låsskärmen i stället."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Försök igen."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Inga fingeravtryck har registrerats."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Enheten har ingen fingeravtryckssensor."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Sensorn har tillfälligt inaktiverats."</string> @@ -638,7 +643,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Besök ett reparationsställe."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"Ansiktsmodellen kunde inte skapas. Försök igen."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Det är för ljust. Testa lägre belysning."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Testa med bättre belysning"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"Flytta telefonen längre bort"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"För telefonen närmare"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Höj telefonen"</string> @@ -1251,8 +1257,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Appar startas."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"Uppgraderingen är klar."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Du tryckte på av/på-knappen, vilket vanligtvis stänger av skärmen.\n\nTesta att trycka lätt när du konfigurerar fingeravtrycket."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Tryck för att stänga av skärmen"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Stäng av skärmen"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"Vill du verifiera ditt fingeravtryck?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"Du tryckte på av/på-knappen, vilket vanligtvis stänger av skärmen.\n\nTesta att trycka lätt för att verifiera ditt fingeravtryck."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Stäng av skärmen"</string> diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml index 2d548433105c..4527c1348b1d 100644 --- a/core/res/res/values-sw/strings.xml +++ b/core/res/res/values-sw/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Tumia mbinu ya kufunga skrini"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Weka mbinu yako ya kufunga skrini ili uendelee"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Bonyeza kwa uthabiti kwenye kitambuzi"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Imeshindwa kuchakata alama ya kidole. Tafadhali jaribu tena."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Safisha kitambua alama ya kidole kisha ujaribu tena"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Safisha kitambuzi kisha ujaribu tena"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Bonyeza kwa nguvu kwenye kitambuzi"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Kidole kilisogezwa polepole zaidi. Tafadhali jaribu tena."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Jaribu alama nyingine ya kidole"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Inang\'aa mno"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Jaribu kurekebisha"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Badilisha mkao wa kidole chako kiasi kila wakati"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Uso umethibitishwa, tafadhali bonyeza thibitisha"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Maunzi ya alama ya kidole hayapatikani."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Imeshindwa kuweka mipangilio ya alama ya kidole"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Muda wa kuweka alama ya kidole umekwisha. Jaribu tena."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Mchakato wa alama ya kidole umeghairiwa."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Mtumiaji ameghairi uthibitishaji wa alama ya kidole."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Majaribio mengi mno. Jaribu tena baadaye."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Umejaribu mara nyingi mno. Badala yake, tumia mbinu ya kufunga skrini."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Jaribu tena."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Hakuna alama za vidole zilizojumuishwa."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Kifaa hiki hakina kitambua alama ya kidole."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Kitambuzi kimezimwa kwa muda."</string> @@ -638,7 +643,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Tembelea mtoa huduma za urekebishaji."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"Imeshindwa kuunda muundo wa uso wako. Jaribu tena."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Inang\'aa mno. Jaribu mwangaza hafifu"</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Jaribu kuongeza mwangaza"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"Sogeza simu mbali kiasi"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Sogeza simu karibu"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Sogeza simu juu zaidi"</string> @@ -1251,8 +1257,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Programu zinaanza"</string> <string name="android_upgrading_complete" msgid="409800058018374746">"Inamaliza kuwasha."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Umebonyeza kitufe cha kuwasha/kuzima — kwa kawaida, hali hii huzima skrini.\n\nJaribu kugusa taratibu unapoweka mipangilio ya alama ya kidole chako."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Gusa ili uzime skrini"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Zima skrini"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"Utaendelea kuthibitisha alama ya kidole chako?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"Umebonyeza kitufe cha kuwasha/kuzima — kwa kawaida, hali hii huzima skrini.\n\nJaribu kugusa taratibu ili uthibitishe alama ya kidole chako."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Zima skrini"</string> diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml index 9a6f6c10b0a5..6c4dcc743a91 100644 --- a/core/res/res/values-ta/strings.xml +++ b/core/res/res/values-ta/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"திரைப் பூட்டைப் பயன்படுத்து"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"தொடர்வதற்கு உங்கள் திரைப் பூட்டை உள்ளிடுங்கள்"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"சென்சாரின் மீது நன்றாக அழுத்தவும்"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"கைரேகையைச் செயலாக்க முடியவில்லை. மீண்டும் முயலவும்."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"கைரேகை சென்சாரைச் சுத்தம் செய்துவிட்டு மீண்டும் முயலவும்"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"சென்சாரைச் சுத்தம் செய்துவிட்டு மீண்டும் முயலவும்"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"சென்சாரின் மீது நன்றாக அழுத்தவும்"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"விரலை மிகவும் மெதுவாக நகர்த்திவிட்டீர்கள். மீண்டும் முயற்சிக்கவும்."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"வேறு கைரேகையை முயலவும்"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"அதிக வெளிச்சமாக உள்ளது"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"விரலைச் சரியாக வைக்கவும்"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"ஒவ்வொரு முறையும் விரலின் நிலையைச் சிறிதளவு மாற்றுங்கள்"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"முகம் அங்கீகரிக்கப்பட்டது. ’உறுதிப்படுத்துக’ என்பதை அழுத்துக"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"கைரேகை வன்பொருள் இல்லை."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"கைரேகையை அமைக்க முடியவில்லை"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"கைரேகைக்கான நேரம் முடிந்தது. மீண்டும் முயலவும்."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"கைரேகை செயல்பாடு ரத்துசெய்யப்பட்டது."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"பயனர், கைரேகை உறுதிப்படுத்துதலை ரத்துசெய்தார்."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"அதிகமான முயற்சிகள். பிறகு முயற்சிக்கவும்."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"பலமுறை முயன்றுவிட்டீர்கள். இதற்குப் பதிலாகத் திரைப்பூட்டைப் பயன்படுத்தவும்."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"மீண்டும் முயற்சிக்கவும்."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"கைரேகைப் பதிவுகள் எதுவும் இல்லை."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"இந்தச் சாதனத்தில் கைரேகை சென்சார் இல்லை."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"சென்சார் தற்காலிகமாக முடக்கப்பட்டுள்ளது."</string> @@ -638,7 +643,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"பழுதுபார்ப்புச் சேவை வழங்குநரைத் தொடர்புகொள்ளவும்."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"முகத் தோற்றம் பதிவாகவில்லை. மீண்டும் முயலவும்."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"அதிக ஒளிர்வு. மிதமான ஒளியில் முயலவும்."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"பிரகாசமான ஒளியில் முயலவும்"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"மொபைலை முகத்தில் இருந்து தள்ளிப் பிடிக்கவும்"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"மொபைலை அருகில் நகர்த்தவும்"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"மொபைலை மேலே நகர்த்தவும்"</string> @@ -1251,8 +1257,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"ஆப்ஸ் தொடங்கப்படுகின்றன."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"துவக்குதலை முடிக்கிறது."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"நீங்கள் பவர் பட்டனை அழுத்தியுள்ளீர்கள் — வழக்கமாக இது திரையை ஆஃப் செய்யும்.\n\nஉங்கள் கைரேகையை அமைக்கும்போது மெதுவாகத் தொடுங்கள்."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"திரையை அணைக்க தட்டவும்"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"திரையை அணை"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"கைரேகைச் சரிபார்ப்பைத் தொடரவா?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"நீங்கள் பவர் பட்டனை அழுத்தியுள்ளீர்கள் — வழக்கமாக இது திரையை ஆஃப் செய்யும்.\n\nஉங்கள் கைரேகையைச் சரிபார்க்க மெதுவாகத் தொடுங்கள்."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"திரையை ஆஃப் செய்"</string> diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml index 257959fd1ee8..05ad50016bf4 100644 --- a/core/res/res/values-te/strings.xml +++ b/core/res/res/values-te/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"స్క్రీన్ లాక్ను ఉపయోగించండి"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"కొనసాగించడానికి మీ స్క్రీన్ లాక్ను ఎంటర్ చేయండి"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"సెన్సార్ మీద గట్టిగా నొక్కండి"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"వేలిముద్రను ప్రాసెస్ చేయడం సాధ్యపడలేదు. దయచేసి మళ్లీ ప్రయత్నించండి."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"వేలిముద్ర సెన్సార్ను క్లీన్ చేసి, మళ్లీ ట్రై చేయండి"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"సెన్సార్ను క్లీన్ చేసి, మళ్లీ ట్రై చేయండి"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"సెన్సార్ మీద గట్టిగా నొక్కండి"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"వేలిని చాలా నెమ్మదిగా కదిలించారు. దయచేసి మళ్లీ ప్రయత్నించండి."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"మరొక వేలిముద్రను ట్రై చేయండి"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"వెలుతురు అధికంగా ఉంది"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"సర్దుబాటు చేయడానికి ట్రై చేయండి"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"ప్రతిసారీ మీ వేళ్ల స్థానాన్ని కొద్దిగా మార్చండి"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"ముఖం ప్రమాణీకరించబడింది, దయచేసి ధృవీకరించును నొక్కండి"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"వేలిముద్ర హార్డ్వేర్ అందుబాటులో లేదు."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"వేలిముద్రను సెటప్ చేయడం సాధ్యం కాదు"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"వేలిముద్ర గడువు సమయం చేరుకుంది. మళ్లీ ప్రయత్నించండి."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"వేలిముద్ర యాక్టివిటీ రద్దయింది."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"వేలిముద్ర చర్యని వినియోగదారు రద్దు చేశారు."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"చాలా ఎక్కువ ప్రయత్నాలు చేశారు. తర్వాత మళ్లీ ప్రయత్నించండి."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"చాలా ఎక్కువ సార్లు ప్రయత్నించారు. బదులుగా స్క్రీన్ లాక్ను ఉపయోగించండి."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"మళ్లీ ప్రయత్నించండి."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"వేలిముద్రలు నమోదు చేయబడలేదు."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"ఈ పరికరంలో వేలిముద్ర సెన్సార్ ఎంపిక లేదు."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"సెన్సార్ తాత్కాలికంగా డిజేబుల్ చేయబడింది."</string> @@ -638,7 +643,7 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"రిపెయిర్ ప్రొవైడర్ను సందర్శించండి."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"మీ ఫేస్మోడల్ క్రియేషన్ కుదరదు. మళ్లీ ట్రై చేయండి."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"వెలుతురు అధికంగా ఉంది. తక్కువ ఉండేలా చూడండి."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"ప్రకాశవంతమైన లైటింగ్లో ట్రై చేయండి"</string> + <string name="face_acquired_too_dark" msgid="8539853432479385326">"తగిన కాంతి లేదు"</string> <string name="face_acquired_too_close" msgid="4453646176196302462">"ఫోన్ను కాస్త దూరంగా జరపండి"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"ఫోన్ను దగ్గరగా పట్టుకోండి"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"ఫోన్ను పైకి పట్టుకోండి"</string> @@ -1251,8 +1256,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"యాప్లను ప్రారంభిస్తోంది."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"బూట్ను ముగిస్తోంది."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"మీరు పవర్ బటన్ను నొక్కారు — ఇది సాధారణంగా స్క్రీన్ను ఆఫ్ చేస్తుంది.\n\nమీ వేలిముద్రను సెటప్ చేస్తున్నప్పుడు తేలికగా ట్యాప్ చేయడానికి ట్రై చేయండి."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"స్క్రీన్ను ఆఫ్ చేయడానికి ట్యాప్ చేయండి"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"స్క్రీన్ను ఆఫ్ చేయి"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"మీ వేలిముద్ర వెరిఫైను కొనసాగించాలా?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"మీరు పవర్ బటన్ను నొక్కారు — ఇది సాధారణంగా స్క్రీన్ను ఆఫ్ చేస్తుంది.\n\nమీ వేలిముద్రను వెరిఫై చేయడానికి తేలికగా ట్యాప్ చేయడం ట్రై చేయండి."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"స్క్రీన్ను ఆఫ్ చేయి"</string> diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml index c5bdaa9b60d3..551bbb75b364 100644 --- a/core/res/res/values-th/strings.xml +++ b/core/res/res/values-th/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"ใช้การล็อกหน้าจอ"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"ป้อนข้อมูลการล็อกหน้าจอเพื่อดำเนินการต่อ"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"กดเซ็นเซอร์ให้แน่น"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"ประมวลผลลายนิ้วมือไม่ได้ โปรดลองอีกครั้ง"</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"ทำความสะอาดเซ็นเซอร์ลายนิ้วมือแล้วลองอีกครั้ง"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"ทำความสะอาดเซ็นเซอร์แล้วลองอีกครั้ง"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"กดเซ็นเซอร์ให้แน่น"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"นิ้วเคลื่อนที่ช้าเกินไป โปรดลองอีกครั้ง"</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"ลองลายนิ้วมืออื่น"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"สว่างเกินไป"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"ลองปรับการวางนิ้ว"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"เปลี่ยนตำแหน่งของนิ้วเล็กน้อยไปเรื่อยๆ ทุกครั้ง"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"ตรวจสอบสิทธิ์ใบหน้าแล้ว โปรดกดยืนยัน"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"ฮาร์ดแวร์ลายนิ้วมือไม่พร้อมใช้งาน"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"ตั้งค่าลายนิ้วมือไม่ได้"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"หมดเวลาใช้ลายนิ้วมือแล้ว โปรดลองอีกครั้ง"</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"ยกเลิกการทำงานของลายนิ้วมือ"</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"ผู้ใช้ยกเลิกการทำงานของลายนิ้วมือ"</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"ดำเนินการหลายครั้งเกินไป ลองอีกครั้งในภายหลัง"</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"ลองหลายครั้งเกินไป ใช้การล็อกหน้าจอแทน"</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"ลองอีกครั้ง"</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"ไม่มีลายนิ้วมือที่ลงทะเบียน"</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"อุปกรณ์นี้ไม่มีเซ็นเซอร์ลายนิ้วมือ"</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"ปิดใช้เซ็นเซอร์ชั่วคราวแล้ว"</string> @@ -638,7 +643,7 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"โปรดติดต่อผู้ให้บริการซ่อม"</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"สร้างรูปแบบใบหน้าไม่ได้ โปรดลองอีกครั้ง"</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"สว่างเกินไป ลองหาตำแหน่งที่แสงน้อยกว่านี้"</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"ลองหาตำแหน่งที่สว่างขึ้น"</string> + <string name="face_acquired_too_dark" msgid="8539853432479385326">"แสงสว่างไม่เพียงพอ"</string> <string name="face_acquired_too_close" msgid="4453646176196302462">"ถือโทรศัพท์ให้ห่างกว่านี้"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"ถือโทรศัพท์ให้ใกล้กว่านี้"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"ยกโทรศัพท์ให้สูงขึ้น"</string> @@ -1251,8 +1256,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"กำลังเริ่มต้นแอปพลิเคชัน"</string> <string name="android_upgrading_complete" msgid="409800058018374746">"เสร็จสิ้นการบูต"</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"คุณกดปุ่มเปิด/ปิดซึ่งโดยปกติจะเป็นการปิดหน้าจอ\n\nลองแตะเบาๆ ขณะตั้งค่าลายนิ้วมือ"</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"แตะเพื่อปิดหน้าจอ"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"ปิดหน้าจอ"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"ยืนยันลายนิ้วมือต่อไหม"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"คุณกดปุ่มเปิด/ปิดซึ่งโดยปกติจะเป็นการปิดหน้าจอ\n\nลองแตะเบาๆ เพื่อยืนยันลายนิ้วมือ"</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"ปิดหน้าจอ"</string> diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml index 517294059a75..c9dfed29937b 100644 --- a/core/res/res/values-tl/strings.xml +++ b/core/res/res/values-tl/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Gumamit ng lock ng screen"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Ilagay ang iyong lock ng screen para magpatuloy"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Pumindot nang madiin sa sensor"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Hindi maproseso ang fingerprint. Pakisubukan ulit."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Linisin ang sensor para sa fingerprint at subukan ulit"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Linisin ang sensor at subukan ulit"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Pumindot nang madiin sa sensor"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Masyadong mabagal ang paggalaw ng daliri. Pakisubukan ulit."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Sumubok ng ibang fingerprint"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Masyadong maliwanag"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Subukang isaayos"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Bahagyang baguhin ang posisyon ng iyong daliri sa bawat pagkakataon"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Na-authenticate ang mukha, pakipindot ang kumpirmahin"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Hindi available ang hardware na ginagamitan ng fingerprint."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Hindi ma-set up ang fingerprint"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Nag-time out ang fingerprint. Subukang muli."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Nakansela ang operasyong ginagamitan ng fingerprint."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Kinansela ng user ang operasyon sa fingerprint."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Napakaraming pagtatangka. Subukan ulit sa ibang pagkakataon."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Masyadong maraming pagsubok. Gamitin na lang ang lock ng screen."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Subukang muli."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Walang naka-enroll na fingerprint."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Walang sensor ng fingerprint ang device na ito."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Pansamantalang na-disable ang sensor."</string> @@ -638,7 +643,7 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Bumisita sa provider ng pag-aayos."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"Hindi magawa ang iyong face model. Subukan ulit."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Masyadong maliwanag. Subukang bawasan ang liwanag."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Subukan sa mas maliwanag"</string> + <string name="face_acquired_too_dark" msgid="8539853432479385326">"Hindi sapat ang liwanag"</string> <string name="face_acquired_too_close" msgid="4453646176196302462">"Ilayo pa ang telepono"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Ilapit pa ang telepono"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Itaas pa ang telepono"</string> @@ -1251,8 +1256,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Sinisimulan ang apps."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"Pagtatapos ng pag-boot."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Pinindot mo ang power button — karaniwan nitong ino-off ang screen.\n\nSubukang i-tap habang sine-set up ang iyong fingerprint."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Mag-tap para i-off ang screen"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"I-off ang screen"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"Magpatuloy sa pag-verify ng fingerprint?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"Pinindot mo ang power button — karaniwan nitong ino-off ang screen.\n\nSubukang i-tap para i-verify ang iyong fingerprint."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"I-off ang screen"</string> diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml index 472c453849d8..ee568bfa119e 100644 --- a/core/res/res/values-tr/strings.xml +++ b/core/res/res/values-tr/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Ekran kilidi kullan"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Devam etmek için ekran kilidinizi girin"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Sensöre sıkıca bastırın"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Parmak izi işlenemedi. Lütfen tekrar deneyin."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Parmak izi sensörünü temizleyip tekrar deneyin"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Sensörü temizleyip tekrar deneyin"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Sensöre sıkıca bastırın"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Parmak hareketi çok yavaştı. Lütfen tekrar deneyin."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Başka bir parmak izi deneyin"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Çok parlak"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Ayarlamayı deneyin"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Her defasında parmağınızın konumunu biraz değiştirin"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Yüz kimliği doğrulandı, lütfen onayla\'ya basın"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Parmak izi donanımı kullanılamıyor."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Parmak izi ayarlanamıyor"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Parmak izi için zaman aşımı oluştu. Tekrar deneyin."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Parmak izi işlemi iptal edildi."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Parmak izi işlemi kullanıcı tarafından iptal edildi."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Çok fazla deneme yapıldı. Daha sonra tekrar deneyin."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Çok fazla deneme yapıldı. Bunun yerine ekran kilidini kullanın."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Tekrar deneyin."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Parmak izi kaydedilmedi."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Bu cihazda parmak izi sensörü yok."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Sensör geçici olarak devre dışı bırakıldı."</string> @@ -638,7 +643,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Bir onarım hizmeti sağlayıcıyı ziyaret edin."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"Yüzünüzün modeli oluşturulamıyor. Tekrar deneyin."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Çok parlak. Parlaklığı daha az bir ışıklandırma deneyin."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Daha parlak ışıkta deneyin"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"Telefonu uzaklaştırın"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Telefonu yaklaştırın"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Telefonu daha yukarı kaldırın"</string> @@ -1251,8 +1257,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Uygulamalar başlatılıyor"</string> <string name="android_upgrading_complete" msgid="409800058018374746">"Açılış tamamlanıyor."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Güç düğmesine bastınız. Bu düğmeye basıldığında genellikle ekran kapanır.\n\nParmak izinizi tanımlarken hafifçe dokunmayı deneyin."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Ekranı kapatmak için dokunun"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Ekranı kapat"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"Parmak izi doğrulamaya devam edilsin mi?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"Güç düğmesine bastınız. Bu düğmeye basıldığında genellikle ekran kapanır.\n\nParmak izinizi doğrulamak için hafifçe dokunmayı deneyin."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Ekranı kapat"</string> diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml index 98c9412c6896..2c87e186399c 100644 --- a/core/res/res/values-uk/strings.xml +++ b/core/res/res/values-uk/strings.xml @@ -588,13 +588,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Доступ розблокуванням екрана"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Щоб продовжити, введіть дані для розблокування екрана"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Міцно притисніть палець до сканера"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Не вдалось обробити відбиток пальця. Повторіть спробу."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Очистьте сканер відбитків пальців і повторіть спробу"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Очистьте сканер і повторіть спробу"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Міцно притисніть палець до сканера"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Ви провели пальцем надто повільно. Повторіть спробу."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Спробуйте інший відбиток пальця"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Надто яскраво"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Спробуйте відкоригувати відбиток пальця"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Щоразу трохи змінюйте положення пальця"</string> <string-array name="fingerprint_acquired_vendor"> @@ -606,13 +609,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Обличчя автентифіковано. Натисніть \"Підтвердити\""</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Сканер відбитків пальців недоступний."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Не вдалося створити відбиток пальця"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Час очікування відбитка пальця минув. Повторіть спробу."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Дію з відбитком пальця скасовано."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Користувач скасував дію з відбитком пальця."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Забагато спроб. Спробуйте пізніше."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Забагато спроб. Використайте натомість розблокування екрана."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Повторіть спробу."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Відбитки пальців не зареєстровано."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"На цьому пристрої немає сканера відбитків пальців."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Датчик тимчасово вимкнено."</string> @@ -640,7 +645,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Зверніться до постачальника послуг із ремонту."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"Модель обличчя не створено. Повторіть спробу."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Занадто яскраво. Потрібно менше світла."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Потрібно більше світла"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"Тримайте телефон далі від обличчя"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Тримайте телефон ближче до обличчя"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Підніміть телефон вище"</string> @@ -1253,8 +1259,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Запуск програм."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"Завершення завантаження."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Ви натиснули кнопку живлення – зазвичай після цього вимикається екран.\n\nЩоб зареєструвати відбиток пальця, спробуйте лише злегка торкнутися датчика."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Натисніть, щоб вимкнути екран"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Вимкнути екран"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"Продовжити підтвердження відбитка?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"Ви натиснули кнопку живлення – зазвичай після цього вимикається екран.\n\nЩоб підтвердити відбиток пальця, спробуйте лише злегка торкнутися датчика."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Вимкнути екран"</string> diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml index 92cefcde2f9d..07ce4cfe97e2 100644 --- a/core/res/res/values-ur/strings.xml +++ b/core/res/res/values-ur/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"اسکرین لاک استعمال کریں"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"جاری رکھنے کے لیے اپنا اسکرین لاک درج کریں"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"سینسر پر اچھی طرح دبائیں"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"فنگر پرنٹ پر کارروائی نہیں کی جا سکی۔ براہ کرم دوبارہ کوشش کریں۔"</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"فنگر پرنٹ سینسر صاف کریں اور دوبارہ کوشش کریں"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"سینسر صاف کریں اور دوبارہ کوشش کریں"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"سینسر پر اچھی طرح دبائیں"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"انگلی کو بہت آہستہ ہٹایا گیا۔ براہ کرم دوبارہ کوشش کریں۔"</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"دوسرا فنگر پرنٹ آزمائیں"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"کافی روشنی ہے"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"ایڈجسٹ کرنے کی کوشش کریں"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"ہر بار اپنی انگلی کی پوزیشن کو تھوڑا تبدیل کریں"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"چہرے کی تصدیق ہو گئی، براہ کرم \'تصدیق کریں\' کو دبائيں"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"فنگر پرنٹ ہارڈ ویئر دستیاب نہیں ہے۔"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"فنگر پرنٹ کو سیٹ اپ نہیں کیا جا سکا"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"فنگر پرنٹ کی میعاد ختم ہوگئی۔ دوبارہ کوشش کریں۔"</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"فنگر پرنٹ کی کارروائی منسوخ ہوگئی۔"</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"صارف نے فنگر پرنٹ کی کارروائی منسوخ کر دی۔"</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"کافی زیادہ کوششیں کی گئیں۔ بعد میں دوبارہ کوشش کریں۔"</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"کافی زیادہ کوششیں۔ اس کے بجائے اسکرین لاک کا استعمال کریں۔"</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"دوبارہ کوشش کریں۔"</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"کوئی فنگر پرنٹ مندرج شدہ نہیں ہے۔"</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"اس آلہ میں فنگر پرنٹ سینسر نہیں ہے۔"</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"سینسر عارضی طور غیر فعال ہے۔"</string> @@ -638,7 +643,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"ایک مرمت فراہم کنندہ کو ملاحظہ کریں۔"</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"آپکے چہرے کا ماڈل تخلیق نہیں ہو سکا۔ پھر کوشش کریں۔"</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"کافی روشنی ہے۔ ہلکی روشنی میں آزمائیں۔"</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"تیز روشنی میں آزمائیں"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"فون کو تھوڑا دور کریں"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"فون کو تھوڑا قریب کریں"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"فون کو تھوڑا اوپر لے جائیں"</string> @@ -1251,8 +1257,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"ایپس شروع ہو رہی ہیں۔"</string> <string name="android_upgrading_complete" msgid="409800058018374746">"بوٹ مکمل ہو رہا ہے۔"</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"آپ نے پاور بٹن دبایا — اس سے عام طور پر اسکرین آف ہو جاتی ہے۔\n\nاپنے فنگر پرنٹ کو سیٹ اپ کرنے کے دوران ہلکا سا تھپتھپانے کی کوشش کریں۔"</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"اسکرین آف کرنے کیلئے تھپتھپائیں"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"اسکرین آف کریں"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"اپنے فنگر پرنٹ کی توثیق کرنا جاری رکھیں؟"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"آپ نے پاور بٹن دبایا — اس سے عام طور پر اسکرین آف ہو جاتی ہے۔\n\nاپنے فنگر پرنٹ کی توثیق کرنے کے لیے ہلکا سا تھپتھپانے کی کوشش کریں۔"</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"اسکرین آف کریں"</string> diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml index a260f84946c5..b56510010bc8 100644 --- a/core/res/res/values-uz/strings.xml +++ b/core/res/res/values-uz/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Ekran qulfi"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Ekran qulfini kiritish bilan davom eting"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Sensorni mahkam bosing"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Barmoq izi aniqlanmadi. Qaytadan urining."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Barmoq izi skanerini tozalang va qayta urining"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Sensorni tozalang va qayta urining"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Sensorni mahkam bosing"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Barmoq juda sekin harakatlandi. Qayta urinib ko‘ring."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Boshqa barmoq izi bilan urining"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Juda yorqin"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Moslashga urining"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Barmoqni har safar biroz surib joylang"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Yuzingiz aniqlandi, tasdiqlash uchun bosing"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Barmoq izi skaneri ish holatida emas."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Barmoq izi sozlanmadi"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Barmoq izini aniqlash vaqti tugab qoldi. Qayta urinib ko‘ring."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Barmoq izi tekshiruvi bekor qilindi."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Barmoq izi amali foydalanuvchi tomonidan bekor qilindi"</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Urinishlar soni ko‘payib ketdi. Keyinroq qayta urinib ko‘ring."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Juda koʻp urinildi. Ekran qulfi orqali urining."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Qayta urinib ko‘ring."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Hech qanday barmoq izi qayd qilinmagan."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Bu qurilmada barmoq izi skaneri mavjud emas."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Sensor vaqtincha faol emas."</string> @@ -638,7 +643,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Xizmat koʻrsatish markaziga murojaat qiling."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"Yuzingiz modeli yaratilmadi. Qayta urining."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Juda yorqin. Biroz soyaroq joy tanlang."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Atrofingizni yanada yoriting"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"Telefonni biroz uzoqroq tuting"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Telefonni yaqinroq tuting"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Telefonni teparoq tuting"</string> @@ -1251,8 +1257,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Ilovalar ishga tushirilmoqda."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"Tizimni yuklashni tugatish."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Quvvat tugmasini bosdingiz — bu odatda ekranni oʻchiradi.\n\nBarmoq izini qoʻshish vaqtida tugmaga yengilgina tegining."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Ekranni oʻchirish uchun bosing"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Ekranni oʻchirish"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"Barmoq izi tasdiqlashda davom etilsinmi?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"Quvvat tugmasini bosdingiz. Bu odatda ekranni oʻchiradi.\n\nBarmoq izingizni tasdiqlash uchun tugmaga yengilgina tegining."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Ekranni oʻchirish"</string> diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml index 7d166677a3fa..18352e368f0e 100644 --- a/core/res/res/values-vi/strings.xml +++ b/core/res/res/values-vi/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Dùng phương thức khóa màn hình"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Hãy nhập phương thức khóa màn hình của bạn để tiếp tục"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Nhấn chắc trên cảm biến"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Không thể xử lý vân tay. Vui lòng thử lại."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Hãy vệ sinh cảm biến vân tay rồi thử lại"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Vệ sinh cảm biến rồi thử lại"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Nhấn chắc trên cảm biến"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Di chuyển ngón tay quá chậm. Vui lòng thử lại."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Hãy thử một vân tay khác"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Quá sáng"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Hãy thử điều chỉnh"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Mỗi lần, hãy thay đổi vị trí ngón tay một chút"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Đã xác thực khuôn mặt, vui lòng nhấn để xác nhận"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Phần cứng vân tay không khả dụng."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Không thể thiết lập vân tay"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Đã hết thời gian chờ vân tay. Hãy thử lại."</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Thao tác dùng dấu vân tay bị hủy."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Người dùng đã hủy thao tác dùng dấu vân tay."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Quá nhiều lần thử. Hãy thử lại sau."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Bạn đã thử quá nhiều lần. Hãy dùng phương thức khoá màn hình."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Thử lại."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Chưa đăng ký vân tay."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Thiết bị này không có cảm biến vân tay."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Đã tạm thời tắt cảm biến."</string> @@ -638,7 +643,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Hãy liên hệ với một nhà cung cấp dịch vụ sửa chữa."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"Không thể tạo mẫu khuôn mặt của bạn. Hãy thử lại."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Quá sáng. Hãy thử giảm độ sáng."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Hãy thử tăng độ sáng"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"Đưa điện thoại ra xa hơn"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Đưa điện thoại lại gần hơn"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Nâng điện thoại lên cao hơn"</string> @@ -1251,8 +1257,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Khởi động ứng dụng."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"Hoàn tất khởi động."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Bạn đã nhấn nút nguồn – thao tác này thường tắt màn hình.\n\nHãy thử nhấn nhẹ khi thiết lập vân tay của bạn."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Nhấn để tắt màn hình"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Tắt màn hình"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"Tiếp tục xác minh vân tay của bạn?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"Bạn đã nhấn nút nguồn – thao tác này thường tắt màn hình.\n\nHãy thử nhấn nhẹ để xác minh vân tay."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Tắt màn hình"</string> diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml index 169bdb31b943..0107c29d41a8 100644 --- a/core/res/res/values-zh-rCN/strings.xml +++ b/core/res/res/values-zh-rCN/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"使用屏幕锁定凭据"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"输入您的屏幕锁定凭据才能继续"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"请用力按住传感器"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"无法处理指纹,请重试。"</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"请清洁指纹传感器,然后重试"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"请清洁传感器,然后重试"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"请用力按住传感器"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"手指移动太慢,请重试。"</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"请试试其他指纹"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"光线太亮"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"请尝试调整指纹"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"请在每次放手指时略微更改手指的位置"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"面孔已验证,请按确认按钮"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"指纹硬件无法使用。"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"无法设置指纹"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"指纹录入操作超时,请重试。"</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"指纹操作已取消。"</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"用户取消了指纹操作。"</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"尝试次数过多,请稍后重试。"</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"尝试次数过多,请通过屏幕锁定功能解锁。"</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"请重试。"</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"未注册任何指纹。"</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"此设备没有指纹传感器。"</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"传感器已暂时停用。"</string> @@ -638,7 +643,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"请联系维修服务提供商。"</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"无法创建您的脸部模型,请重试。"</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"亮度过高,请尝试使用较柔和的亮度。"</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"请尝试调亮光线"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"请将手机拿远一点"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"请将手机拿近一点"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"请将手机举高一点"</string> @@ -1251,8 +1257,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"正在启动应用。"</string> <string name="android_upgrading_complete" msgid="409800058018374746">"即将完成启动。"</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"您已按电源按钮,这通常会关闭屏幕。\n\n请尝试在设置指纹时轻轻按一下。"</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"按一下即可关闭屏幕"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"关闭屏幕"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"要继续验证您的指纹吗?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"您已按电源按钮,这通常会关闭屏幕。\n\n请尝试轻轻按一下来验证您的指纹。"</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"关闭屏幕"</string> diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml index eaa19d9973be..c78403920d47 100644 --- a/core/res/res/values-zh-rHK/strings.xml +++ b/core/res/res/values-zh-rHK/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"使用螢幕鎖定"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"如要繼續操作,請輸入螢幕鎖定解鎖憑證"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"請用力按住感應器"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"無法處理指紋。請再試一次。"</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"請清潔指紋感應器,然後再試一次"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"請清潔感應器,然後再試一次"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"請用力按住感應器"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"手指移動太慢,請重試。"</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"改用其他指紋"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"太亮"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"嘗試調整"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"每次掃瞄時請稍微變更手指的位置"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"面孔已經驗證,請㩒一下 [確認]"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"無法使用指紋軟件。"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"無法設定指紋"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"指紋已逾時。請再試一次。"</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"指紋操作已取消。"</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"使用者已取消指紋操作。"</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"嘗試次數過多,請稍後再試。"</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"嘗試次數過多,請改用螢幕鎖定功能。"</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"再試一次。"</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"未註冊任何指紋"</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"此裝置沒有指紋感應器。"</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"感應器已暫時停用。"</string> @@ -638,7 +643,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"請諮詢維修服務供應商。"</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"無法建立面部模型,請再試一次。"</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"影像太亮。請嘗試在更暗的環境下使用。"</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"請試用更充足的光線"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"請將手機移開一點"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"請將手機移近一點"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"請將手機向上移"</string> @@ -1251,8 +1257,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"正在啟動應用程式。"</string> <string name="android_upgrading_complete" msgid="409800058018374746">"啟動完成。"</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"您已按下開關按鈕,這麼做通常會關閉螢幕。\n\n設定指紋時請嘗試輕按開關按鈕。"</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"輕按即可關閉螢幕"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"關閉螢幕"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"要繼續驗證指紋嗎?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"您已按下開關按鈕,這麼做通常會關閉螢幕。\n\n嘗試輕按開關按鈕以驗證指紋。"</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"關閉螢幕"</string> diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml index 753b4b60fdc5..0f0cf7711e13 100644 --- a/core/res/res/values-zh-rTW/strings.xml +++ b/core/res/res/values-zh-rTW/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"使用螢幕鎖定功能"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"如要繼續操作,請輸入螢幕鎖定憑證"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"請確實按住感應器"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"無法處理指紋,請再試一次。"</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"請清潔指紋感應器,然後再試一次"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"清潔感應器,然後再試一次"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"請確實按住感應器"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"手指移動速度過慢,請再試一次。"</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"改用其他指紋"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"太亮"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"請試著調整"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"每次掃描時請稍微改變手指的位置"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"臉孔驗證成功,請按下 [確認] 按鈕"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"指紋硬體無法使用。"</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"無法設定指紋"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"指紋處理作業逾時,請再試一次。"</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"指紋作業已取消。"</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"使用者已取消指紋驗證作業。"</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"嘗試次數過多,請稍後再試。"</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"嘗試次數過多,請改用螢幕鎖定功能。"</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"請再試一次。"</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"未登錄任何指紋。"</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"這個裝置沒有指紋感應器。"</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"感應器已暫時停用。"</string> @@ -638,7 +643,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"請洽詢維修供應商。"</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"無法建立臉部模型,請再試一次。"</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"亮度過高,請嘗試使用較柔和的照明方式。"</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"請採用更明亮的光源"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"請將手機拿遠一點"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"請將手機拿近一點"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"請將手機舉高一點"</string> @@ -1251,8 +1257,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"正在啟動應用程式。"</string> <string name="android_upgrading_complete" msgid="409800058018374746">"啟動完成。"</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"你已按下電源鍵,這麼做通常會關閉螢幕。\n\n設定指紋時請試著減輕觸碰電源鍵的力道。"</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"輕觸即可關閉螢幕"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"關閉螢幕"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"要繼續驗證指紋嗎?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"你已按下電源鍵,這麼做通常會關閉螢幕。\n\n驗證指紋時,請試著減輕觸碰電源鍵的力道。"</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"關閉螢幕"</string> diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml index ac137fb33825..d3cd1d4064a2 100644 --- a/core/res/res/values-zu/strings.xml +++ b/core/res/res/values-zu/strings.xml @@ -586,13 +586,16 @@ <string name="screen_lock_app_setting_name" msgid="6054944352976789228">"Sebenzisa isikhiya sesikrini"</string> <string name="screen_lock_dialog_default_subtitle" msgid="120359538048533695">"Faka ukukhiya isikrini kwakho ukuze uqhubeke"</string> <string name="fingerprint_acquired_partial" msgid="4323789264604479684">"Cindezela ngokuqinile kunzwa"</string> - <string name="fingerprint_acquired_insufficient" msgid="2545149524031515411">"Ayikwazanga ukucubungula izigxivizo zeminwe. Sicela uzame futhi."</string> + <!-- no translation found for fingerprint_acquired_insufficient (623888149088216458) --> + <skip /> <string name="fingerprint_acquired_imager_dirty" msgid="1770676120848224250">"Hlanza inzwa yesigxivizo somunwe bese uzame futhi"</string> <string name="fingerprint_acquired_imager_dirty_alt" msgid="9169582140486372897">"Hlanza inzwa bese uzame futhi"</string> <string name="fingerprint_acquired_too_fast" msgid="1628459767349116104">"Cindezela ngokuqinile kunzwa"</string> <string name="fingerprint_acquired_too_slow" msgid="6683510291554497580">"Umnwe uhanjiswe kancane kakhulu. Sicela uzame futhi."</string> <string name="fingerprint_acquired_already_enrolled" msgid="2285166003936206785">"Zama ezinye izigxivizo zeminwe"</string> <string name="fingerprint_acquired_too_bright" msgid="3863560181670915607">"Kukhanya kakhulu"</string> + <!-- no translation found for fingerprint_acquired_power_press (3107864151278434961) --> + <skip /> <string name="fingerprint_acquired_try_adjusting" msgid="3667006071003809364">"Zama ukulungisa"</string> <string name="fingerprint_acquired_immobile" msgid="1621891895241888048">"Shintsha indawo yomunwe wakho kancane isikhathi ngasinye"</string> <string-array name="fingerprint_acquired_vendor"> @@ -604,13 +607,15 @@ <string name="face_authenticated_confirmation_required" msgid="6872632732508013755">"Ukuqinisekiswa kobuso, sicela ucindezele okuthi qinisekisa"</string> <string name="fingerprint_error_hw_not_available" msgid="4571700896929561202">"Izingxenyekazi zekhompuyutha zezigxivizo zeminwe azitholakali."</string> <string name="fingerprint_error_no_space" msgid="7285481581905967580">"Ayikwazi ukusetha izigxivizo zeminwe"</string> - <string name="fingerprint_error_timeout" msgid="2946635815726054226">"Kufinyelelwe isikhathi sokuvala sezigxivizo zeminwe. Zama futhi"</string> + <!-- no translation found for fingerprint_error_timeout (7361192266621252164) --> + <skip /> <string name="fingerprint_error_canceled" msgid="540026881380070750">"Ukusebenza kwezigxivizo zeminwe kukhanseliwe."</string> <string name="fingerprint_error_user_canceled" msgid="7685676229281231614">"Umsebenzi wezigxivizo zomunwe ukhanselwe umsebenzisi."</string> - <string name="fingerprint_error_lockout" msgid="7853461265604738671">"Imizamo eminingi kakhulu. Zama futhi emuva kwesikhathi."</string> - <!-- no translation found for fingerprint_error_lockout_permanent (9060651300306264843) --> + <!-- no translation found for fingerprint_error_lockout (6626753679019351368) --> + <skip /> + <string name="fingerprint_error_lockout_permanent" msgid="9060651300306264843">"Imizamo eminingi kakhulu. Sebenzisa ukukhiya isikrini kunalokho."</string> + <!-- no translation found for fingerprint_error_unable_to_process (2446280592818621224) --> <skip /> - <string name="fingerprint_error_unable_to_process" msgid="1148553603490048742">"Zama futhi."</string> <string name="fingerprint_error_no_fingerprints" msgid="8671811719699072411">"Azikho izigxivizo zeminwe ezibhalisiwe."</string> <string name="fingerprint_error_hw_not_present" msgid="578914350967423382">"Le divayisi ayinayo inzwa yezigxivizo zeminwe."</string> <string name="fingerprint_error_security_update_required" msgid="7750187320640856433">"Inzwa ikhutshazwe okwesikhashana."</string> @@ -638,7 +643,8 @@ <string name="fingerprint_recalibrate_notification_content" msgid="8519935717822194943">"Vakashela umhlinzeki wokulungisa."</string> <string name="face_acquired_insufficient" msgid="6889245852748492218">"Ayikwazi ukusungula imodeli yobuso bakho. Zama futhi."</string> <string name="face_acquired_too_bright" msgid="8070756048978079164">"Kukhanya kakhulu. Zama ukukhanya okuthambile."</string> - <string name="face_acquired_too_dark" msgid="7919016380747701228">"Zama ukukhanyisa okukhudlwana"</string> + <!-- no translation found for face_acquired_too_dark (8539853432479385326) --> + <skip /> <string name="face_acquired_too_close" msgid="4453646176196302462">"Yisa ifoni kude"</string> <string name="face_acquired_too_far" msgid="2922278214231064859">"Sondeza ifoni eduze"</string> <string name="face_acquired_too_high" msgid="8278815780046368576">"Yisa ifoni phezulu"</string> @@ -1251,8 +1257,10 @@ <string name="android_upgrading_starting_apps" msgid="6206161195076057075">"Qalisa izinhlelo zokusebenza."</string> <string name="android_upgrading_complete" msgid="409800058018374746">"Qedela ukuqala kabusha."</string> <string name="fp_power_button_enrollment_message" msgid="5648173517663246140">"Ucindezele inkinobho yamandla — lokhu kuvame ukuvala isikrini.\n\nZama ukuthepha kancane ngenkathi usetha isigxivizo sakho somunwe."</string> - <string name="fp_power_button_enrollment_title" msgid="8997641910928785172">"Thepha ukuze uvale isikrini"</string> - <string name="fp_power_button_enrollment_button_text" msgid="8351290204990805109">"Vala isikrini"</string> + <!-- no translation found for fp_power_button_enrollment_title (6976841690455338563) --> + <skip /> + <!-- no translation found for fp_power_button_enrollment_button_text (3199783266386029200) --> + <skip /> <string name="fp_power_button_bp_title" msgid="5585506104526820067">"Qhubeka uqinisekise isigxivizo sakho somunwe?"</string> <string name="fp_power_button_bp_message" msgid="2983163038168903393">"Ucindezele inkinobho yamandla — lokhu kuvame ukuvala isikrini.\n\nZama ukuthepha kancane ukuze uqinisekise isigxivizo sakho somunwe."</string> <string name="fp_power_button_bp_positive_button" msgid="728945472408552251">"Vala isikrini"</string> diff --git a/core/res/res/values/bools.xml b/core/res/res/values/bools.xml index 5fd9dc0ca798..988303ea7bc5 100644 --- a/core/res/res/values/bools.xml +++ b/core/res/res/values/bools.xml @@ -18,6 +18,7 @@ <bool name="kg_enable_camera_default_widget">true</bool> <bool name="kg_center_small_widgets_vertically">false</bool> <bool name="kg_top_align_page_shrink_on_bouncer_visible">true</bool> + <bool name="kg_wake_on_acquire_start">false</bool> <bool name="action_bar_embed_tabs">true</bool> <bool name="split_action_bar_is_narrow">true</bool> <bool name="preferences_prefer_dual_pane">false</bool> diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index d5f40e0eb259..c3b6df144544 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -1733,7 +1733,7 @@ <item name="default_lock_wallpaper" type="drawable">@null</item> <!-- Component name of the built in wallpaper used to display bitmap wallpapers. This must not be null. --> - <string name="image_wallpaper_component" translatable="false">com.android.systemui/com.android.systemui.ImageWallpaper</string> + <string name="image_wallpaper_component" translatable="false">com.android.systemui/com.android.systemui.wallpapers.ImageWallpaper</string> <!-- True if WallpaperService is enabled --> <bool name="config_enableWallpaperService">true</bool> diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index aad32b118b8f..6ec98e82211c 100644 --- a/core/res/res/values/strings.xml +++ b/core/res/res/values/strings.xml @@ -1696,7 +1696,7 @@ <!-- Message shown during fingerprint acquisision when the fingerprint cannot be recognized --> <string name="fingerprint_acquired_partial">Press firmly on the sensor</string> <!-- Message shown during fingerprint acquisision when the fingerprint cannot be recognized --> - <string name="fingerprint_acquired_insufficient">Couldn\'t process fingerprint. Please try again.</string> + <string name="fingerprint_acquired_insufficient">Can\u2019t recognize fingerprint. Try again.</string> <!-- Message shown during fingerprint acquisision when the fingerprint sensor needs cleaning --> <string name="fingerprint_acquired_imager_dirty">Clean fingerprint sensor and try again</string> <string name="fingerprint_acquired_imager_dirty_alt">Clean sensor and try again</string> @@ -1708,6 +1708,8 @@ <string name="fingerprint_acquired_already_enrolled">Try another fingerprint</string> <!-- Message shown during fingerprint acquisition when fingerprint sensor detected too much light.[CHAR LIMIT=50] --> <string name="fingerprint_acquired_too_bright">Too bright</string> + <!-- Message shown during fingerprint acquisition when a Power press has been detected.[CHAR LIMIT=50] --> + <string name="fingerprint_acquired_power_press">Power press detected</string> <!-- Message shown during fingerprint acquisition when a fingerprint must be adjusted.[CHAR LIMIT=50] --> <string name="fingerprint_acquired_try_adjusting">Try adjusting</string> <!-- Message shown during fingerprint acquisition when a fingeprint area has already been captured during enrollment [CHAR LIMIT=100] --> @@ -1732,17 +1734,17 @@ <!-- Error message shown when the fingerprint hardware has run out of room for storing fingerprints --> <string name="fingerprint_error_no_space">Can\u2019t set up fingerprint</string> <!-- Error message shown when the fingerprint hardware timer has expired and the user needs to restart the operation. --> - <string name="fingerprint_error_timeout">Fingerprint time out reached. Try again.</string> + <string name="fingerprint_error_timeout">Fingerprint setup timed out. Try again.</string> <!-- Generic error message shown when the fingerprint operation (e.g. enrollment or authentication) is canceled. Generally not shown to the user--> <string name="fingerprint_error_canceled">Fingerprint operation canceled.</string> <!-- Generic error message shown when the fingerprint authentication operation is canceled due to user input. Generally not shown to the user --> <string name="fingerprint_error_user_canceled">Fingerprint operation canceled by user.</string> <!-- Generic error message shown when the fingerprint operation fails because too many attempts have been made. --> - <string name="fingerprint_error_lockout">Too many attempts. Try again later.</string> + <string name="fingerprint_error_lockout">Too many attempts. Use screen lock instead.</string> <!-- Generic error message shown when the fingerprint operation fails because strong authentication is required --> <string name="fingerprint_error_lockout_permanent">Too many attempts. Use screen lock instead.</string> <!-- Generic error message shown when the fingerprint hardware can't recognize the fingerprint --> - <string name="fingerprint_error_unable_to_process">Try again.</string> + <string name="fingerprint_error_unable_to_process">Can\u2019t process fingerprint. Try again.</string> <!-- Generic error message shown when the user has no enrolled fingerprints --> <string name="fingerprint_error_no_fingerprints">No fingerprints enrolled.</string> <!-- Generic error message shown when the app requests fingerprint authentication on a device without a sensor --> @@ -1804,7 +1806,7 @@ <!-- Message shown during face acquisition when the image is too bright [CHAR LIMIT=50] --> <string name="face_acquired_too_bright">Too bright. Try gentler lighting.</string> <!-- Message shown during face acquisition when the image is too dark [CHAR LIMIT=50] --> - <string name="face_acquired_too_dark">Try brighter lighting</string> + <string name="face_acquired_too_dark">Not enough light</string> <!-- Message shown during face acquisition when the user is too close to sensor [CHAR LIMIT=50] --> <string name="face_acquired_too_close">Move phone farther away</string> <!-- Message shown during face acquisition when the user is too far from sensor [CHAR LIMIT=50] --> @@ -3574,11 +3576,11 @@ <!-- [CHAR LIMIT=40] Title of dialog shown to confirm device going to sleep if the power button is pressed during fingerprint enrollment. --> - <string name="fp_power_button_enrollment_title">Tap to turn off screen</string> + <string name="fp_power_button_enrollment_title">To end setup, turn off screen</string> <!-- [CHAR LIMIT=20] Positive button of dialog shown to confirm device going to sleep if the power button is pressed during fingerprint enrollment. --> - <string name="fp_power_button_enrollment_button_text">Turn off screen</string> + <string name="fp_power_button_enrollment_button_text">Turn off</string> <!-- [CHAR LIMIT=40] Title of dialog shown to confirm device going to sleep if the power button is pressed during biometric prompt when a side fingerprint sensor is present. --> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index e773a9c706b0..6c6a0a3e3abd 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -2612,6 +2612,7 @@ <java-symbol type="string" name="fingerprint_acquired_imager_dirty" /> <java-symbol type="string" name="fingerprint_acquired_too_slow" /> <java-symbol type="string" name="fingerprint_acquired_too_fast" /> + <java-symbol type="string" name="fingerprint_acquired_power_press" /> <java-symbol type="string" name="fingerprint_acquired_too_bright" /> <java-symbol type="array" name="fingerprint_acquired_vendor" /> <java-symbol type="string" name="fingerprint_error_canceled" /> @@ -2831,6 +2832,7 @@ <java-symbol type="dimen" name="fast_scroller_minimum_touch_target" /> <java-symbol type="array" name="config_cdma_international_roaming_indicators" /> <java-symbol type="string" name="kg_text_message_separator" /> + <java-symbol type="bool" name="kg_wake_on_acquire_start" /> <java-symbol type="bool" name="config_use_sim_language_file" /> <java-symbol type="bool" name="config_LTE_eri_for_network_name" /> @@ -4279,6 +4281,7 @@ <java-symbol type="id" name="conversation_icon_badge_ring" /> <java-symbol type="id" name="conversation_icon_badge_bg" /> <java-symbol type="id" name="expand_button_container" /> + <java-symbol type="id" name="expand_button_a11y_container" /> <java-symbol type="id" name="expand_button_touch_container" /> <java-symbol type="id" name="messaging_group_content_container" /> <java-symbol type="id" name="expand_button_and_content_container" /> diff --git a/core/tests/coretests/src/android/app/NotificationChannelGroupTest.java b/core/tests/coretests/src/android/app/NotificationChannelGroupTest.java index 2a3da05eabb3..625c66a4c60e 100644 --- a/core/tests/coretests/src/android/app/NotificationChannelGroupTest.java +++ b/core/tests/coretests/src/android/app/NotificationChannelGroupTest.java @@ -17,9 +17,11 @@ package android.app; import static junit.framework.TestCase.assertEquals; +import static junit.framework.TestCase.assertTrue; import android.os.Parcel; import android.test.AndroidTestCase; +import android.text.TextUtils; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; @@ -70,4 +72,18 @@ public class NotificationChannelGroupTest { assertEquals(NotificationChannelGroup.MAX_TEXT_LENGTH, fromParcel.getDescription().length()); } + + @Test + public void testNullableFields() { + NotificationChannelGroup group = new NotificationChannelGroup("my_group_01", null); + + Parcel parcel = Parcel.obtain(); + group.writeToParcel(parcel, 0); + parcel.setDataPosition(0); + + NotificationChannelGroup fromParcel = + NotificationChannelGroup.CREATOR.createFromParcel(parcel); + assertEquals(group.getId(), fromParcel.getId()); + assertTrue(TextUtils.isEmpty(fromParcel.getName())); + } } diff --git a/core/tests/coretests/src/android/ddm/DdmHandleViewDebugTest.java b/core/tests/coretests/src/android/ddm/DdmHandleViewDebugTest.java new file mode 100644 index 000000000000..7248983c741c --- /dev/null +++ b/core/tests/coretests/src/android/ddm/DdmHandleViewDebugTest.java @@ -0,0 +1,398 @@ +/* + * 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 android.ddm; + +import static android.ddm.DdmHandleViewDebug.deserializeMethodParameters; +import static android.ddm.DdmHandleViewDebug.serializeReturnValue; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; + +import android.ddm.DdmHandleViewDebug.ViewMethodInvocationSerializationException; +import android.platform.test.annotations.Presubmit; + +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.filters.SmallTest; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.nio.BufferUnderflowException; +import java.nio.ByteBuffer; +import java.util.Arrays; + +@RunWith(AndroidJUnit4.class) +@SmallTest +@Presubmit +public final class DdmHandleViewDebugTest { + // true + private static final byte[] SERIALIZED_BOOLEAN_TRUE = {0x00, 0x5A, 1}; + + @Test + public void serializeReturnValue_booleanTrue() throws Exception { + assertArrayEquals(SERIALIZED_BOOLEAN_TRUE, serializeReturnValue(boolean.class, true)); + } + + @Test + public void deserializeMethodParameters_booleanTrue() throws Exception { + expectDeserializedArgument(boolean.class, true, SERIALIZED_BOOLEAN_TRUE); + } + + // false + private static final byte[] SERIALIZED_BOOLEAN_FALSE = {0x00, 0x5A, 0}; + + @Test + public void serializeReturnValue_booleanFalse() throws Exception { + assertArrayEquals(SERIALIZED_BOOLEAN_FALSE, serializeReturnValue(boolean.class, false)); + } + + @Test + public void deserializeMethodParameters_booleanFalse() throws Exception { + expectDeserializedArgument(boolean.class, false, SERIALIZED_BOOLEAN_FALSE); + } + + // (byte) 42 + private static final byte[] SERIALIZED_BYTE = {0x00, 0x42, 42}; + + @Test + public void serializeReturnValue_byte() throws Exception { + assertArrayEquals(SERIALIZED_BYTE, serializeReturnValue(byte.class, (byte) 42)); + } + + @Test + public void deserializeMethodParameters_byte() throws Exception { + expectDeserializedArgument(byte.class, (byte) 42, SERIALIZED_BYTE); + } + + // '\u1122' + private static final byte[] SERIALIZED_CHAR = {0x00, 0x43, 0x11, 0x22}; + + @Test + public void serializeReturnValue_char() throws Exception { + assertArrayEquals(SERIALIZED_CHAR, serializeReturnValue(char.class, '\u1122')); + } + + @Test + public void deserializeMethodParameters_char() throws Exception { + expectDeserializedArgument(char.class, '\u1122', SERIALIZED_CHAR); + } + + // (short) 0x1011 + private static final byte[] SERIALIZED_SHORT = {0x00, 0x53, 0x10, 0x11}; + + @Test + public void serializeReturnValue_short() throws Exception { + assertArrayEquals(SERIALIZED_SHORT, + serializeReturnValue(short.class, (short) 0x1011)); + } + + @Test + public void deserializeMethodParameters_short() throws Exception { + expectDeserializedArgument(short.class, (short) 0x1011, SERIALIZED_SHORT); + } + + // 0x11223344 + private static final byte[] SERIALIZED_INT = {0x00, 0x49, 0x11, 0x22, 0x33, 0x44}; + + @Test + public void serializeReturnValue_int() throws Exception { + assertArrayEquals(SERIALIZED_INT, + serializeReturnValue(int.class, 0x11223344)); + } + + @Test + public void deserializeMethodParameters_int() throws Exception { + expectDeserializedArgument(int.class, 0x11223344, SERIALIZED_INT); + } + + // 0x0011223344556677L + private static final byte[] SERIALIZED_LONG = + {0x00, 0x4a, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; + + @Test + public void serializeReturnValue_long() throws Exception { + assertArrayEquals(SERIALIZED_LONG, + serializeReturnValue(long.class, 0x0011223344556677L)); + } + + @Test + public void deserializeMethodParameters_long() throws Exception { + expectDeserializedArgument(long.class, 0x0011223344556677L, SERIALIZED_LONG); + } + + // 3.141d + private static final byte[] SERIALIZED_DOUBLE = + {0x00, 0x44, (byte) 0x40, (byte) 0x09, (byte) 0x20, (byte) 0xc4, (byte) 0x9b, + (byte) 0xa5, (byte) 0xe3, (byte) 0x54}; + + @Test + public void serializeReturnValue_double() throws Exception { + assertArrayEquals( + SERIALIZED_DOUBLE, + serializeReturnValue(double.class, 3.141d)); + } + + @Test + public void deserializeMethodParameters_double() throws Exception { + expectDeserializedArgument(double.class, 3.141d, SERIALIZED_DOUBLE); + } + + // 3.141f + private static final byte[] SERIALIZED_FLOAT = + {0x00, 0x46, (byte) 0x40, (byte) 0x49, (byte) 0x06, (byte) 0x25}; + + @Test + public void serializeReturnValue_float() throws Exception { + assertArrayEquals(SERIALIZED_FLOAT, + serializeReturnValue(float.class, 3.141f)); + } + + @Test + public void deserializeMethodParameters_float() throws Exception { + expectDeserializedArgument(float.class, 3.141f, SERIALIZED_FLOAT); + } + + // "foo" + private static final byte[] SERIALIZED_ASCII_STRING = {0x00, 0x52, 0, 3, 0x66, 0x6f, 0x6f}; + + @Test + public void serializeReturnValue_asciiString() throws Exception { + assertArrayEquals(SERIALIZED_ASCII_STRING, + serializeReturnValue(String.class, "foo")); + } + + @Test + public void deserializeMethodParameters_asciiString() throws Exception { + expectDeserializedArgument(String.class, "foo", SERIALIZED_ASCII_STRING); + } + + // "\u1122" + private static final byte[] SERIALIZED_NON_ASCII_STRING = + {0x00, 0x52, 0, 3, (byte) 0xe1, (byte) 0x84, (byte) 0xa2}; + + @Test + public void serializeReturnValue_nonAsciiString_encodesAsUtf8() throws Exception { + assertArrayEquals(SERIALIZED_NON_ASCII_STRING, + serializeReturnValue(String.class, "\u1122")); + } + + @Test + public void deserializeMethodParameters_decodesFromUtf8() throws Exception { + expectDeserializedArgument(String.class, "\u1122", SERIALIZED_NON_ASCII_STRING); + } + + // "" + private static final byte[] SERIALIZED_EMPTY_STRING = {0x00, 0x52, 0, 0}; + + @Test + public void serializeReturnValue_emptyString() throws Exception { + assertArrayEquals(SERIALIZED_EMPTY_STRING, serializeReturnValue(String.class, "")); + } + + @Test + public void deserializeMethodParameters_emptyString() throws Exception { + expectDeserializedArgument(String.class, "", SERIALIZED_EMPTY_STRING); + } + + @Test + public void serializeReturnValue_nullString_encodesAsEmptyString() throws Exception { + assertArrayEquals(new byte[]{0x00, 0x52, 0, 0}, serializeReturnValue(String.class, null)); + } + + // Illegal - string length exceeding actual bytes + private static final byte[] SERIALIZED_INVALID_STRING = + {0x00, 0x52, 0, 3, 0x66}; + + @Test + public void deserializeMethodParameters_stringPayloadMissing_throws() throws Exception { + Object[] args = new Object[1]; + Class<?>[] argTypes = new Class<?>[1]; + assertThrows(BufferUnderflowException.class, + () -> deserializeMethodParameters(args, argTypes, + ByteBuffer.wrap(SERIALIZED_INVALID_STRING))); + } + + @Test + public void serializeAndDeserialize_handlesStringsUpTo64k() throws Exception { + char[] chars = new char[65535]; + Arrays.fill(chars, 'a'); + String original = new String(chars); + byte[] serialized = serializeReturnValue(String.class, original); + + // 2 bytes for the R signature char, 2 bytes char string byte count, 2^16-1 bytes ASCII + // payload + assertEquals(2 + 2 + 65535, serialized.length); + + // length is unsigned short + assertArrayEquals(new byte[]{0x00, 0x52, (byte) 0xff, (byte) 0xff}, + Arrays.copyOfRange(serialized, 0, 4)); + + // length of string must be interpreted as unsigned short, returning original content + expectDeserializedArgument(String.class, original, serialized); + } + + private static final byte[] SERIALIZED_VOID = {0x00, 0x56}; + + @Test + public void serializeReturnValue_void() throws Exception { + assertArrayEquals(SERIALIZED_VOID, serializeReturnValue(void.class, null)); + } + + @Test + public void deserializeMethodParameters_void_throws() throws Exception { + Object[] args = new Object[1]; + Class<?>[] argTypes = new Class<?>[1]; + assertThrows(ViewMethodInvocationSerializationException.class, + () -> deserializeMethodParameters(args, argTypes, + ByteBuffer.wrap(SERIALIZED_VOID))); + } + + // new byte[]{} + private static final byte[] SERIALIZED_EMPTY_BYTE_ARRAY = {0x00, 0x5b, 0x00, 0x42, 0, 0, 0, 0}; + + @Test + public void serializeReturnValue_emptyByteArray() throws Exception { + assertArrayEquals(SERIALIZED_EMPTY_BYTE_ARRAY, + serializeReturnValue(byte[].class, new byte[]{})); + } + + @Test + public void deserializeMethodParameters_emptyByteArray() throws Exception { + expectDeserializedArgument(byte[].class, new byte[]{}, SERIALIZED_EMPTY_BYTE_ARRAY); + } + + // new byte[]{0, 42} + private static final byte[] SERIALIZED_SIMPLE_BYTE_ARRAY = + {0x00, 0x5b, 0x00, 0x42, 0, 0, 0, 2, 0, 42}; + + @Test + public void serializeReturnValue_byteArray() throws Exception { + assertArrayEquals(SERIALIZED_SIMPLE_BYTE_ARRAY, + serializeReturnValue(byte[].class, new byte[]{0, 42})); + } + + @Test + public void deserializeMethodParameters_byteArray() throws Exception { + expectDeserializedArgument(byte[].class, new byte[]{0, 42}, SERIALIZED_SIMPLE_BYTE_ARRAY); + } + + @Test + public void serializeReturnValue_largeByteArray_encodesSizeCorrectly() throws Exception { + byte[] result = serializeReturnValue(byte[].class, new byte[0x012233]); + // 2 bytes for the each [Z signature char, 4 bytes int array length, 0x012233 bytes payload + assertEquals(2 + 2 + 4 + 74291, result.length); + + assertArrayEquals(new byte[]{0x00, 0x5b, 0x00, 0x42, 0x00, 0x01, 0x22, 0x33}, + Arrays.copyOfRange(result, 0, 8)); + } + + // Illegal - declared size exceeds remaining buffer length + private static final byte[] SERIALIZED_INVALID_BYTE_ARRAY = + {0x00, 0x5b, 0x00, 0x42, 0, 0, 0, 3, 0, 42}; + + @Test + public void deserializeMethodParameters_sizeExceedsBuffer_throws() throws Exception { + Object[] args = new Object[1]; + Class<?>[] argTypes = new Class<?>[1]; + assertThrows(BufferUnderflowException.class, + () -> deserializeMethodParameters(args, argTypes, + ByteBuffer.wrap(SERIALIZED_INVALID_BYTE_ARRAY))); + } + + // new int[]{} + private static final byte[] SERIALIZED_EMPTY_INT_ARRAY = {0x00, 0x5b, 0x00, 0x49, 0, 0, 0, 0}; + + @Test + public void serializeReturnValue_nonByteArrayType_throws() throws Exception { + assertThrows(ViewMethodInvocationSerializationException.class, + () -> serializeReturnValue(int[].class, 42)); + } + + @Test + public void deserializeMethodParameters_nonByteArrayType_throws() throws Exception { + Object[] args = new Object[1]; + Class<?>[] argTypes = new Class<?>[1]; + assertThrows(ViewMethodInvocationSerializationException.class, + () -> deserializeMethodParameters(args, argTypes, + ByteBuffer.wrap(SERIALIZED_EMPTY_INT_ARRAY))); + } + + // new byte[]{0, 42} + private static final byte[] SERIALIZED_MULTIPLE_PARAMETERS = + {0x00, 0x42, 42, 0x00, 0x5A, 1}; + + @Test + public void deserializeMethodParameters_multipleParameters() throws Exception { + expectDeserializedArguments(new Class[]{byte.class, boolean.class}, + new Object[]{(byte) 42, true}, SERIALIZED_MULTIPLE_PARAMETERS); + } + + // Illegal - type 'X' + private static final byte[] SERIALIZED_INVALID_UNKNOWN_TYPE = {0x00, 0x58}; + + @Test + public void deserializeMethodParameters_unknownType_throws() throws Exception { + Object[] args = new Object[1]; + Class<?>[] argTypes = new Class<?>[1]; + assertThrows(ViewMethodInvocationSerializationException.class, + () -> deserializeMethodParameters(args, argTypes, + ByteBuffer.wrap(SERIALIZED_INVALID_UNKNOWN_TYPE))); + } + + @Test + public void deserializeMethodParameters_noArgumentsEmptyPacket_isNoop() throws Exception { + Object[] args = new Object[0]; + Class<?>[] argTypes = new Class<?>[0]; + deserializeMethodParameters(args, argTypes, ByteBuffer.wrap(new byte[0])); + } + + @Test + public void deserializeMethodParameters_withArgumentsEmptyPacket_throws() throws Exception { + Object[] args = new Object[1]; + Class<?>[] argTypes = new Class<?>[1]; + assertThrows(BufferUnderflowException.class, + () -> deserializeMethodParameters(args, argTypes, ByteBuffer.wrap(new byte[0]))); + } + + private static void expectDeserializedArgument(Class<?> expectedType, Object expectedValue, + byte[] argumentBuffer) throws Exception { + expectDeserializedArguments(new Class[]{expectedType}, new Object[]{expectedValue}, + argumentBuffer); + } + + private static void expectDeserializedArguments(Class<?>[] expectedTypes, + Object[] expectedValues, byte[] argumentBuffer) throws Exception { + final int argCount = expectedTypes.length; + assertEquals("test helper not used correctly", argCount, expectedValues.length); + Object[] actualArgs = new Object[argCount]; + Class<?>[] actualArgTypes = new Class<?>[argCount]; + + ByteBuffer buffer = ByteBuffer.wrap(argumentBuffer); + deserializeMethodParameters(actualArgs, actualArgTypes, buffer); + + for (int i = 0; i < argCount; i++) { + String context = "argument " + i; + assertEquals(context, expectedTypes[i], actualArgTypes[i]); + if (byte[].class.equals(expectedTypes[i])) { + assertArrayEquals((byte[]) expectedValues[i], (byte[]) actualArgs[i]); + } else { + assertEquals(expectedValues[i], actualArgs[i]); + } + } + } +} diff --git a/core/tests/coretests/src/android/ddm/OWNERS b/core/tests/coretests/src/android/ddm/OWNERS new file mode 100644 index 000000000000..c8be1919fb93 --- /dev/null +++ b/core/tests/coretests/src/android/ddm/OWNERS @@ -0,0 +1 @@ +michschn@google.com diff --git a/core/tests/coretests/src/android/service/notification/ConditionTest.java b/core/tests/coretests/src/android/service/notification/ConditionTest.java new file mode 100644 index 000000000000..42629ba41287 --- /dev/null +++ b/core/tests/coretests/src/android/service/notification/ConditionTest.java @@ -0,0 +1,101 @@ +/* + * 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 android.service.notification; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.fail; + +import android.net.Uri; +import android.os.Parcel; + +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.filters.SmallTest; + +import com.google.common.base.Strings; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.lang.reflect.Field; + +@RunWith(AndroidJUnit4.class) +@SmallTest +public class ConditionTest { + private static final String CLASS = "android.service.notification.Condition"; + + @Test + public void testLongFields_inConstructors() { + String longString = Strings.repeat("A", 65536); + Uri longUri = Uri.parse("uri://" + Strings.repeat("A", 65530)); + + // Confirm strings are truncated via short constructor + Condition cond1 = new Condition(longUri, longString, Condition.STATE_TRUE); + + assertEquals(Condition.MAX_STRING_LENGTH, cond1.id.toString().length()); + assertEquals(Condition.MAX_STRING_LENGTH, cond1.summary.length()); + + // Confirm strings are truncated via long constructor + Condition cond2 = new Condition(longUri, longString, longString, longString, + -1, Condition.STATE_TRUE, Condition.FLAG_RELEVANT_ALWAYS); + + assertEquals(Condition.MAX_STRING_LENGTH, cond2.id.toString().length()); + assertEquals(Condition.MAX_STRING_LENGTH, cond2.summary.length()); + assertEquals(Condition.MAX_STRING_LENGTH, cond2.line1.length()); + assertEquals(Condition.MAX_STRING_LENGTH, cond2.line2.length()); + } + + @Test + public void testLongFields_viaParcel() { + // Set fields via reflection to force them to be long, then parcel and unparcel to make sure + // it gets truncated upon unparcelling. + Condition cond = new Condition(Uri.parse("uri://placeholder"), "placeholder", + Condition.STATE_TRUE); + + try { + String longString = Strings.repeat("A", 65536); + Uri longUri = Uri.parse("uri://" + Strings.repeat("A", 65530)); + Field id = Class.forName(CLASS).getDeclaredField("id"); + id.setAccessible(true); + id.set(cond, longUri); + Field summary = Class.forName(CLASS).getDeclaredField("summary"); + summary.setAccessible(true); + summary.set(cond, longString); + Field line1 = Class.forName(CLASS).getDeclaredField("line1"); + line1.setAccessible(true); + line1.set(cond, longString); + Field line2 = Class.forName(CLASS).getDeclaredField("line2"); + line2.setAccessible(true); + line2.set(cond, longString); + } catch (NoSuchFieldException e) { + fail(e.toString()); + } catch (ClassNotFoundException e) { + fail(e.toString()); + } catch (IllegalAccessException e) { + fail(e.toString()); + } + + Parcel parcel = Parcel.obtain(); + cond.writeToParcel(parcel, 0); + parcel.setDataPosition(0); + + Condition fromParcel = new Condition(parcel); + assertEquals(Condition.MAX_STRING_LENGTH, fromParcel.id.toString().length()); + assertEquals(Condition.MAX_STRING_LENGTH, fromParcel.summary.length()); + assertEquals(Condition.MAX_STRING_LENGTH, fromParcel.line1.length()); + assertEquals(Condition.MAX_STRING_LENGTH, fromParcel.line2.length()); + } +} diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserListAdapterTest.kt b/core/tests/coretests/src/com/android/internal/app/ChooserListAdapterTest.kt deleted file mode 100644 index f027e0b50c18..000000000000 --- a/core/tests/coretests/src/com/android/internal/app/ChooserListAdapterTest.kt +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright (C) 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.internal.app - -import android.content.ComponentName -import android.content.pm.PackageManager -import android.os.Bundle -import android.service.chooser.ChooserTarget -import android.view.View -import android.widget.FrameLayout -import android.widget.ImageView -import android.widget.TextView -import androidx.test.ext.junit.runners.AndroidJUnit4 -import androidx.test.platform.app.InstrumentationRegistry -import com.android.internal.R -import com.android.internal.app.chooser.SelectableTargetInfo -import com.android.internal.app.chooser.SelectableTargetInfo.SelectableTargetInfoCommunicator -import com.android.server.testutils.any -import com.android.server.testutils.mock -import com.android.server.testutils.whenever -import org.junit.Test -import org.junit.runner.RunWith -import org.mockito.Mockito.anyInt -import org.mockito.Mockito.doNothing -import org.mockito.Mockito.times -import org.mockito.Mockito.verify - -@RunWith(AndroidJUnit4::class) -class ChooserListAdapterTest { - private val packageManager = mock<PackageManager> { - whenever(resolveActivity(any(), anyInt())).thenReturn(mock()) - } - private val context = InstrumentationRegistry.getInstrumentation().getContext() - private val resolverListController = mock<ResolverListController>() - private val chooserListCommunicator = mock<ChooserListAdapter.ChooserListCommunicator> { - whenever(maxRankedTargets).thenReturn(0) - } - private val selectableTargetInfoCommunicator = - mock<SelectableTargetInfoCommunicator> { - whenever(targetIntent).thenReturn(mock()) - } - private val chooserActivityLogger = mock<ChooserActivityLogger>() - - private val testSubject = ChooserListAdapter( - context, - emptyList(), - emptyArray(), - emptyList(), - false, - resolverListController, - chooserListCommunicator, - selectableTargetInfoCommunicator, - packageManager, - chooserActivityLogger - ) - - @Test - fun testDirectShareTargetLoadingIconIsStarted() { - val view = createView() - val viewHolder = ResolverListAdapter.ViewHolder(view) - view.tag = viewHolder - val targetInfo = createSelectableTargetInfo() - val iconTask = mock<ChooserListAdapter.LoadDirectShareIconTask> { - doNothing().whenever(this).loadIcon() - } - testSubject.setTestLoadDirectShareTaskProvider( - mock { - whenever(get()).thenReturn(iconTask) - } - ) - testSubject.testViewBind(view, targetInfo, 0) - - verify(iconTask, times(1)).loadIcon() - verify(iconTask, times(1)).setViewHolder(viewHolder) - } - - @Test - fun testOnlyOneTaskPerTarget() { - val view = createView() - val viewHolderOne = ResolverListAdapter.ViewHolder(view) - view.tag = viewHolderOne - val targetInfo = createSelectableTargetInfo() - val iconTaskOne = mock<ChooserListAdapter.LoadDirectShareIconTask> { - doNothing().whenever(this).loadIcon() - } - val testTaskProvider = mock<ChooserListAdapter.LoadDirectShareIconTaskProvider> { - whenever(get()).thenReturn(iconTaskOne) - } - testSubject.setTestLoadDirectShareTaskProvider( - testTaskProvider - ) - testSubject.testViewBind(view, targetInfo, 0) - - val viewHolderTwo = ResolverListAdapter.ViewHolder(view) - view.tag = viewHolderTwo - whenever(testTaskProvider.get()).thenReturn(mock()) - - testSubject.testViewBind(view, targetInfo, 0) - - verify(iconTaskOne, times(1)).loadIcon() - verify(iconTaskOne, times(1)).setViewHolder(viewHolderOne) - verify(iconTaskOne, times(1)).setViewHolder(viewHolderTwo) - verify(testTaskProvider, times(1)).get() - } - - private fun createSelectableTargetInfo(): SelectableTargetInfo = - SelectableTargetInfo( - context, - null, - createChooserTarget(), - 1f, - selectableTargetInfoCommunicator, - null - ) - - private fun createChooserTarget(): ChooserTarget = - ChooserTarget( - "Title", - null, - 1f, - ComponentName("package", "package.Class"), - Bundle() - ) - - private fun createView(): View { - val view = FrameLayout(context) - TextView(context).apply { - id = R.id.text1 - view.addView(this) - } - TextView(context).apply { - id = R.id.text2 - view.addView(this) - } - ImageView(context).apply { - id = R.id.icon - view.addView(this) - } - return view - } -} diff --git a/graphics/java/android/graphics/RuntimeShader.java b/graphics/java/android/graphics/RuntimeShader.java index 6abe34b1d675..9c36fc36474c 100644 --- a/graphics/java/android/graphics/RuntimeShader.java +++ b/graphics/java/android/graphics/RuntimeShader.java @@ -214,7 +214,7 @@ import libcore.util.NativeAllocationRegistry; * uniform shader myShader; * vec4 main(vec2 canvas_coordinates) { * // swap the red and blue color channels when sampling from myShader - * return myShader.sample(canvas_coordinates).bgra; + * return myShader.eval(canvas_coordinates).bgra; * }</pre> * * <p>After creating a {@link RuntimeShader} with that program the shader uniform can diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java index 724a50fbdb04..126f8350839c 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java @@ -139,6 +139,16 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen } } + @Override + public void setSplitAttributesCalculator(@NonNull SplitAttributesCalculator calculator) { + // TODO: Implement this method + } + + @Override + public void clearSplitAttributesCalculator() { + // TODO: Implement this method + } + @NonNull List<EmbeddingRule> getSplitRules() { return mSplitRules; @@ -901,6 +911,36 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen mPresenter.cleanupContainer(wct, container, false /* shouldFinishDependent */); } + @Nullable + @GuardedBy("mLock") + private TaskFragmentContainer resolveStartActivityIntentFromNonActivityContext( + @NonNull WindowContainerTransaction wct, @NonNull Intent intent) { + final int taskCount = mTaskContainers.size(); + if (taskCount == 0) { + // We don't have other Activity to check split with. + return null; + } + if (taskCount > 1) { + Log.w(TAG, "App is calling startActivity from a non-Activity context when it has" + + " more than one Task. If the new launch Activity is in a different process," + + " and it is expected to be embedded, please start it from an Activity" + + " instead."); + return null; + } + + // Check whether the Intent should be embedded in the known Task. + final TaskContainer taskContainer = mTaskContainers.valueAt(0); + if (taskContainer.isInPictureInPicture() + || taskContainer.getTopNonFinishingActivity() == null) { + // We don't embed activity when it is in PIP, or if we can't find any other owner + // activity in the Task. + return null; + } + + return resolveStartActivityIntent(wct, taskContainer.getTaskId(), intent, + null /* launchingActivity */); + } + /** * When we are trying to handle a new activity Intent, returns the {@link TaskFragmentContainer} * that we should reparent the new activity to if there is any embedding rule matched. @@ -1486,13 +1526,20 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen .toActivityStack(); final ActivityStack secondaryContainer = container.getSecondaryContainer() .toActivityStack(); + final SplitAttributes.SplitType splitType = shouldShowSideBySide(container) + ? new SplitAttributes.SplitType.RatioSplitType( + container.getSplitRule().getSplitRatio()) + : new SplitAttributes.SplitType.ExpandContainersSplitType(); final SplitInfo splitState = new SplitInfo(primaryContainer, secondaryContainer, // Splits that are not showing side-by-side are reported as having 0 split // ratio, since by definition in the API the primary container occupies no // width of the split when covered by the secondary. - shouldShowSideBySide(container) - ? container.getSplitRule().getSplitRatio() - : 0.0f); + // TODO(b/241042437): use v2 APIs for splitAttributes + new SplitAttributes.Builder() + .setSplitType(splitType) + .setLayoutDirection(container.getSplitRule().getLayoutDirection()) + .build() + ); splitStates.add(splitState); } } @@ -1777,23 +1824,38 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen @Override public Instrumentation.ActivityResult onStartActivity(@NonNull Context who, @NonNull Intent intent, @NonNull Bundle options) { - // TODO(b/190433398): Check if the activity is configured to always be expanded. - - // Check if activity should be put in a split with the activity that launched it. - if (!(who instanceof Activity)) { - return super.onStartActivity(who, intent, options); - } - final Activity launchingActivity = (Activity) who; - if (isInPictureInPicture(launchingActivity)) { - // We don't embed activity when it is in PIP. - return super.onStartActivity(who, intent, options); + // TODO(b/232042367): Consolidate the activity create handling so that we can handle + // cross-process the same as normal. + + final Activity launchingActivity; + if (who instanceof Activity) { + // We will check if the new activity should be split with the activity that launched + // it. + launchingActivity = (Activity) who; + if (isInPictureInPicture(launchingActivity)) { + // We don't embed activity when it is in PIP. + return super.onStartActivity(who, intent, options); + } + } else { + // When the context to start activity is not an Activity context, we will check if + // the new activity should be embedded in the known Task belonging to the organizer + // process. @see #resolveStartActivityIntentFromNonActivityContext + // It is a current security limitation that we can't access the activity info of + // other process even if it is in the same Task. + launchingActivity = null; } synchronized (mLock) { - final int taskId = getTaskId(launchingActivity); final WindowContainerTransaction wct = new WindowContainerTransaction(); - final TaskFragmentContainer launchedInTaskFragment = resolveStartActivityIntent(wct, - taskId, intent, launchingActivity); + final TaskFragmentContainer launchedInTaskFragment; + if (launchingActivity != null) { + final int taskId = getTaskId(launchingActivity); + launchedInTaskFragment = resolveStartActivityIntent(wct, taskId, intent, + launchingActivity); + } else { + launchedInTaskFragment = resolveStartActivityIntentFromNonActivityContext(wct, + intent); + } if (launchedInTaskFragment != null) { // Make sure the WCT is applied immediately instead of being queued so that the // TaskFragment will be ready before activity attachment. diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationAdapter.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationAdapter.java index cdee9e386b33..af5d8c561874 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationAdapter.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationAdapter.java @@ -16,7 +16,6 @@ package androidx.window.extensions.embedding; -import static android.graphics.Matrix.MSCALE_X; import static android.graphics.Matrix.MTRANS_X; import static android.graphics.Matrix.MTRANS_Y; @@ -41,30 +40,44 @@ class TaskFragmentAnimationAdapter { */ private static final int LAYER_NO_OVERRIDE = -1; + @NonNull final Animation mAnimation; + @NonNull final RemoteAnimationTarget mTarget; + @NonNull final SurfaceControl mLeash; + /** Area in absolute coordinate that the animation surface shouldn't go beyond. */ + @NonNull + private final Rect mWholeAnimationBounds = new Rect(); + @NonNull final Transformation mTransformation = new Transformation(); + @NonNull final float[] mMatrix = new float[9]; + @NonNull final float[] mVecs = new float[4]; + @NonNull final Rect mRect = new Rect(); private boolean mIsFirstFrame = true; private int mOverrideLayer = LAYER_NO_OVERRIDE; TaskFragmentAnimationAdapter(@NonNull Animation animation, @NonNull RemoteAnimationTarget target) { - this(animation, target, target.leash); + this(animation, target, target.leash, target.screenSpaceBounds); } /** * @param leash the surface to animate. + * @param wholeAnimationBounds area in absolute coordinate that the animation surface shouldn't + * go beyond. */ TaskFragmentAnimationAdapter(@NonNull Animation animation, - @NonNull RemoteAnimationTarget target, @NonNull SurfaceControl leash) { + @NonNull RemoteAnimationTarget target, @NonNull SurfaceControl leash, + @NonNull Rect wholeAnimationBounds) { mAnimation = animation; mTarget = target; mLeash = leash; + mWholeAnimationBounds.set(wholeAnimationBounds); } /** @@ -94,23 +107,32 @@ class TaskFragmentAnimationAdapter { /** To be overridden by subclasses to adjust the animation surface change. */ void onAnimationUpdateInner(@NonNull SurfaceControl.Transaction t) { + // Update the surface position and alpha. mTransformation.getMatrix().postTranslate( mTarget.localBounds.left, mTarget.localBounds.top); t.setMatrix(mLeash, mTransformation.getMatrix(), mMatrix); t.setAlpha(mLeash, mTransformation.getAlpha()); - // Get current animation position. + + // Get current surface bounds in absolute coordinate. + // positionX/Y are in local coordinate, so minus the local offset to get the slide amount. final int positionX = Math.round(mMatrix[MTRANS_X]); final int positionY = Math.round(mMatrix[MTRANS_Y]); - // The exiting surface starts at position: mTarget.localBounds and moves with - // positionX varying. Offset our crop region by the amount we have slided so crop - // regions stays exactly on the original container in split. - final int cropOffsetX = mTarget.localBounds.left - positionX; - final int cropOffsetY = mTarget.localBounds.top - positionY; - final Rect cropRect = new Rect(); - cropRect.set(mTarget.localBounds); - // Because window crop uses absolute position. - cropRect.offsetTo(0, 0); - cropRect.offset(cropOffsetX, cropOffsetY); + final Rect cropRect = new Rect(mTarget.screenSpaceBounds); + final Rect localBounds = mTarget.localBounds; + cropRect.offset(positionX - localBounds.left, positionY - localBounds.top); + + // Store the current offset of the surface top left from (0,0) in absolute coordinate. + final int offsetX = cropRect.left; + final int offsetY = cropRect.top; + + // Intersect to make sure the animation happens within the whole animation bounds. + if (!cropRect.intersect(mWholeAnimationBounds)) { + // Hide the surface when it is outside of the animation area. + t.setAlpha(mLeash, 0); + } + + // cropRect is in absolute coordinate, so we need to translate it to surface top left. + cropRect.offset(-offsetX, -offsetY); t.setCrop(mLeash, cropRect); } @@ -124,52 +146,6 @@ class TaskFragmentAnimationAdapter { } /** - * Should be used when the {@link RemoteAnimationTarget} is in split with others, and want to - * animate together as one. This adapter will offset the animation leash to make the animate of - * two windows look like a single window. - */ - static class SplitAdapter extends TaskFragmentAnimationAdapter { - private final boolean mIsLeftHalf; - private final int mWholeAnimationWidth; - - /** - * @param isLeftHalf whether this is the left half of the animation. - * @param wholeAnimationWidth the whole animation windows width. - */ - SplitAdapter(@NonNull Animation animation, @NonNull RemoteAnimationTarget target, - boolean isLeftHalf, int wholeAnimationWidth) { - super(animation, target); - mIsLeftHalf = isLeftHalf; - mWholeAnimationWidth = wholeAnimationWidth; - if (wholeAnimationWidth == 0) { - throw new IllegalArgumentException("SplitAdapter must provide wholeAnimationWidth"); - } - } - - @Override - void onAnimationUpdateInner(@NonNull SurfaceControl.Transaction t) { - float posX = mTarget.localBounds.left; - final float posY = mTarget.localBounds.top; - // This window is half of the whole animation window. Offset left/right to make it - // look as one with the other half. - mTransformation.getMatrix().getValues(mMatrix); - final int targetWidth = mTarget.localBounds.width(); - final float scaleX = mMatrix[MSCALE_X]; - final float totalOffset = mWholeAnimationWidth * (1 - scaleX) / 2; - final float curOffset = targetWidth * (1 - scaleX) / 2; - final float offsetDiff = totalOffset - curOffset; - if (mIsLeftHalf) { - posX += offsetDiff; - } else { - posX -= offsetDiff; - } - mTransformation.getMatrix().postTranslate(posX, posY); - t.setMatrix(mLeash, mTransformation.getMatrix(), mMatrix); - t.setAlpha(mLeash, mTransformation.getAlpha()); - } - } - - /** * Should be used for the animation of the snapshot of a {@link RemoteAnimationTarget} that has * size change. */ @@ -177,7 +153,7 @@ class TaskFragmentAnimationAdapter { SnapshotAdapter(@NonNull Animation animation, @NonNull RemoteAnimationTarget target) { // Start leash is the snapshot of the starting surface. - super(animation, target, target.startLeash); + super(animation, target, target.startLeash, target.screenSpaceBounds); } @Override diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationRunner.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationRunner.java index 8af2d9c6810b..8c416e881059 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationRunner.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationRunner.java @@ -213,10 +213,10 @@ class TaskFragmentAnimationRunner extends IRemoteAnimationRunner.Stub { for (RemoteAnimationTarget target : targets) { if (target.mode != MODE_CLOSING) { openingTargets.add(target); - openingWholeScreenBounds.union(target.localBounds); + openingWholeScreenBounds.union(target.screenSpaceBounds); } else { closingTargets.add(target); - closingWholeScreenBounds.union(target.localBounds); + closingWholeScreenBounds.union(target.screenSpaceBounds); } } @@ -249,20 +249,8 @@ class TaskFragmentAnimationRunner extends IRemoteAnimationRunner.Stub { @NonNull BiFunction<RemoteAnimationTarget, Rect, Animation> animationProvider, @NonNull Rect wholeAnimationBounds) { final Animation animation = animationProvider.apply(target, wholeAnimationBounds); - final Rect targetBounds = target.localBounds; - if (targetBounds.left == wholeAnimationBounds.left - && targetBounds.right != wholeAnimationBounds.right) { - // This is the left split of the whole animation window. - return new TaskFragmentAnimationAdapter.SplitAdapter(animation, target, - true /* isLeftHalf */, wholeAnimationBounds.width()); - } else if (targetBounds.left != wholeAnimationBounds.left - && targetBounds.right == wholeAnimationBounds.right) { - // This is the right split of the whole animation window. - return new TaskFragmentAnimationAdapter.SplitAdapter(animation, target, - false /* isLeftHalf */, wholeAnimationBounds.width()); - } - // Open/close window that fills the whole animation. - return new TaskFragmentAnimationAdapter(animation, target); + return new TaskFragmentAnimationAdapter(animation, target, target.leash, + wholeAnimationBounds); } @NonNull diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationSpec.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationSpec.java index 97d42391b6c4..ef5ea563de12 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationSpec.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentAnimationSpec.java @@ -195,7 +195,10 @@ class TaskFragmentAnimationSpec { ? com.android.internal.R.anim.task_fragment_open_enter : com.android.internal.R.anim.task_fragment_open_exit); } - animation.initialize(target.localBounds.width(), target.localBounds.height(), + // Use the whole animation bounds instead of the change bounds, so that when multiple change + // targets are opening at the same time, the animation applied to each will be the same. + // Otherwise, we may see gap between the activities that are launching together. + animation.initialize(wholeAnimationBounds.width(), wholeAnimationBounds.height(), wholeAnimationBounds.width(), wholeAnimationBounds.height()); animation.scaleCurrentDuration(mTransitionAnimationScaleSetting); return animation; @@ -215,7 +218,10 @@ class TaskFragmentAnimationSpec { ? com.android.internal.R.anim.task_fragment_close_enter : com.android.internal.R.anim.task_fragment_close_exit); } - animation.initialize(target.localBounds.width(), target.localBounds.height(), + // Use the whole animation bounds instead of the change bounds, so that when multiple change + // targets are closing at the same time, the animation applied to each will be the same. + // Otherwise, we may see gap between the activities that are finishing together. + animation.initialize(wholeAnimationBounds.width(), wholeAnimationBounds.height(), wholeAnimationBounds.width(), wholeAnimationBounds.height()); animation.scaleCurrentDuration(mTransitionAnimationScaleSetting); return animation; diff --git a/libs/WindowManager/Jetpack/window-extensions-release.aar b/libs/WindowManager/Jetpack/window-extensions-release.aar Binary files differindex e9a1721fba2a..2c766d81d611 100644 --- a/libs/WindowManager/Jetpack/window-extensions-release.aar +++ b/libs/WindowManager/Jetpack/window-extensions-release.aar diff --git a/libs/WindowManager/Shell/res/values-af/strings.xml b/libs/WindowManager/Shell/res/values-af/strings.xml index aacc5963a3a0..cc600741d1b7 100644 --- a/libs/WindowManager/Shell/res/values-af/strings.xml +++ b/libs/WindowManager/Shell/res/values-af/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Kamerakwessies?\nTik om aan te pas"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Nie opgelos nie?\nTik om terug te stel"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Geen kamerakwessies nie? Tik om toe te maak."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Sien en doen meer"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"Sleep ’n ander program in vir verdeelde skerm"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Dubbeltik buite ’n program om dit te herposisioneer"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Het dit"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Vou uit vir meer inligting."</string> <string name="maximize_button_text" msgid="1650859196290301963">"Maksimeer"</string> diff --git a/libs/WindowManager/Shell/res/values-am/strings.xml b/libs/WindowManager/Shell/res/values-am/strings.xml index 02fdc4214bf5..7aa877041d53 100644 --- a/libs/WindowManager/Shell/res/values-am/strings.xml +++ b/libs/WindowManager/Shell/res/values-am/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"የካሜራ ችግሮች አሉ?\nዳግም ለማበጀት መታ ያድርጉ"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"አልተስተካከለም?\nለማህደር መታ ያድርጉ"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"ምንም የካሜራ ችግሮች የሉም? ለማሰናበት መታ ያድርጉ።"</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"ተጨማሪ ይመልከቱ እና ያድርጉ"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"ለተከፈለ ማያ ገጽ ሌላ መተግበሪያ ይጎትቱ"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"ቦታውን ለመቀየር ከመተግበሪያው ውጪ ሁለቴ መታ ያድርጉ"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"ገባኝ"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"ለተጨማሪ መረጃ ይዘርጉ።"</string> <string name="maximize_button_text" msgid="1650859196290301963">"አስፋ"</string> diff --git a/libs/WindowManager/Shell/res/values-ar/strings.xml b/libs/WindowManager/Shell/res/values-ar/strings.xml index 5003f79513b5..2d0d9705cab1 100644 --- a/libs/WindowManager/Shell/res/values-ar/strings.xml +++ b/libs/WindowManager/Shell/res/values-ar/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"هل هناك مشاكل في الكاميرا؟\nانقر لإعادة الضبط."</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"ألم يتم حل المشكلة؟\nانقر للعودة"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"أليس هناك مشاكل في الكاميرا؟ انقر للإغلاق."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"استخدام تطبيقات متعدّدة في وقت واحد"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"اسحب تطبيقًا آخر لاستخدام وضع تقسيم الشاشة."</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"انقر مرّتين خارج تطبيق لتغيير موضعه."</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"حسنًا"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"التوسيع للحصول على مزيد من المعلومات"</string> <string name="maximize_button_text" msgid="1650859196290301963">"تكبير"</string> diff --git a/libs/WindowManager/Shell/res/values-as/strings.xml b/libs/WindowManager/Shell/res/values-as/strings.xml index b849345b71e0..42153ff1ad96 100644 --- a/libs/WindowManager/Shell/res/values-as/strings.xml +++ b/libs/WindowManager/Shell/res/values-as/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"কেমেৰাৰ কোনো সমস্যা হৈছে নেকি?\nপুনৰ খাপ খোৱাবলৈ টিপক"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"এইটো সমাধান কৰা নাই নেকি?\nপূৰ্বাৱস্থালৈ নিবলৈ টিপক"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"কেমেৰাৰ কোনো সমস্যা নাই নেকি? অগ্ৰাহ্য কৰিবলৈ টিপক।"</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"চাওক আৰু অধিক কৰক"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"বিভাজিত স্ক্ৰীনৰ বাবে অন্য এটা এপ্ টানি আনি এৰক"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"এপ্টোৰ স্থান সলনি কৰিবলৈ ইয়াৰ বাহিৰত দুবাৰ টিপক"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"বুজি পালোঁ"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"অধিক তথ্যৰ বাবে বিস্তাৰ কৰক।"</string> <string name="maximize_button_text" msgid="1650859196290301963">"সৰ্বাধিক মাত্ৰালৈ বঢ়াওক"</string> diff --git a/libs/WindowManager/Shell/res/values-az/strings.xml b/libs/WindowManager/Shell/res/values-az/strings.xml index 0c7f74c9ea75..5da5a97ff076 100644 --- a/libs/WindowManager/Shell/res/values-az/strings.xml +++ b/libs/WindowManager/Shell/res/values-az/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Kamera problemi var?\nBərpa etmək üçün toxunun"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Düzəltməmisiniz?\nGeri qaytarmaq üçün toxunun"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Kamera problemi yoxdur? Qapatmaq üçün toxunun."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Ardını görün və edin"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"Bölünmüş ekrandan istifadə etmək üçün başqa tətbiqi sürüşdürüb gətirin"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Tətbiqin yerini dəyişmək üçün kənarına iki dəfə toxunun"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Anladım"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Ətraflı məlumat üçün genişləndirin."</string> <string name="maximize_button_text" msgid="1650859196290301963">"Böyüdün"</string> 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 a9fcb66e9a06..aff2b9f686c8 100644 --- a/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml +++ b/libs/WindowManager/Shell/res/values-b+sr+Latn/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Imate problema sa kamerom?\nDodirnite da biste ponovo uklopili"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Problem nije rešen?\nDodirnite da biste vratili"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Nemate problema sa kamerom? Dodirnite da biste odbacili."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Vidite i uradite više"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"Prevucite drugu aplikaciju da biste koristili podeljeni ekran"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Dvaput dodirnite izvan aplikacije da biste promenili njenu poziciju"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Važi"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Proširite za još informacija."</string> <string name="maximize_button_text" msgid="1650859196290301963">"Uvećajte"</string> diff --git a/libs/WindowManager/Shell/res/values-be/strings.xml b/libs/WindowManager/Shell/res/values-be/strings.xml index 8fa2de56c2de..e325e511596c 100644 --- a/libs/WindowManager/Shell/res/values-be/strings.xml +++ b/libs/WindowManager/Shell/res/values-be/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Праблемы з камерай?\nНацісніце, каб пераабсталяваць"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Не ўдалося выправіць?\nНацісніце, каб аднавіць"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Ніякіх праблем з камерай? Націсніце, каб адхіліць."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Адначасова выконвайце розныя задачы"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"Перацягніце іншую праграму, каб выкарыстоўваць падзелены экран"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Двойчы націсніце экран па-за праграмай, каб перамясціць яе"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Зразумела"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Разгарнуць для дадатковай інфармацыі"</string> <string name="maximize_button_text" msgid="1650859196290301963">"Разгарнуць"</string> diff --git a/libs/WindowManager/Shell/res/values-bg/strings.xml b/libs/WindowManager/Shell/res/values-bg/strings.xml index 60ea63e40816..3bedc86a79ac 100644 --- a/libs/WindowManager/Shell/res/values-bg/strings.xml +++ b/libs/WindowManager/Shell/res/values-bg/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Имате проблеми с камерата?\nДокоснете за ремонтиране"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Проблемът не се отстрани?\nДокоснете за връщане в предишното състояние"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Нямате проблеми с камерата? Докоснете, за да отхвърлите."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Преглеждайте и правете повече неща"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"Преместете друго приложение с плъзгане, за да преминете в режим за разделен екран"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Докоснете два пъти извън дадено приложение, за да промените позицията му"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Разбрах"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Разгъване за още информация."</string> <string name="maximize_button_text" msgid="1650859196290301963">"Увеличаване"</string> diff --git a/libs/WindowManager/Shell/res/values-bn/strings.xml b/libs/WindowManager/Shell/res/values-bn/strings.xml index 8e262c31f282..35e5b38233cc 100644 --- a/libs/WindowManager/Shell/res/values-bn/strings.xml +++ b/libs/WindowManager/Shell/res/values-bn/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"ক্যামেরা সংক্রান্ত সমস্যা?\nরিফিট করতে ট্যাপ করুন"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"এখনও সমাধান হয়নি?\nরিভার্ট করার জন্য ট্যাপ করুন"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"ক্যামেরা সংক্রান্ত সমস্যা নেই? বাতিল করতে ট্যাপ করুন।"</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"দেখুন ও আরও অনেক কিছু করুন"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"স্প্লিট স্ক্রিনের জন্য অন্য অ্যাপে টেনে আনুন"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"কোনও অ্যাপের স্থান পরিবর্তন করতে তার বাইরে ডবল ট্যাপ করুন"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"বুঝেছি"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"আরও তথ্যের জন্য বড় করুন।"</string> <string name="maximize_button_text" msgid="1650859196290301963">"বড় করুন"</string> diff --git a/libs/WindowManager/Shell/res/values-bs/strings.xml b/libs/WindowManager/Shell/res/values-bs/strings.xml index 8a4521f70b97..34b282b24666 100644 --- a/libs/WindowManager/Shell/res/values-bs/strings.xml +++ b/libs/WindowManager/Shell/res/values-bs/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problemi s kamerom?\nDodirnite da ponovo namjestite"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Nije popravljeno?\nDodirnite da vratite"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Nema problema s kamerom? Dodirnite da odbacite."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Pogledajte i učinite više"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"Prevucite još jednu aplikaciju za podijeljeni ekran"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Dvaput dodirnite izvan aplikacije da promijenite njen položaj"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Razumijem"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Proširite za više informacija."</string> <string name="maximize_button_text" msgid="1650859196290301963">"Maksimiziranje"</string> diff --git a/libs/WindowManager/Shell/res/values-ca/strings.xml b/libs/WindowManager/Shell/res/values-ca/strings.xml index fe4cb5d63023..0279917272a5 100644 --- a/libs/WindowManager/Shell/res/values-ca/strings.xml +++ b/libs/WindowManager/Shell/res/values-ca/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Tens problemes amb la càmera?\nToca per resoldre\'ls"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"El problema no s\'ha resolt?\nToca per desfer els canvis"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"No tens cap problema amb la càmera? Toca per ignorar."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Consulta i fes més coses"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"Arrossega una altra aplicació per utilitzar la pantalla dividida"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Fes doble toc fora d\'una aplicació per canviar-ne la posició"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Entesos"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Desplega per obtenir més informació."</string> <string name="maximize_button_text" msgid="1650859196290301963">"Maximitza"</string> diff --git a/libs/WindowManager/Shell/res/values-cs/strings.xml b/libs/WindowManager/Shell/res/values-cs/strings.xml index 1508b5aa7d22..d58100b5bb9b 100644 --- a/libs/WindowManager/Shell/res/values-cs/strings.xml +++ b/libs/WindowManager/Shell/res/values-cs/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problémy s fotoaparátem?\nKlepnutím vyřešíte"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Nepomohlo to?\nKlepnutím se vrátíte"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Žádné problémy s fotoaparátem? Klepnutím zavřete."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Lepší zobrazení a více možností"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"Přetáhnutím druhé aplikace použijete rozdělenou obrazovku"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Dvojitým klepnutím mimo aplikaci změníte její umístění"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Rozbalením zobrazíte další informace."</string> <string name="maximize_button_text" msgid="1650859196290301963">"Maximalizovat"</string> diff --git a/libs/WindowManager/Shell/res/values-da/strings.xml b/libs/WindowManager/Shell/res/values-da/strings.xml index 05d2148d0806..abb9cea6c6f3 100644 --- a/libs/WindowManager/Shell/res/values-da/strings.xml +++ b/libs/WindowManager/Shell/res/values-da/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Har du problemer med dit kamera?\nTryk for at gendanne det oprindelige format"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Løste det ikke problemet?\nTryk for at fortryde"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Har du ingen problemer med dit kamera? Tryk for at afvise."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Se og gør mere"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"Træk en anden app hertil for at bruge opdelt skærm"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Tryk to gange uden for en app for at justere dens placering"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Udvid for at få flere oplysninger."</string> <string name="maximize_button_text" msgid="1650859196290301963">"Maksimér"</string> diff --git a/libs/WindowManager/Shell/res/values-de/strings.xml b/libs/WindowManager/Shell/res/values-de/strings.xml index 406bf3e00c04..a579394818b9 100644 --- a/libs/WindowManager/Shell/res/values-de/strings.xml +++ b/libs/WindowManager/Shell/res/values-de/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Probleme mit der Kamera?\nZum Anpassen tippen."</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Das Problem ist nicht behoben?\nZum Rückgängigmachen tippen."</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Keine Probleme mit der Kamera? Zum Schließen tippen."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Mehr sehen und erledigen"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"Weitere App hineinziehen, um den Bildschirm zu teilen"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Außerhalb einer App doppeltippen, um die Position zu ändern"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Ok"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Für weitere Informationen maximieren."</string> <string name="maximize_button_text" msgid="1650859196290301963">"Maximieren"</string> diff --git a/libs/WindowManager/Shell/res/values-el/strings.xml b/libs/WindowManager/Shell/res/values-el/strings.xml index a34acb2b13de..248cff818da6 100644 --- a/libs/WindowManager/Shell/res/values-el/strings.xml +++ b/libs/WindowManager/Shell/res/values-el/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Προβλήματα με την κάμερα;\nΠατήστε για επιδιόρθωση."</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Δεν διορθώθηκε;\nΠατήστε για επαναφορά."</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Δεν αντιμετωπίζετε προβλήματα με την κάμερα; Πατήστε για παράβλεψη."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Δείτε και κάντε περισσότερα"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"Σύρετε σε μια άλλη εφαρμογή για διαχωρισμό οθόνης"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Πατήστε δύο φορές έξω από μια εφαρμογή για να αλλάξετε τη θέση της"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Το κατάλαβα"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Ανάπτυξη για περισσότερες πληροφορίες."</string> <string name="maximize_button_text" msgid="1650859196290301963">"Μεγιστοποίηση"</string> diff --git a/libs/WindowManager/Shell/res/values-es-rUS/strings.xml b/libs/WindowManager/Shell/res/values-es-rUS/strings.xml index 2482584f76a3..08a7f49f3dfd 100644 --- a/libs/WindowManager/Shell/res/values-es-rUS/strings.xml +++ b/libs/WindowManager/Shell/res/values-es-rUS/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"¿Tienes problemas con la cámara?\nPresiona para reajustarla"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"¿No se resolvió?\nPresiona para revertir los cambios"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"¿No tienes problemas con la cámara? Presionar para descartar."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Aprovecha más"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"Arrastra otra app para el modo de pantalla dividida"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Presiona dos veces fuera de una app para cambiar su ubicación"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Entendido"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Expande para obtener más información."</string> <string name="maximize_button_text" msgid="1650859196290301963">"Maximizar"</string> diff --git a/libs/WindowManager/Shell/res/values-es/strings.xml b/libs/WindowManager/Shell/res/values-es/strings.xml index 0aa35beb88ba..139232cc808f 100644 --- a/libs/WindowManager/Shell/res/values-es/strings.xml +++ b/libs/WindowManager/Shell/res/values-es/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"¿Problemas con la cámara?\nToca para reajustar"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"¿No se ha solucionado?\nToca para revertir"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"¿No hay problemas con la cámara? Toca para cerrar."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Consulta más información y haz más"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"Arrastra otra aplicación para activar la pantalla dividida"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Toca dos veces fuera de una aplicación para cambiarla de posición"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Entendido"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Mostrar más información"</string> <string name="maximize_button_text" msgid="1650859196290301963">"Maximizar"</string> diff --git a/libs/WindowManager/Shell/res/values-et/strings.xml b/libs/WindowManager/Shell/res/values-et/strings.xml index c9e53c73b4b3..d6f35807d290 100644 --- a/libs/WindowManager/Shell/res/values-et/strings.xml +++ b/libs/WindowManager/Shell/res/values-et/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Kas teil on kaameraprobleeme?\nPuudutage ümberpaigutamiseks."</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Kas probleemi ei lahendatud?\nPuudutage ennistamiseks."</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Kas kaameraprobleeme pole? Puudutage loobumiseks."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Vaadake ja tehke rohkem"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"Lohistage muusse rakendusse, et jagatud ekraanikuva kasutada"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Topeltpuudutage rakendusest väljaspool, et selle asendit muuta"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Selge"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Laiendage lisateabe saamiseks."</string> <string name="maximize_button_text" msgid="1650859196290301963">"Maksimeeri"</string> diff --git a/libs/WindowManager/Shell/res/values-eu/strings.xml b/libs/WindowManager/Shell/res/values-eu/strings.xml index 888b0866a2c2..e0efadd6f735 100644 --- a/libs/WindowManager/Shell/res/values-eu/strings.xml +++ b/libs/WindowManager/Shell/res/values-eu/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Arazoak dauzkazu kamerarekin?\nBerriro doitzeko, sakatu hau."</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Ez al da konpondu?\nLeheneratzeko, sakatu hau."</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Ez daukazu arazorik kamerarekin? Baztertzeko, sakatu hau."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Ikusi eta egin gauza gehiago"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"Pantaila zatituta ikusteko, arrastatu beste aplikazio bat"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Aplikazioaren posizioa aldatzeko, sakatu birritan haren kanpoaldea"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Ados"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Informazio gehiago lortzeko, zabaldu hau."</string> <string name="maximize_button_text" msgid="1650859196290301963">"Maximizatu"</string> diff --git a/libs/WindowManager/Shell/res/values-fa/strings.xml b/libs/WindowManager/Shell/res/values-fa/strings.xml index 1d137d1981f5..267dd2050cfa 100644 --- a/libs/WindowManager/Shell/res/values-fa/strings.xml +++ b/libs/WindowManager/Shell/res/values-fa/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"دوربین مشکل دارد؟\nبرای تنظیم مجدد اندازه ضربه بزنید"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"مشکل برطرف نشد؟\nبرای برگرداندن ضربه بزنید"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"دوربین مشکلی ندارد؟ برای بستن ضربه بزنید."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"از چندین برنامه بهطور همزمان استفاده کنید"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"برای حالت صفحهٔ دونیمه، در برنامهای دیگر بکشید"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"برای جابهجا کردن برنامه، بیرون از آن دوضربه بزنید"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"متوجهام"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"برای اطلاعات بیشتر، گسترده کنید."</string> <string name="maximize_button_text" msgid="1650859196290301963">"بزرگ کردن"</string> diff --git a/libs/WindowManager/Shell/res/values-fi/strings.xml b/libs/WindowManager/Shell/res/values-fi/strings.xml index 0c044897e286..30321a20c643 100644 --- a/libs/WindowManager/Shell/res/values-fi/strings.xml +++ b/libs/WindowManager/Shell/res/values-fi/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Onko kameran kanssa ongelmia?\nKorjaa napauttamalla"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Eikö ongelma ratkennut?\nKumoa napauttamalla"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Ei ongelmia kameran kanssa? Hylkää napauttamalla."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Näe ja tee enemmän"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"Käytä jaettua näyttöä vetämällä tähän toinen sovellus"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Kaksoisnapauta sovelluksen ulkopuolella, jos haluat siirtää sitä"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Katso lisätietoja laajentamalla."</string> <string name="maximize_button_text" msgid="1650859196290301963">"Suurenna"</string> diff --git a/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml b/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml index 34037bf42f80..12789975fb5e 100644 --- a/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml +++ b/libs/WindowManager/Shell/res/values-fr-rCA/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problèmes d\'appareil photo?\nTouchez pour réajuster"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Problème non résolu?\nTouchez pour rétablir"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Aucun problème d\'appareil photo? Touchez pour ignorer."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Voir et en faire plus"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"Faites glisser une autre application pour utiliser l\'écran partagé"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Touchez deux fois à côté d\'une application pour la repositionner"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Développer pour en savoir plus."</string> <string name="maximize_button_text" msgid="1650859196290301963">"Agrandir"</string> diff --git a/libs/WindowManager/Shell/res/values-fr/strings.xml b/libs/WindowManager/Shell/res/values-fr/strings.xml index d717268353c6..84c861896443 100644 --- a/libs/WindowManager/Shell/res/values-fr/strings.xml +++ b/libs/WindowManager/Shell/res/values-fr/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problèmes d\'appareil photo ?\nAppuyez pour réajuster"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Problème non résolu ?\nAppuyez pour rétablir"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Aucun problème d\'appareil photo ? Appuyez pour ignorer."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Voir et interagir plus"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"Faites glisser une autre appli pour utiliser l\'écran partagé"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Appuyez deux fois en dehors d\'une appli pour la repositionner"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Développez pour obtenir plus d\'informations"</string> <string name="maximize_button_text" msgid="1650859196290301963">"Agrandir"</string> diff --git a/libs/WindowManager/Shell/res/values-gl/strings.xml b/libs/WindowManager/Shell/res/values-gl/strings.xml index d5500a1f1887..59ec2deab17c 100644 --- a/libs/WindowManager/Shell/res/values-gl/strings.xml +++ b/libs/WindowManager/Shell/res/values-gl/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Tes problemas coa cámara?\nToca para reaxustala"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Non se solucionaron os problemas?\nToca para reverter o seu tratamento"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Non hai problemas coa cámara? Tocar para ignorar."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Ver e facer máis"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"Arrastra outra aplicación para usar a pantalla dividida"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Toca dúas veces fóra da aplicación para cambiala de posición"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Entendido"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Despregar para obter máis información."</string> <string name="maximize_button_text" msgid="1650859196290301963">"Maximizar"</string> diff --git a/libs/WindowManager/Shell/res/values-gu/strings.xml b/libs/WindowManager/Shell/res/values-gu/strings.xml index e48f62b0b4be..85d98ed2fc7b 100644 --- a/libs/WindowManager/Shell/res/values-gu/strings.xml +++ b/libs/WindowManager/Shell/res/values-gu/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"કૅમેરામાં સમસ્યાઓ છે?\nફરીથી ફિટ કરવા માટે ટૅપ કરો"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"સુધારો નથી થયો?\nપહેલાંના પર પાછું ફેરવવા માટે ટૅપ કરો"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"કૅમેરામાં કોઈ સમસ્યા નથી? છોડી દેવા માટે ટૅપ કરો."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"જુઓ અને બીજું ઘણું કરો"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"સ્ક્રીન વિભાજન માટે કોઈ અન્ય ઍપમાં ખેંચો"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"કોઈ ઍપની જગ્યા બદલવા માટે, તેની બહાર બે વાર ટૅપ કરો"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"સમજાઈ ગયું"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"વધુ માહિતી માટે મોટું કરો."</string> <string name="maximize_button_text" msgid="1650859196290301963">"મોટું કરો"</string> diff --git a/libs/WindowManager/Shell/res/values-hi/strings.xml b/libs/WindowManager/Shell/res/values-hi/strings.xml index 43c9894a08fa..bd90b7ea9220 100644 --- a/libs/WindowManager/Shell/res/values-hi/strings.xml +++ b/libs/WindowManager/Shell/res/values-hi/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"क्या कैमरे से जुड़ी कोई समस्या है?\nफिर से फ़िट करने के लिए टैप करें"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"क्या समस्या ठीक नहीं हुई?\nपहले जैसा करने के लिए टैप करें"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"क्या कैमरे से जुड़ी कोई समस्या नहीं है? खारिज करने के लिए टैप करें."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"पूरी जानकारी लेकर, बेहतर तरीके से काम करें"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"स्प्लिट स्क्रीन के लिए, दूसरे ऐप्लिकेशन को खींचें और छोड़ें"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"किसी ऐप्लिकेशन की जगह बदलने के लिए, उसके बाहर दो बार टैप करें"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"ठीक है"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"ज़्यादा जानकारी के लिए बड़ा करें."</string> <string name="maximize_button_text" msgid="1650859196290301963">"बड़ा करें"</string> diff --git a/libs/WindowManager/Shell/res/values-hr/strings.xml b/libs/WindowManager/Shell/res/values-hr/strings.xml index 951901b32640..41df0df1ee87 100644 --- a/libs/WindowManager/Shell/res/values-hr/strings.xml +++ b/libs/WindowManager/Shell/res/values-hr/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problemi s fotoaparatom?\nDodirnite za popravak"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Problem nije riješen?\nDodirnite za vraćanje"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Nemate problema s fotoaparatom? Dodirnite za odbacivanje."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Gledajte i učinite više"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"Povucite drugu aplikaciju unutra da biste podijelili zaslon"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Dvaput dodirnite izvan aplikacije da biste je premjestili"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Shvaćam"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Proširite da biste saznali više."</string> <string name="maximize_button_text" msgid="1650859196290301963">"Maksimiziraj"</string> diff --git a/libs/WindowManager/Shell/res/values-hu/strings.xml b/libs/WindowManager/Shell/res/values-hu/strings.xml index bfe1849f2dde..9736a69f4001 100644 --- a/libs/WindowManager/Shell/res/values-hu/strings.xml +++ b/libs/WindowManager/Shell/res/values-hu/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Kamerával kapcsolatos problémába ütközött?\nKoppintson a megoldáshoz."</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Nem sikerült a hiba kijavítása?\nKoppintson a visszaállításhoz."</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Nincsenek problémái kamerával? Koppintson az elvetéshez."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Több mindent láthat és tehet"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"Húzzon ide egy másik alkalmazást az osztott képernyő használatához"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Koppintson duplán az alkalmazáson kívül az áthelyezéséhez"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Értem"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Kibontással további információkhoz juthat."</string> <string name="maximize_button_text" msgid="1650859196290301963">"Teljes méret"</string> diff --git a/libs/WindowManager/Shell/res/values-hy/strings.xml b/libs/WindowManager/Shell/res/values-hy/strings.xml index b5b37e2ca71e..3c6449421dec 100644 --- a/libs/WindowManager/Shell/res/values-hy/strings.xml +++ b/libs/WindowManager/Shell/res/values-hy/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Տեսախցիկի հետ կապված խնդիրնե՞ր կան։\nՀպեք՝ վերակարգավորելու համար։"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Չհաջողվե՞ց շտկել։\nՀպեք՝ փոփոխությունները չեղարկելու համար։"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Տեսախցիկի հետ կապված խնդիրներ չկա՞ն։ Փակելու համար հպեք։"</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Միաժամանակ կատարեք մի քանի առաջադրանք"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"Քաշեք մյուս հավելվածի մեջ՝ էկրանի տրոհումն օգտագործելու համար"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Կրկնակի հպեք հավելվածի կողքին՝ այն տեղափոխելու համար"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Եղավ"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Ծավալեք՝ ավելին իմանալու համար։"</string> <string name="maximize_button_text" msgid="1650859196290301963">"Ծավալել"</string> diff --git a/libs/WindowManager/Shell/res/values-in/strings.xml b/libs/WindowManager/Shell/res/values-in/strings.xml index fed0215e20e1..61f39036320c 100644 --- a/libs/WindowManager/Shell/res/values-in/strings.xml +++ b/libs/WindowManager/Shell/res/values-in/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Masalah kamera?\nKetuk untuk memperbaiki"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Tidak dapat diperbaiki?\nKetuk untuk mengembalikan"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Tidak ada masalah kamera? Ketuk untuk menutup."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Lihat dan lakukan lebih banyak hal"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"Tarik aplikasi lain untuk menggunakan layar terpisah"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Ketuk dua kali di luar aplikasi untuk mengubah posisinya"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Oke"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Luaskan untuk melihat informasi selengkapnya."</string> <string name="maximize_button_text" msgid="1650859196290301963">"Maksimalkan"</string> diff --git a/libs/WindowManager/Shell/res/values-is/strings.xml b/libs/WindowManager/Shell/res/values-is/strings.xml index b43aa3b05a0d..044348c94a95 100644 --- a/libs/WindowManager/Shell/res/values-is/strings.xml +++ b/libs/WindowManager/Shell/res/values-is/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Myndavélavesen?\nÝttu til að breyta stærð"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Ennþá vesen?\nÝttu til að afturkalla"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Ekkert myndavélavesen? Ýttu til að hunsa."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Sjáðu og gerðu meira"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"Dragðu annað forrit inn til að nota skjáskiptingu"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Ýttu tvisvar utan við forrit til að færa það"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Ég skil"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Stækka til að sjá frekari upplýsingar."</string> <string name="maximize_button_text" msgid="1650859196290301963">"Stækka"</string> diff --git a/libs/WindowManager/Shell/res/values-it/strings.xml b/libs/WindowManager/Shell/res/values-it/strings.xml index ed2f2ac379ed..ca97693481cb 100644 --- a/libs/WindowManager/Shell/res/values-it/strings.xml +++ b/libs/WindowManager/Shell/res/values-it/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problemi con la fotocamera?\nTocca per risolverli"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Il problema non si è risolto?\nTocca per ripristinare"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Nessun problema con la fotocamera? Tocca per ignorare."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Visualizza più contenuti e fai di più"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"Trascina in un\'altra app per usare lo schermo diviso"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Tocca due volte fuori da un\'app per riposizionarla"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Espandi per avere ulteriori informazioni."</string> <string name="maximize_button_text" msgid="1650859196290301963">"Ingrandisci"</string> diff --git a/libs/WindowManager/Shell/res/values-iw/strings.xml b/libs/WindowManager/Shell/res/values-iw/strings.xml index 246fcc0b6c10..67de8a0fde34 100644 --- a/libs/WindowManager/Shell/res/values-iw/strings.xml +++ b/libs/WindowManager/Shell/res/values-iw/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"בעיות במצלמה?\nאפשר להקיש כדי לבצע התאמה מחדש"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"הבעיה לא נפתרה?\nאפשר להקיש כדי לחזור לגרסה הקודמת"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"אין בעיות במצלמה? אפשר להקיש כדי לסגור."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"רוצה לראות ולעשות יותר?"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"צריך לגרור אפליקציה אחרת כדי להשתמש במסך מפוצל"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"צריך להקיש הקשה כפולה מחוץ לאפליקציה כדי למקם אותה מחדש"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"הבנתי"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"מרחיבים כדי לקבל מידע נוסף."</string> <string name="maximize_button_text" msgid="1650859196290301963">"הגדלה"</string> diff --git a/libs/WindowManager/Shell/res/values-ja/strings.xml b/libs/WindowManager/Shell/res/values-ja/strings.xml index beb13c4d858d..cc8527e73636 100644 --- a/libs/WindowManager/Shell/res/values-ja/strings.xml +++ b/libs/WindowManager/Shell/res/values-ja/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"カメラに関する問題の場合は、\nタップすると修正できます"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"修正されなかった場合は、\nタップすると元に戻ります"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"カメラに関する問題でない場合は、タップすると閉じます。"</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"表示を拡大して機能を強化"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"分割画面にするにはもう 1 つのアプリをドラッグしてください"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"位置を変えるにはアプリの外側をダブルタップしてください"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"開くと詳細が表示されます。"</string> <string name="maximize_button_text" msgid="1650859196290301963">"最大化"</string> diff --git a/libs/WindowManager/Shell/res/values-ka/strings.xml b/libs/WindowManager/Shell/res/values-ka/strings.xml index 86d47cd07d71..0ef4563b7a8a 100644 --- a/libs/WindowManager/Shell/res/values-ka/strings.xml +++ b/libs/WindowManager/Shell/res/values-ka/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"კამერად პრობლემები აქვს?\nშეეხეთ გამოსასწორებლად"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"არ გამოსწორდა?\nშეეხეთ წინა ვერსიის დასაბრუნებლად"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"კამერას პრობლემები არ აქვს? შეეხეთ უარყოფისთვის."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"მეტის ნახვა და გაკეთება"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"ეკრანის გასაყოფად ჩავლებით გადაიტანეთ სხვა აპში"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"ორმაგად შეეხეთ აპის გარშემო სივრცეს, რათა ის სხვაგან გადაიტანოთ"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"გასაგებია"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"დამატებითი ინფორმაციისთვის გააფართოეთ."</string> <string name="maximize_button_text" msgid="1650859196290301963">"მაქსიმალურად გაშლა"</string> diff --git a/libs/WindowManager/Shell/res/values-kk/strings.xml b/libs/WindowManager/Shell/res/values-kk/strings.xml index 31bb209f8e59..6ba9a68943cf 100644 --- a/libs/WindowManager/Shell/res/values-kk/strings.xml +++ b/libs/WindowManager/Shell/res/values-kk/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Камерада қателер шықты ма?\nЖөндеу үшін түртіңіз."</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Жөнделмеді ме?\nҚайтару үшін түртіңіз."</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Камерада қателер шықпады ма? Жабу үшін түртіңіз."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Қосымша ақпаратты қарап, әрекеттер жасау"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"Экранды бөлу үшін басқа қолданбаға сүйреңіз."</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Қолданбаның орнын өзгерту үшін одан тыс жерді екі рет түртіңіз."</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Түсінікті"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Толығырақ ақпарат алу үшін терезені жайыңыз."</string> <string name="maximize_button_text" msgid="1650859196290301963">"Жаю"</string> diff --git a/libs/WindowManager/Shell/res/values-km/strings.xml b/libs/WindowManager/Shell/res/values-km/strings.xml index 38bbbd8504fa..03682d800e50 100644 --- a/libs/WindowManager/Shell/res/values-km/strings.xml +++ b/libs/WindowManager/Shell/res/values-km/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"មានបញ្ហាពាក់ព័ន្ធនឹងកាមេរ៉ាឬ?\nចុចដើម្បីដោះស្រាយ"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"មិនបានដោះស្រាយបញ្ហានេះទេឬ?\nចុចដើម្បីត្រឡប់"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"មិនមានបញ្ហាពាក់ព័ន្ធនឹងកាមេរ៉ាទេឬ? ចុចដើម្បីច្រានចោល។"</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"មើលឃើញ និងធ្វើបានកាន់តែច្រើន"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"អូសកម្មវិធីមួយទៀតចូល ដើម្បីប្រើមុខងារបំបែកអេក្រង់"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"ចុចពីរដងនៅក្រៅកម្មវិធី ដើម្បីប្ដូរទីតាំងកម្មវិធីនោះ"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"យល់ហើយ"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"ពង្រីកដើម្បីទទួលបានព័ត៌មានបន្ថែម។"</string> <string name="maximize_button_text" msgid="1650859196290301963">"ពង្រីក"</string> diff --git a/libs/WindowManager/Shell/res/values-kn/strings.xml b/libs/WindowManager/Shell/res/values-kn/strings.xml index 2d0656ee1373..167a38e09c60 100644 --- a/libs/WindowManager/Shell/res/values-kn/strings.xml +++ b/libs/WindowManager/Shell/res/values-kn/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"ಕ್ಯಾಮರಾ ಸಮಸ್ಯೆಗಳಿವೆಯೇ?\nಮರುಹೊಂದಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"ಅದನ್ನು ಸರಿಪಡಿಸಲಿಲ್ಲವೇ?\nಹಿಂತಿರುಗಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"ಕ್ಯಾಮರಾ ಸಮಸ್ಯೆಗಳಿಲ್ಲವೇ? ವಜಾಗೊಳಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"ನೋಡಿ ಮತ್ತು ಹೆಚ್ಚಿನದನ್ನು ಮಾಡಿ"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"ಸ್ಪ್ಲಿಟ್ ಸ್ಕ್ರೀನ್ಗಾಗಿ ಮತ್ತೊಂದು ಆ್ಯಪ್ನಲ್ಲಿ ಎಳೆಯಿರಿ"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"ಆ್ಯಪ್ ಒಂದರ ಸ್ಥಾನವನ್ನು ಬದಲಾಯಿಸಲು ಅದರ ಹೊರಗೆ ಡಬಲ್-ಟ್ಯಾಪ್ ಮಾಡಿ"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"ಸರಿ"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"ಇನ್ನಷ್ಟು ಮಾಹಿತಿಗಾಗಿ ವಿಸ್ತೃತಗೊಳಿಸಿ."</string> <string name="maximize_button_text" msgid="1650859196290301963">"ಹಿಗ್ಗಿಸಿ"</string> diff --git a/libs/WindowManager/Shell/res/values-ko/strings.xml b/libs/WindowManager/Shell/res/values-ko/strings.xml index dadf3f6f8b90..1175a0e884a4 100644 --- a/libs/WindowManager/Shell/res/values-ko/strings.xml +++ b/libs/WindowManager/Shell/res/values-ko/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"카메라 문제가 있나요?\n해결하려면 탭하세요."</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"해결되지 않았나요?\n되돌리려면 탭하세요."</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"카메라에 문제가 없나요? 닫으려면 탭하세요."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"더 많은 정보를 보고 더 많은 작업을 처리하세요"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"화면 분할을 사용하려면 다른 앱을 드래그해 가져옵니다."</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"앱 위치를 조정하려면 앱 외부를 두 번 탭합니다."</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"확인"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"추가 정보는 펼쳐서 확인하세요."</string> <string name="maximize_button_text" msgid="1650859196290301963">"최대화"</string> diff --git a/libs/WindowManager/Shell/res/values-ky/strings.xml b/libs/WindowManager/Shell/res/values-ky/strings.xml index edd13d58db7c..b047863bdcf6 100644 --- a/libs/WindowManager/Shell/res/values-ky/strings.xml +++ b/libs/WindowManager/Shell/res/values-ky/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Камерада маселелер келип чыктыбы?\nОңдоо үчүн таптаңыз"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Оңдолгон жокпу?\nАртка кайтаруу үчүн таптаңыз"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Камерада маселе жокпу? Этибарга албоо үчүн таптаңыз."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Көрүп, көбүрөөк нерселерди жасаңыз"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"Экранды бөлүү үчүн башка колдонмону сүйрөңүз"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Колдонмону жылдыруу үчүн сырт жагын эки жолу таптаңыз"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Түшүндүм"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Толук маалымат алуу үчүн жайып көрүңүз."</string> <string name="maximize_button_text" msgid="1650859196290301963">"Чоңойтуу"</string> diff --git a/libs/WindowManager/Shell/res/values-lo/strings.xml b/libs/WindowManager/Shell/res/values-lo/strings.xml index 8d54e486e491..00bf7f4c7983 100644 --- a/libs/WindowManager/Shell/res/values-lo/strings.xml +++ b/libs/WindowManager/Shell/res/values-lo/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"ມີບັນຫາກ້ອງຖ່າຍຮູບບໍ?\nແຕະເພື່ອປັບໃໝ່"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"ບໍ່ໄດ້ແກ້ໄຂມັນບໍ?\nແຕະເພື່ອແປງກັບຄືນ"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"ບໍ່ມີບັນຫາກ້ອງຖ່າຍຮູບບໍ? ແຕະເພື່ອປິດໄວ້."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"ເບິ່ງ ແລະ ເຮັດຫຼາຍຂຶ້ນ"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"ລາກແອັບອື່ນເຂົ້າມາເພື່ອແບ່ງໜ້າຈໍ"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"ແຕະສອງເທື່ອໃສ່ນອກແອັບໃດໜຶ່ງເພື່ອຈັດຕຳແໜ່ງຂອງມັນຄືນໃໝ່"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"ເຂົ້າໃຈແລ້ວ"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"ຂະຫຍາຍເພື່ອເບິ່ງຂໍ້ມູນເພີ່ມເຕີມ."</string> <string name="maximize_button_text" msgid="1650859196290301963">"ຂະຫຍາຍໃຫຍ່ສຸດ"</string> diff --git a/libs/WindowManager/Shell/res/values-lt/strings.xml b/libs/WindowManager/Shell/res/values-lt/strings.xml index a7a5e55dca63..39817930f308 100644 --- a/libs/WindowManager/Shell/res/values-lt/strings.xml +++ b/libs/WindowManager/Shell/res/values-lt/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Iškilo problemų dėl kameros?\nPalieskite, kad pritaikytumėte iš naujo"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Nepavyko pataisyti?\nPalieskite, kad grąžintumėte"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Nėra jokių problemų dėl kameros? Palieskite, kad atsisakytumėte."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Daugiau turinio ir funkcijų"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"Vilkite kitoje programoje, kad galėtumėte naudoti išskaidyto ekrano režimą"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Dukart palieskite už programos ribų, kad pakeistumėte jos poziciją"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Supratau"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Išskleiskite, jei reikia daugiau informacijos."</string> <string name="maximize_button_text" msgid="1650859196290301963">"Padidinti"</string> diff --git a/libs/WindowManager/Shell/res/values-lv/strings.xml b/libs/WindowManager/Shell/res/values-lv/strings.xml index c7f2677250dd..3599c14dcadd 100644 --- a/libs/WindowManager/Shell/res/values-lv/strings.xml +++ b/libs/WindowManager/Shell/res/values-lv/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Vai ir problēmas ar kameru?\nPieskarieties, lai tās novērstu."</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Vai problēma netika novērsta?\nPieskarieties, lai atjaunotu."</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Vai nav problēmu ar kameru? Pieskarieties, lai nerādītu."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Uzziniet un paveiciet vairāk"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"Lai izmantotu sadalītu ekrānu, ievelciet vēl vienu lietotni"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Lai pārvietotu lietotni, veiciet dubultskārienu ārpus lietotnes"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Labi"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Izvērsiet, lai iegūtu plašāku informāciju."</string> <string name="maximize_button_text" msgid="1650859196290301963">"Maksimizēt"</string> diff --git a/libs/WindowManager/Shell/res/values-mk/strings.xml b/libs/WindowManager/Shell/res/values-mk/strings.xml index 7331a6c77186..6c41b0ca0afd 100644 --- a/libs/WindowManager/Shell/res/values-mk/strings.xml +++ b/libs/WindowManager/Shell/res/values-mk/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Проблеми со камерата?\nДопрете за да се совпадне повторно"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Не се поправи?\nДопрете за враќање"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Нема проблеми со камерата? Допрете за отфрлање."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Погледнете и направете повеќе"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"Повлечете во друга апликација за поделен екран"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Допрете двапати надвор од некоја апликација за да ја преместите"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Сфатив"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Проширете за повеќе информации."</string> <string name="maximize_button_text" msgid="1650859196290301963">"Зголеми"</string> diff --git a/libs/WindowManager/Shell/res/values-ml/strings.xml b/libs/WindowManager/Shell/res/values-ml/strings.xml index f548ca5bf73e..76dfc0d944a5 100644 --- a/libs/WindowManager/Shell/res/values-ml/strings.xml +++ b/libs/WindowManager/Shell/res/values-ml/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"ക്യാമറ പ്രശ്നങ്ങളുണ്ടോ?\nശരിയാക്കാൻ ടാപ്പ് ചെയ്യുക"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"അത് പരിഹരിച്ചില്ലേ?\nപുനഃസ്ഥാപിക്കാൻ ടാപ്പ് ചെയ്യുക"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"ക്യാമറാ പ്രശ്നങ്ങളൊന്നുമില്ലേ? നിരസിക്കാൻ ടാപ്പ് ചെയ്യുക."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"കൂടുതൽ കാണുക, ചെയ്യുക"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"സ്ക്രീൻ വിഭജന മോഡിന്, മറ്റൊരു ആപ്പ് വലിച്ചിടുക"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"ആപ്പിന്റെ സ്ഥാനം മാറ്റാൻ അതിന് പുറത്ത് ഡബിൾ ടാപ്പ് ചെയ്യുക"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"മനസ്സിലായി"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"കൂടുതൽ വിവരങ്ങൾക്ക് വികസിപ്പിക്കുക."</string> <string name="maximize_button_text" msgid="1650859196290301963">"വലുതാക്കുക"</string> diff --git a/libs/WindowManager/Shell/res/values-mn/strings.xml b/libs/WindowManager/Shell/res/values-mn/strings.xml index c20255828573..a8bd85ed27f5 100644 --- a/libs/WindowManager/Shell/res/values-mn/strings.xml +++ b/libs/WindowManager/Shell/res/values-mn/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Камерын асуудал гарсан уу?\nДахин тааруулахын тулд товшино уу"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Үүнийг засаагүй юу?\nБуцаахын тулд товшино уу"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Камерын асуудал байхгүй юу? Хаахын тулд товшино уу."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Харж илүү ихийг хий"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"Дэлгэцийг хуваахын тулд өөр апп руу чирнэ үү"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Аппыг дахин байрлуулахын тулд гадна талд нь хоёр товшино"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Ойлголоо"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Нэмэлт мэдээлэл авах бол дэлгэнэ үү."</string> <string name="maximize_button_text" msgid="1650859196290301963">"Томруулах"</string> diff --git a/libs/WindowManager/Shell/res/values-mr/strings.xml b/libs/WindowManager/Shell/res/values-mr/strings.xml index b9131f1cb8fc..5874812d9281 100644 --- a/libs/WindowManager/Shell/res/values-mr/strings.xml +++ b/libs/WindowManager/Shell/res/values-mr/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"कॅमेराशी संबंधित काही समस्या आहेत का?\nपुन्हा फिट करण्यासाठी टॅप करा"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"निराकरण झाले नाही?\nरिव्हर्ट करण्यासाठी कृपया टॅप करा"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"कॅमेराशी संबंधित कोणत्याही समस्या नाहीत का? डिसमिस करण्यासाठी टॅप करा."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"पहा आणि आणखी बरेच काही करा"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"स्प्लिट-स्क्रीन वापरण्यासाठी दुसऱ्या ॲपमध्ये ड्रॅग करा"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"ॲपची स्थिती पुन्हा बदलण्यासाठी, त्याच्या बाहेर दोनदा टॅप करा"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"समजले"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"अधिक माहितीसाठी विस्तार करा."</string> <string name="maximize_button_text" msgid="1650859196290301963">"मोठे करा"</string> diff --git a/libs/WindowManager/Shell/res/values-ms/strings.xml b/libs/WindowManager/Shell/res/values-ms/strings.xml index 6ce08e000222..88270df81660 100644 --- a/libs/WindowManager/Shell/res/values-ms/strings.xml +++ b/libs/WindowManager/Shell/res/values-ms/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Isu kamera?\nKetik untuk memuatkan semula"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Isu tidak dibetulkan?\nKetik untuk kembali"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Tiada isu kamera? Ketik untuk mengetepikan."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Lihat dan lakukan lebih"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"Seret apl lain untuk skrin pisah"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Ketik dua kali di luar apl untuk menempatkan semula apl itu"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Kembangkan untuk mendapatkan maklumat lanjut."</string> <string name="maximize_button_text" msgid="1650859196290301963">"Maksimumkan"</string> diff --git a/libs/WindowManager/Shell/res/values-my/strings.xml b/libs/WindowManager/Shell/res/values-my/strings.xml index d7df4665b38e..9a2d1bad094e 100644 --- a/libs/WindowManager/Shell/res/values-my/strings.xml +++ b/libs/WindowManager/Shell/res/values-my/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"ကင်မရာပြဿနာလား။\nပြင်ဆင်ရန် တို့ပါ"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"ကောင်းမသွားဘူးလား။\nပြန်ပြောင်းရန် တို့ပါ"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"ကင်မရာပြဿနာ မရှိဘူးလား။ ပယ်ရန် တို့ပါ။"</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"ကြည့်ပြီး ပိုမိုလုပ်ဆောင်ပါ"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"မျက်နှာပြင် ခွဲ၍ပြသနိုင်ရန် နောက်အက်ပ်တစ်ခုကို ဖိဆွဲပါ"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"နေရာပြန်ချရန် အက်ပ်အပြင်ဘက်ကို နှစ်ချက်တို့ပါ"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"ရပြီ"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"နောက်ထပ်အချက်အလက်များအတွက် ချဲ့နိုင်သည်။"</string> <string name="maximize_button_text" msgid="1650859196290301963">"ချဲ့ရန်"</string> diff --git a/libs/WindowManager/Shell/res/values-nb/strings.xml b/libs/WindowManager/Shell/res/values-nb/strings.xml index 86e83817a9c9..ec9e635dd9bb 100644 --- a/libs/WindowManager/Shell/res/values-nb/strings.xml +++ b/libs/WindowManager/Shell/res/values-nb/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Har du kameraproblemer?\nTrykk for å tilpasse"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Ble ikke problemet løst?\nTrykk for å gå tilbake"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Har du ingen kameraproblemer? Trykk for å lukke."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Se og gjør mer"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"Dra inn en annen app for å bruke delt skjerm"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Dobbelttrykk utenfor en app for å flytte den"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Greit"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Vis for å få mer informasjon."</string> <string name="maximize_button_text" msgid="1650859196290301963">"Maksimer"</string> diff --git a/libs/WindowManager/Shell/res/values-ne/strings.xml b/libs/WindowManager/Shell/res/values-ne/strings.xml index 3a0cc7616fa1..dc7d98d1f702 100644 --- a/libs/WindowManager/Shell/res/values-ne/strings.xml +++ b/libs/WindowManager/Shell/res/values-ne/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"क्यामेरासम्बन्धी समस्या देखियो?\nसमस्या हल गर्न ट्याप गर्नुहोस्"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"समस्या हल भएन?\nपहिलेको जस्तै बनाउन ट्याप गर्नुहोस्"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"क्यामेरासम्बन्धी कुनै पनि समस्या छैन? खारेज गर्न ट्याप गर्नुहोस्।"</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"थप कुरा हेर्नुहोस् र गर्नुहोस्"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"स्प्लिट स्क्रिन मोड प्रयोग गर्न अर्को एप ड्रयाग एन्ड ड्रप गर्नुहोस्"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"तपाईं जुन एपको स्थिति मिलाउन चाहनुहुन्छ सोही एपको बाहिर डबल ट्याप गर्नुहोस्"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"बुझेँ"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"थप जानकारी प्राप्त गर्न चाहनुहुन्छ भने एक्स्पान्ड गर्नुहोस्।"</string> <string name="maximize_button_text" msgid="1650859196290301963">"ठुलो बनाउनुहोस्"</string> diff --git a/libs/WindowManager/Shell/res/values-nl/strings.xml b/libs/WindowManager/Shell/res/values-nl/strings.xml index cfd7b5fe532c..5bae2a34100c 100644 --- a/libs/WindowManager/Shell/res/values-nl/strings.xml +++ b/libs/WindowManager/Shell/res/values-nl/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Cameraproblemen?\nTik om opnieuw passend te maken."</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Is dit geen oplossing?\nTik om terug te zetten."</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Geen cameraproblemen? Tik om te sluiten."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Zie en doe meer"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"Sleep een andere app hier naartoe om het scherm te splitsen"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Dubbeltik naast een app om deze opnieuw te positioneren"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Uitvouwen voor meer informatie."</string> <string name="maximize_button_text" msgid="1650859196290301963">"Maximaliseren"</string> diff --git a/libs/WindowManager/Shell/res/values-or/strings.xml b/libs/WindowManager/Shell/res/values-or/strings.xml index a24b3a4d6186..c5ef4f10ce39 100644 --- a/libs/WindowManager/Shell/res/values-or/strings.xml +++ b/libs/WindowManager/Shell/res/values-or/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"କ୍ୟାମେରାରେ ସମସ୍ୟା ଅଛି?\nପୁଣି ଫିଟ କରିବାକୁ ଟାପ କରନ୍ତୁ"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"ଏହାର ସମାଧାନ ହୋଇନାହିଁ?\nଫେରିଯିବା ପାଇଁ ଟାପ କରନ୍ତୁ"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"କ୍ୟାମେରାରେ କିଛି ସମସ୍ୟା ନାହିଁ? ଖାରଜ କରିବାକୁ ଟାପ କରନ୍ତୁ।"</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"ଦେଖନ୍ତୁ ଏବଂ ଆହୁରି ଅନେକ କିଛି କରନ୍ତୁ"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"ସ୍ପ୍ଲିଟ-ସ୍କ୍ରିନ ପାଇଁ ଅନ୍ୟ ଏକ ଆପକୁ ଡ୍ରାଗ କରନ୍ତୁ"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"ଏକ ଆପକୁ ରିପୋଜିସନ କରିବା ପାଇଁ ଏହାର ବାହାରେ ଦୁଇଥର-ଟାପ କରନ୍ତୁ"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"ବୁଝିଗଲି"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"ଅଧିକ ସୂଚନା ପାଇଁ ବିସ୍ତାର କରନ୍ତୁ।"</string> <string name="maximize_button_text" msgid="1650859196290301963">"ବଡ଼ କରନ୍ତୁ"</string> diff --git a/libs/WindowManager/Shell/res/values-pa/strings.xml b/libs/WindowManager/Shell/res/values-pa/strings.xml index 5777a9603d56..f0262052513c 100644 --- a/libs/WindowManager/Shell/res/values-pa/strings.xml +++ b/libs/WindowManager/Shell/res/values-pa/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"ਕੀ ਕੈਮਰੇ ਸੰਬੰਧੀ ਸਮੱਸਿਆਵਾਂ ਹਨ?\nਮੁੜ-ਫਿੱਟ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"ਕੀ ਇਹ ਠੀਕ ਨਹੀਂ ਹੋਈ?\nਵਾਪਸ ਉਹੀ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"ਕੀ ਕੈਮਰੇ ਸੰਬੰਧੀ ਕੋਈ ਸਮੱਸਿਆ ਨਹੀਂ ਹੈ? ਖਾਰਜ ਕਰਨ ਲਈ ਟੈਪ ਕਰੋ।"</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"ਦੇਖੋ ਅਤੇ ਹੋਰ ਬਹੁਤ ਕੁਝ ਕਰੋ"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"ਸਪਲਿਟ ਸਕ੍ਰੀਨ ਦੇ ਲਈ ਕਿਸੇ ਹੋਰ ਐਪ ਵਿੱਚ ਘਸੀਟੋ"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"ਕਿਸੇ ਐਪ ਦੀ ਜਗ੍ਹਾ ਬਦਲਣ ਲਈ ਉਸ ਦੇ ਬਾਹਰ ਡਬਲ ਟੈਪ ਕਰੋ"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"ਸਮਝ ਲਿਆ"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"ਹੋਰ ਜਾਣਕਾਰੀ ਲਈ ਵਿਸਤਾਰ ਕਰੋ।"</string> <string name="maximize_button_text" msgid="1650859196290301963">"ਵੱਡਾ ਕਰੋ"</string> diff --git a/libs/WindowManager/Shell/res/values-pl/strings.xml b/libs/WindowManager/Shell/res/values-pl/strings.xml index ce498b2097d8..22c0c37002c9 100644 --- a/libs/WindowManager/Shell/res/values-pl/strings.xml +++ b/libs/WindowManager/Shell/res/values-pl/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problemy z aparatem?\nKliknij, aby dopasować"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Naprawa się nie udała?\nKliknij, aby cofnąć"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Brak problemów z aparatem? Kliknij, aby zamknąć"</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Zobacz i zrób więcej"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"Przeciągnij drugą aplikację, aby podzielić ekran"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Kliknij dwukrotnie poza aplikacją, aby ją przenieść"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Rozwiń, aby wyświetlić więcej informacji."</string> <string name="maximize_button_text" msgid="1650859196290301963">"Maksymalizuj"</string> diff --git a/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml b/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml index 4e1995680bbe..0bbffb3182b5 100644 --- a/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml +++ b/libs/WindowManager/Shell/res/values-pt-rBR/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problemas com a câmera?\nToque para ajustar o enquadramento"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"O problema não foi corrigido?\nToque para reverter"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Não tem problemas com a câmera? Toque para dispensar."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Veja e faça mais"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"Arraste outro app para a tela dividida"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Toque duas vezes fora de um app para reposicionar"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Entendi"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Abra para ver mais informações."</string> <string name="maximize_button_text" msgid="1650859196290301963">"Maximizar"</string> diff --git a/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml b/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml index 42156276136d..07dd4d73ebd3 100644 --- a/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml +++ b/libs/WindowManager/Shell/res/values-pt-rPT/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problemas com a câmara?\nToque aqui para reajustar"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Não foi corrigido?\nToque para reverter"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Nenhum problema com a câmara? Toque para ignorar."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Veja e faça mais"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"Arraste outra app para usar o ecrã dividido"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Toque duas vezes fora de uma app para a reposicionar"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Expandir para obter mais informações"</string> <string name="maximize_button_text" msgid="1650859196290301963">"Maximizar"</string> diff --git a/libs/WindowManager/Shell/res/values-pt/strings.xml b/libs/WindowManager/Shell/res/values-pt/strings.xml index 4e1995680bbe..0bbffb3182b5 100644 --- a/libs/WindowManager/Shell/res/values-pt/strings.xml +++ b/libs/WindowManager/Shell/res/values-pt/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problemas com a câmera?\nToque para ajustar o enquadramento"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"O problema não foi corrigido?\nToque para reverter"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Não tem problemas com a câmera? Toque para dispensar."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Veja e faça mais"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"Arraste outro app para a tela dividida"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Toque duas vezes fora de um app para reposicionar"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Entendi"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Abra para ver mais informações."</string> <string name="maximize_button_text" msgid="1650859196290301963">"Maximizar"</string> diff --git a/libs/WindowManager/Shell/res/values-ro/strings.xml b/libs/WindowManager/Shell/res/values-ro/strings.xml index 535b021ae8e6..3ec4f1b1264c 100644 --- a/libs/WindowManager/Shell/res/values-ro/strings.xml +++ b/libs/WindowManager/Shell/res/values-ro/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Aveți probleme cu camera foto?\nAtingeți pentru a reîncadra"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Nu ați remediat problema?\nAtingeți pentru a reveni"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Nu aveți probleme cu camera foto? Atingeți pentru a închide."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Vezi și fă mai multe"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"Trage în altă aplicație pentru a folosi ecranul împărțit"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Atinge de două ori lângă o aplicație pentru a o repoziționa"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Extindeți pentru mai multe informații"</string> <string name="maximize_button_text" msgid="1650859196290301963">"Maximizați"</string> diff --git a/libs/WindowManager/Shell/res/values-ru/strings.xml b/libs/WindowManager/Shell/res/values-ru/strings.xml index e094b6b0e88c..f1ff000ebc4c 100644 --- a/libs/WindowManager/Shell/res/values-ru/strings.xml +++ b/libs/WindowManager/Shell/res/values-ru/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Проблемы с камерой?\nНажмите, чтобы исправить."</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Не помогло?\nНажмите, чтобы отменить изменения."</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Нет проблем с камерой? Нажмите, чтобы закрыть."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Выполняйте несколько задач одновременно"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"Перетащите сюда другое приложение, чтобы использовать разделение экрана."</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Чтобы переместить приложение, дважды нажмите рядом с ним."</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"ОК"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Развернуть, чтобы узнать больше."</string> <string name="maximize_button_text" msgid="1650859196290301963">"Развернуть"</string> diff --git a/libs/WindowManager/Shell/res/values-si/strings.xml b/libs/WindowManager/Shell/res/values-si/strings.xml index d52b8f606be4..39bd260c2901 100644 --- a/libs/WindowManager/Shell/res/values-si/strings.xml +++ b/libs/WindowManager/Shell/res/values-si/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"කැමරා ගැටලුද?\nයළි සවි කිරීමට තට්ටු කරන්න"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"එය විසඳුවේ නැතිද?\nප්රතිවර්තනය කිරීමට තට්ටු කරන්න"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"කැමරා ගැටලු නොමැතිද? ඉවත දැමීමට තට්ටු කරන්න"</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"බලන්න සහ තවත් දේ කරන්න"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"බෙදුම් තිරය සඳහා වෙනත් යෙදුමකට අදින්න"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"යෙදුමක් නැවත ස්ථානගත කිරීමට පිටතින් දෙවරක් තට්ටු කරන්න"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"තේරුණා"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"වැඩිදුර තොරතුරු සඳහා දිග හරින්න"</string> <string name="maximize_button_text" msgid="1650859196290301963">"විහිදන්න"</string> diff --git a/libs/WindowManager/Shell/res/values-sk/strings.xml b/libs/WindowManager/Shell/res/values-sk/strings.xml index 0dc8af5e6543..88592315a53c 100644 --- a/libs/WindowManager/Shell/res/values-sk/strings.xml +++ b/libs/WindowManager/Shell/res/values-sk/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problémy s kamerou?\nKlepnutím znova upravte."</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Nevyriešilo sa to?\nKlepnutím sa vráťte."</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Nemáte problémy s kamerou? Klepnutím zatvoríte."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Zobrazte si a zvládnite toho viac"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"Rozdelenú obrazovku aktivujete presunutím ďalšie aplikácie"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Dvojitým klepnutím mimo aplikácie zmeníte jej pozíciu"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Dobre"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Po rozbalení sa dozviete viac."</string> <string name="maximize_button_text" msgid="1650859196290301963">"Maximalizovať"</string> diff --git a/libs/WindowManager/Shell/res/values-sl/strings.xml b/libs/WindowManager/Shell/res/values-sl/strings.xml index 49902da7546e..22fe0f8bc657 100644 --- a/libs/WindowManager/Shell/res/values-sl/strings.xml +++ b/libs/WindowManager/Shell/res/values-sl/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Težave s fotoaparatom?\nDotaknite se za vnovično prilagoditev"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"To ni odpravilo težave?\nDotaknite se za povrnitev"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Nimate težav s fotoaparatom? Dotaknite se za opustitev."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Oglejte si in naredite več"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"Za razdeljeni zaslon povlecite sem še eno aplikacijo."</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Dvakrat se dotaknite zunaj aplikacije, če jo želite prestaviti."</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"V redu"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Razširitev za več informacij"</string> <string name="maximize_button_text" msgid="1650859196290301963">"Maksimiraj"</string> diff --git a/libs/WindowManager/Shell/res/values-sq/strings.xml b/libs/WindowManager/Shell/res/values-sq/strings.xml index 765a6d95f470..2a3671b85d0d 100644 --- a/libs/WindowManager/Shell/res/values-sq/strings.xml +++ b/libs/WindowManager/Shell/res/values-sq/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Ka probleme me kamerën?\nTrokit për ta ripërshtatur"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Nuk u rregullua?\nTrokit për ta rikthyer"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Nuk ka probleme me kamerën? Trokit për ta shpërfillur."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Shiko dhe bëj më shumë"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"Zvarrite në një aplikacion tjetër për ekranin e ndarë"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Trokit dy herë jashtë një aplikacioni për ta ripozicionuar"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"E kuptova"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Zgjeroje për më shumë informacion."</string> <string name="maximize_button_text" msgid="1650859196290301963">"Maksimizo"</string> diff --git a/libs/WindowManager/Shell/res/values-sr/strings.xml b/libs/WindowManager/Shell/res/values-sr/strings.xml index 1d7a122eb056..09471037fde7 100644 --- a/libs/WindowManager/Shell/res/values-sr/strings.xml +++ b/libs/WindowManager/Shell/res/values-sr/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Имате проблема са камером?\nДодирните да бисте поново уклопили"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Проблем није решен?\nДодирните да бисте вратили"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Немате проблема са камером? Додирните да бисте одбацили."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Видите и урадите више"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"Превуците другу апликацију да бисте користили подељени екран"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Двапут додирните изван апликације да бисте променили њену позицију"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Важи"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Проширите за још информација."</string> <string name="maximize_button_text" msgid="1650859196290301963">"Увећајте"</string> diff --git a/libs/WindowManager/Shell/res/values-sv/strings.xml b/libs/WindowManager/Shell/res/values-sv/strings.xml index 90e894df01a3..70282a4b1a4d 100644 --- a/libs/WindowManager/Shell/res/values-sv/strings.xml +++ b/libs/WindowManager/Shell/res/values-sv/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Problem med kameran?\nTryck för att anpassa på nytt"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Löstes inte problemet?\nTryck för att återställa"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Inga problem med kameran? Tryck för att ignorera."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Se och gör mer"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"Dra till en annan app för läget Delad skärm"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Tryck snabbt två gånger utanför en app för att flytta den"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Utöka för mer information."</string> <string name="maximize_button_text" msgid="1650859196290301963">"Utöka"</string> diff --git a/libs/WindowManager/Shell/res/values-sw/strings.xml b/libs/WindowManager/Shell/res/values-sw/strings.xml index e445f2a58001..1aab85c54add 100644 --- a/libs/WindowManager/Shell/res/values-sw/strings.xml +++ b/libs/WindowManager/Shell/res/values-sw/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Je, kuna hitilafu za kamera?\nGusa ili urekebishe"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Umeshindwa kurekebisha?\nGusa ili urejeshe nakala ya awali"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Je, hakuna hitilafu za kamera? Gusa ili uondoe."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Angalia na ufanye zaidi"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"Buruta ndani programu nyingine ili utumie hali ya skrini iliyogawanywa"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Gusa mara mbili nje ya programu ili uihamishe"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Nimeelewa"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Panua ili upate maelezo zaidi."</string> <string name="maximize_button_text" msgid="1650859196290301963">"Panua"</string> diff --git a/libs/WindowManager/Shell/res/values-ta/strings.xml b/libs/WindowManager/Shell/res/values-ta/strings.xml index 2f0ed7dc2c99..befc8eb6f808 100644 --- a/libs/WindowManager/Shell/res/values-ta/strings.xml +++ b/libs/WindowManager/Shell/res/values-ta/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"கேமரா தொடர்பான சிக்கல்களா?\nமீண்டும் பொருத்த தட்டவும்"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"சிக்கல்கள் சரிசெய்யப்படவில்லையா?\nமாற்றியமைக்க தட்டவும்"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"கேமரா தொடர்பான சிக்கல்கள் எதுவும் இல்லையா? நிராகரிக்க தட்டவும்."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"பலவற்றைப் பார்த்தல் மற்றும் செய்தல்"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"திரைப் பிரிப்புக்கு மற்றொரு ஆப்ஸை இழுக்கலாம்"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"ஆப்ஸை இடம் மாற்ற அதன் வெளியில் இருமுறை தட்டலாம்"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"சரி"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"கூடுதல் தகவல்களுக்கு விரிவாக்கலாம்."</string> <string name="maximize_button_text" msgid="1650859196290301963">"பெரிதாக்கும்"</string> diff --git a/libs/WindowManager/Shell/res/values-te/strings.xml b/libs/WindowManager/Shell/res/values-te/strings.xml index 2b38018dff15..88bb13004657 100644 --- a/libs/WindowManager/Shell/res/values-te/strings.xml +++ b/libs/WindowManager/Shell/res/values-te/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"కెమెరా సమస్యలు ఉన్నాయా?\nరీఫిట్ చేయడానికి ట్యాప్ చేయండి"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"దాని సమస్యను పరిష్కరించలేదా?\nపూర్వస్థితికి మార్చడానికి ట్యాప్ చేయండి"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"కెమెరా సమస్యలు లేవా? తీసివేయడానికి ట్యాప్ చేయండి."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"చూసి, మరిన్ని చేయండి"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"స్ప్లిట్-స్క్రీన్ కోసం మరొక యాప్లోకి లాగండి"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"యాప్ స్థానాన్ని మార్చడానికి దాని వెలుపల డబుల్-ట్యాప్ చేయండి"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"అర్థమైంది"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"మరింత సమాచారం కోసం విస్తరించండి."</string> <string name="maximize_button_text" msgid="1650859196290301963">"గరిష్టీకరించండి"</string> diff --git a/libs/WindowManager/Shell/res/values-th/strings.xml b/libs/WindowManager/Shell/res/values-th/strings.xml index f317e4c59d52..63d3bb83832d 100644 --- a/libs/WindowManager/Shell/res/values-th/strings.xml +++ b/libs/WindowManager/Shell/res/values-th/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"หากพบปัญหากับกล้อง\nแตะเพื่อแก้ไข"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"หากไม่ได้แก้ไข\nแตะเพื่อเปลี่ยนกลับ"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"หากไม่พบปัญหากับกล้อง แตะเพื่อปิด"</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"รับชมและทำสิ่งต่างๆ ได้มากขึ้น"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"ลากไปไว้ในแอปอื่นเพื่อแยกหน้าจอ"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"แตะสองครั้งด้านนอกแอปเพื่อเปลี่ยนตำแหน่ง"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"รับทราบ"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"ขยายเพื่อดูข้อมูลเพิ่มเติม"</string> <string name="maximize_button_text" msgid="1650859196290301963">"ขยายใหญ่สุด"</string> diff --git a/libs/WindowManager/Shell/res/values-tl/strings.xml b/libs/WindowManager/Shell/res/values-tl/strings.xml index d12875b915a7..50334f5e772e 100644 --- a/libs/WindowManager/Shell/res/values-tl/strings.xml +++ b/libs/WindowManager/Shell/res/values-tl/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"May mga isyu sa camera?\nI-tap para i-refit"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Hindi ito naayos?\nI-tap para i-revert"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Walang isyu sa camera? I-tap para i-dismiss."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Tumingin at gumawa ng higit pa"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"Mag-drag ng ibang app para sa split screen"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Mag-double tap sa labas ng app para baguhin ang posisyon nito"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"I-expand para sa higit pang impormasyon."</string> <string name="maximize_button_text" msgid="1650859196290301963">"I-maximize"</string> diff --git a/libs/WindowManager/Shell/res/values-tr/strings.xml b/libs/WindowManager/Shell/res/values-tr/strings.xml index 80d07160d8d4..e1ea0df780e6 100644 --- a/libs/WindowManager/Shell/res/values-tr/strings.xml +++ b/libs/WindowManager/Shell/res/values-tr/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Kameranızda sorun mu var?\nDüzeltmek için dokunun"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Bu işlem sorunu düzeltmedi mi?\nİşlemi geri almak için dokunun"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Kameranızda sorun yok mu? Kapatmak için dokunun."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Daha fazlasını görün ve yapın"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"Bölünmüş ekran için başka bir uygulamayı sürükleyin"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Yeniden konumlandırmak için uygulamanın dışına iki kez dokunun"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Anladım"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Daha fazla bilgi için genişletin."</string> <string name="maximize_button_text" msgid="1650859196290301963">"Ekranı Kapla"</string> diff --git a/libs/WindowManager/Shell/res/values-uk/strings.xml b/libs/WindowManager/Shell/res/values-uk/strings.xml index 07d0f446240e..9e713c77cacd 100644 --- a/libs/WindowManager/Shell/res/values-uk/strings.xml +++ b/libs/WindowManager/Shell/res/values-uk/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Проблеми з камерою?\nНатисніть, щоб пристосувати"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Проблему не вирішено?\nНатисніть, щоб скасувати зміни"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Немає проблем із камерою? Торкніться, щоб закрити."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Більше простору та можливостей"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"Щоб перейти в режим розділення екрана, перетягніть сюди інший додаток"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Щоб перемістити додаток, двічі торкніться області поза ним"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"ОK"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Розгорніть, щоб дізнатися більше."</string> <string name="maximize_button_text" msgid="1650859196290301963">"Збільшити"</string> diff --git a/libs/WindowManager/Shell/res/values-ur/strings.xml b/libs/WindowManager/Shell/res/values-ur/strings.xml index 44370413a505..596cf4b15d40 100644 --- a/libs/WindowManager/Shell/res/values-ur/strings.xml +++ b/libs/WindowManager/Shell/res/values-ur/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"کیمرے کے مسائل؟\nدوبارہ فٹ کرنے کیلئے تھپتھپائیں"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"یہ حل نہیں ہوا؟\nلوٹانے کیلئے تھپتھپائیں"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"کوئی کیمرے کا مسئلہ نہیں ہے؟ برخاست کرنے کیلئے تھپتھپائیں۔"</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"دیکھیں اور بہت کچھ کریں"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"اسپلٹ اسکرین کے ليے دوسری ایپ میں گھسیٹیں"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"کسی ایپ کی پوزیشن تبدیل کرنے کے لیے اس ایپ کے باہر دو بار تھپتھپائیں"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"سمجھ آ گئی"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"مزید معلومات کے لیے پھیلائیں۔"</string> <string name="maximize_button_text" msgid="1650859196290301963">"بڑا کریں"</string> diff --git a/libs/WindowManager/Shell/res/values-uz/strings.xml b/libs/WindowManager/Shell/res/values-uz/strings.xml index 78133b0d01f9..275940a22f25 100644 --- a/libs/WindowManager/Shell/res/values-uz/strings.xml +++ b/libs/WindowManager/Shell/res/values-uz/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Kamera nosozmi?\nQayta moslash uchun bosing"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Tuzatilmadimi?\nQaytarish uchun bosing"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Kamera muammosizmi? Yopish uchun bosing."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Yana boshqa amallar"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"Ekranni ikkiga ajratish uchun boshqa ilovani bu yerga torting"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Qayta joylash uchun ilova tashqarisiga ikki marta bosing"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Batafsil axborot olish uchun kengaytiring."</string> <string name="maximize_button_text" msgid="1650859196290301963">"Yoyish"</string> diff --git a/libs/WindowManager/Shell/res/values-vi/strings.xml b/libs/WindowManager/Shell/res/values-vi/strings.xml index 1e025b326622..24fb1ca57aec 100644 --- a/libs/WindowManager/Shell/res/values-vi/strings.xml +++ b/libs/WindowManager/Shell/res/values-vi/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Có vấn đề với máy ảnh?\nHãy nhấn để sửa lỗi"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Bạn chưa khắc phục vấn đề?\nHãy nhấn để hủy bỏ"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Không có vấn đề với máy ảnh? Hãy nhấn để đóng."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Xem và làm được nhiều việc hơn"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"Kéo vào một ứng dụng khác để chia đôi màn hình"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Nhấn đúp bên ngoài ứng dụng để đặt lại vị trí"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"OK"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Mở rộng để xem thêm thông tin."</string> <string name="maximize_button_text" msgid="1650859196290301963">"Phóng to"</string> diff --git a/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml b/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml index f3ffcffd3d5f..e52a7b556be0 100644 --- a/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml +++ b/libs/WindowManager/Shell/res/values-zh-rCN/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"相机有问题?\n点按即可整修"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"没有解决此问题?\n点按即可恢复"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"相机没有问题?点按即可忽略。"</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"查看和处理更多任务"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"拖入另一个应用,即可使用分屏模式"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"在某个应用外连续点按两次,即可调整它的位置"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"知道了"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"展开即可了解详情。"</string> <string name="maximize_button_text" msgid="1650859196290301963">"最大化"</string> diff --git a/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml b/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml index 1585fec78998..eed1e5299365 100644 --- a/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml +++ b/libs/WindowManager/Shell/res/values-zh-rHK/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"相機有問題?\n輕按即可修正"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"未能修正問題?\n輕按即可還原"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"相機冇問題?㩒一下就可以即可閂咗佢。"</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"瀏覽更多內容及執行更多操作"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"拖入另一個應用程式即可分割螢幕"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"在應用程式外輕按兩下即可調整位置"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"知道了"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"展開即可查看詳情。"</string> <string name="maximize_button_text" msgid="1650859196290301963">"最大化"</string> diff --git a/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml b/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml index e0bdf7e4801d..f9f28ab02aa6 100644 --- a/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml +++ b/libs/WindowManager/Shell/res/values-zh-rTW/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"相機有問題嗎?\n輕觸即可修正"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"未修正問題嗎?\n輕觸即可還原"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"相機沒問題嗎?輕觸即可關閉。"</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"瀏覽更多內容及執行更多操作"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"拖進另一個應用程式即可使用分割畫面模式"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"在應用程式外輕觸兩下即可調整位置"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"我知道了"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"展開即可查看詳細資訊。"</string> <string name="maximize_button_text" msgid="1650859196290301963">"最大化"</string> diff --git a/libs/WindowManager/Shell/res/values-zu/strings.xml b/libs/WindowManager/Shell/res/values-zu/strings.xml index 07c22134d968..ddb6a4c3166e 100644 --- a/libs/WindowManager/Shell/res/values-zu/strings.xml +++ b/libs/WindowManager/Shell/res/values-zu/strings.xml @@ -76,12 +76,9 @@ <string name="camera_compat_treatment_suggested_button_description" msgid="8103916969024076767">"Izinkinga zekhamera?\nThepha ukuze uyilinganise kabusha"</string> <string name="camera_compat_treatment_applied_button_description" msgid="2944157113330703897">"Akuyilungisanga?\nThepha ukuze ubuyele"</string> <string name="camera_compat_dismiss_button_description" msgid="2795364433503817511">"Azikho izinkinga zekhamera? Thepha ukuze ucashise."</string> - <!-- no translation found for letterbox_education_dialog_title (7739895354143295358) --> - <skip /> - <!-- no translation found for letterbox_education_split_screen_text (6206339484068670830) --> - <skip /> - <!-- no translation found for letterbox_education_reposition_text (4589957299813220661) --> - <skip /> + <string name="letterbox_education_dialog_title" msgid="7739895354143295358">"Bona futhi wenze okuningi"</string> + <string name="letterbox_education_split_screen_text" msgid="6206339484068670830">"Hudula kwenye i-app mayelana nokuhlukanisa isikrini"</string> + <string name="letterbox_education_reposition_text" msgid="4589957299813220661">"Thepha kabili ngaphandle kwe-app ukuze uyimise kabusha"</string> <string name="letterbox_education_got_it" msgid="4057634570866051177">"Ngiyezwa"</string> <string name="letterbox_education_expand_button_description" msgid="1729796567101129834">"Nweba ukuze uthole ulwazi olwengeziwe"</string> <string name="maximize_button_text" msgid="1650859196290301963">"Khulisa"</string> diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java index b5409b7d78af..43679364b443 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellTaskOrganizer.java @@ -876,8 +876,12 @@ public class ShellTaskOrganizer extends TaskOrganizer implements pkg = info.getTaskInfo().baseActivity.getPackageName(); } Rect bounds = info.getTaskInfo().getConfiguration().windowConfiguration.getBounds(); + boolean running = info.getTaskInfo().isRunning; + boolean visible = info.getTaskInfo().isVisible; + boolean focused = info.getTaskInfo().isFocused; pw.println(innerPrefix + "#" + i + " task=" + key + " listener=" + listener - + " wmMode=" + windowingMode + " pkg=" + pkg + " bounds=" + bounds); + + " wmMode=" + windowingMode + " pkg=" + pkg + " bounds=" + bounds + + " running=" + running + " visible=" + visible + " focused=" + focused); } pw.println(); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/TaskView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/TaskView.java index a8764e05c3e2..d76ad3d27c70 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/TaskView.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/TaskView.java @@ -517,7 +517,9 @@ public class TaskView extends SurfaceView implements SurfaceHolder.Callback, getViewTreeObserver().removeOnComputeInternalInsetsListener(this); } - ActivityManager.RunningTaskInfo getTaskInfo() { + /** Returns the task info for the task in the TaskView. */ + @Nullable + public ActivityManager.RunningTaskInfo getTaskInfo() { return mTaskInfo; } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationAdapter.java b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationAdapter.java index cc4db933ec9f..591e3476ecd9 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationAdapter.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationAdapter.java @@ -16,7 +16,6 @@ package com.android.wm.shell.activityembedding; -import static android.graphics.Matrix.MSCALE_X; import static android.graphics.Matrix.MTRANS_X; import static android.graphics.Matrix.MTRANS_Y; @@ -42,31 +41,45 @@ class ActivityEmbeddingAnimationAdapter { */ private static final int LAYER_NO_OVERRIDE = -1; + @NonNull final Animation mAnimation; + @NonNull final TransitionInfo.Change mChange; + @NonNull final SurfaceControl mLeash; + /** Area in absolute coordinate that the animation surface shouldn't go beyond. */ + @NonNull + private final Rect mWholeAnimationBounds = new Rect(); + @NonNull final Transformation mTransformation = new Transformation(); + @NonNull final float[] mMatrix = new float[9]; + @NonNull final float[] mVecs = new float[4]; + @NonNull final Rect mRect = new Rect(); private boolean mIsFirstFrame = true; private int mOverrideLayer = LAYER_NO_OVERRIDE; ActivityEmbeddingAnimationAdapter(@NonNull Animation animation, @NonNull TransitionInfo.Change change) { - this(animation, change, change.getLeash()); + this(animation, change, change.getLeash(), change.getEndAbsBounds()); } /** * @param leash the surface to animate, which is not necessary the same as - * {@link TransitionInfo.Change#getLeash()}, it can be a screenshot for example. + * {@link TransitionInfo.Change#getLeash()}, it can be a screenshot for example. + * @param wholeAnimationBounds area in absolute coordinate that the animation surface shouldn't + * go beyond. */ ActivityEmbeddingAnimationAdapter(@NonNull Animation animation, - @NonNull TransitionInfo.Change change, @NonNull SurfaceControl leash) { + @NonNull TransitionInfo.Change change, @NonNull SurfaceControl leash, + @NonNull Rect wholeAnimationBounds) { mAnimation = animation; mChange = change; mLeash = leash; + mWholeAnimationBounds.set(wholeAnimationBounds); } /** @@ -96,23 +109,31 @@ class ActivityEmbeddingAnimationAdapter { /** To be overridden by subclasses to adjust the animation surface change. */ void onAnimationUpdateInner(@NonNull SurfaceControl.Transaction t) { + // Update the surface position and alpha. final Point offset = mChange.getEndRelOffset(); mTransformation.getMatrix().postTranslate(offset.x, offset.y); t.setMatrix(mLeash, mTransformation.getMatrix(), mMatrix); t.setAlpha(mLeash, mTransformation.getAlpha()); - // Get current animation position. + + // Get current surface bounds in absolute coordinate. + // positionX/Y are in local coordinate, so minus the local offset to get the slide amount. final int positionX = Math.round(mMatrix[MTRANS_X]); final int positionY = Math.round(mMatrix[MTRANS_Y]); - // The exiting surface starts at position: Change#getEndRelOffset() and moves with - // positionX varying. Offset our crop region by the amount we have slided so crop - // regions stays exactly on the original container in split. - final int cropOffsetX = offset.x - positionX; - final int cropOffsetY = offset.y - positionY; - final Rect cropRect = new Rect(); - cropRect.set(mChange.getEndAbsBounds()); - // Because window crop uses absolute position. - cropRect.offsetTo(0, 0); - cropRect.offset(cropOffsetX, cropOffsetY); + final Rect cropRect = new Rect(mChange.getEndAbsBounds()); + cropRect.offset(positionX - offset.x, positionY - offset.y); + + // Store the current offset of the surface top left from (0,0) in absolute coordinate. + final int offsetX = cropRect.left; + final int offsetY = cropRect.top; + + // Intersect to make sure the animation happens within the whole animation bounds. + if (!cropRect.intersect(mWholeAnimationBounds)) { + // Hide the surface when it is outside of the animation area. + t.setAlpha(mLeash, 0); + } + + // cropRect is in absolute coordinate, so we need to translate it to surface top left. + cropRect.offset(-offsetX, -offsetY); t.setCrop(mLeash, cropRect); } @@ -127,53 +148,6 @@ class ActivityEmbeddingAnimationAdapter { } /** - * Should be used when the {@link TransitionInfo.Change} is in split with others, and wants to - * animate together as one. This adapter will offset the animation leash to make the animate of - * two windows look like a single window. - */ - static class SplitAdapter extends ActivityEmbeddingAnimationAdapter { - private final boolean mIsLeftHalf; - private final int mWholeAnimationWidth; - - /** - * @param isLeftHalf whether this is the left half of the animation. - * @param wholeAnimationWidth the whole animation windows width. - */ - SplitAdapter(@NonNull Animation animation, @NonNull TransitionInfo.Change change, - boolean isLeftHalf, int wholeAnimationWidth) { - super(animation, change); - mIsLeftHalf = isLeftHalf; - mWholeAnimationWidth = wholeAnimationWidth; - if (wholeAnimationWidth == 0) { - throw new IllegalArgumentException("SplitAdapter must provide wholeAnimationWidth"); - } - } - - @Override - void onAnimationUpdateInner(@NonNull SurfaceControl.Transaction t) { - final Point offset = mChange.getEndRelOffset(); - float posX = offset.x; - final float posY = offset.y; - // This window is half of the whole animation window. Offset left/right to make it - // look as one with the other half. - mTransformation.getMatrix().getValues(mMatrix); - final int changeWidth = mChange.getEndAbsBounds().width(); - final float scaleX = mMatrix[MSCALE_X]; - final float totalOffset = mWholeAnimationWidth * (1 - scaleX) / 2; - final float curOffset = changeWidth * (1 - scaleX) / 2; - final float offsetDiff = totalOffset - curOffset; - if (mIsLeftHalf) { - posX += offsetDiff; - } else { - posX -= offsetDiff; - } - mTransformation.getMatrix().postTranslate(posX, posY); - t.setMatrix(mLeash, mTransformation.getMatrix(), mMatrix); - t.setAlpha(mLeash, mTransformation.getAlpha()); - } - } - - /** * Should be used for the animation of the snapshot of a {@link TransitionInfo.Change} that has * size change. */ @@ -181,7 +155,7 @@ class ActivityEmbeddingAnimationAdapter { SnapshotAdapter(@NonNull Animation animation, @NonNull TransitionInfo.Change change, @NonNull SurfaceControl snapshotLeash) { - super(animation, change, snapshotLeash); + super(animation, change, snapshotLeash, change.getEndAbsBounds()); } @Override @@ -196,7 +170,9 @@ class ActivityEmbeddingAnimationAdapter { void onAnimationEnd(@NonNull SurfaceControl.Transaction t) { super.onAnimationEnd(t); // Remove the screenshot leash after animation is finished. - t.remove(mLeash); + if (mLeash.isValid()) { + t.remove(mLeash); + } } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunner.java index 7e0795d11153..d88cc007c7b5 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunner.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunner.java @@ -22,9 +22,9 @@ import static android.view.WindowManagerPolicyConstants.TYPE_LAYER_OFFSET; import android.animation.Animator; import android.animation.ValueAnimator; import android.content.Context; -import android.graphics.Point; import android.graphics.Rect; import android.os.IBinder; +import android.util.ArraySet; import android.util.Log; import android.view.SurfaceControl; import android.view.animation.Animation; @@ -40,6 +40,7 @@ import com.android.wm.shell.transition.Transitions; import java.util.ArrayList; import java.util.List; +import java.util.Set; import java.util.function.BiFunction; /** To run the ActivityEmbedding animations. */ @@ -169,15 +170,12 @@ class ActivityEmbeddingAnimationRunner { final Rect openingWholeScreenBounds = new Rect(); final Rect closingWholeScreenBounds = new Rect(); for (TransitionInfo.Change change : info.getChanges()) { - final Rect bounds = new Rect(change.getEndAbsBounds()); - final Point offset = change.getEndRelOffset(); - bounds.offsetTo(offset.x, offset.y); if (Transitions.isOpeningType(change.getMode())) { openingChanges.add(change); - openingWholeScreenBounds.union(bounds); + openingWholeScreenBounds.union(change.getEndAbsBounds()); } else { closingChanges.add(change); - closingWholeScreenBounds.union(bounds); + closingWholeScreenBounds.union(change.getEndAbsBounds()); } } @@ -210,60 +208,73 @@ class ActivityEmbeddingAnimationRunner { @NonNull BiFunction<TransitionInfo.Change, Rect, Animation> animationProvider, @NonNull Rect wholeAnimationBounds) { final Animation animation = animationProvider.apply(change, wholeAnimationBounds); - final Rect bounds = new Rect(change.getEndAbsBounds()); - final Point offset = change.getEndRelOffset(); - bounds.offsetTo(offset.x, offset.y); - if (bounds.left == wholeAnimationBounds.left - && bounds.right != wholeAnimationBounds.right) { - // This is the left split of the whole animation window. - return new ActivityEmbeddingAnimationAdapter.SplitAdapter(animation, change, - true /* isLeftHalf */, wholeAnimationBounds.width()); - } else if (bounds.left != wholeAnimationBounds.left - && bounds.right == wholeAnimationBounds.right) { - // This is the right split of the whole animation window. - return new ActivityEmbeddingAnimationAdapter.SplitAdapter(animation, change, - false /* isLeftHalf */, wholeAnimationBounds.width()); - } - // Open/close window that fills the whole animation. - return new ActivityEmbeddingAnimationAdapter(animation, change); + return new ActivityEmbeddingAnimationAdapter(animation, change, change.getLeash(), + wholeAnimationBounds); } @NonNull private List<ActivityEmbeddingAnimationAdapter> createChangeAnimationAdapters( @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction startTransaction) { final List<ActivityEmbeddingAnimationAdapter> adapters = new ArrayList<>(); + final Set<TransitionInfo.Change> handledChanges = new ArraySet<>(); + + // For the first iteration, we prepare the animation for the change type windows. This is + // needed because there may be window that is reparented while resizing. In such case, we + // will do the following: + // 1. Capture a screenshot from the Activity surface. + // 2. Attach the screenshot surface to the top of TaskFragment (Activity's parent) surface. + // 3. Animate the TaskFragment using Activity Change info (start/end bounds). + // This is because the TaskFragment surface/change won't contain the Activity's before its + // reparent. for (TransitionInfo.Change change : info.getChanges()) { - if (change.getMode() == TRANSIT_CHANGE - && !change.getStartAbsBounds().equals(change.getEndAbsBounds())) { - // This is the window with bounds change. - final WindowContainerToken parentToken = change.getParent(); - final Rect parentBounds; - if (parentToken != null) { - TransitionInfo.Change parentChange = info.getChange(parentToken); - parentBounds = parentChange != null - ? parentChange.getEndAbsBounds() - : change.getEndAbsBounds(); - } else { - parentBounds = change.getEndAbsBounds(); + if (change.getMode() != TRANSIT_CHANGE + || change.getStartAbsBounds().equals(change.getEndAbsBounds())) { + continue; + } + + // This is the window with bounds change. + handledChanges.add(change); + final WindowContainerToken parentToken = change.getParent(); + TransitionInfo.Change boundsAnimationChange = change; + if (parentToken != null) { + // When the parent window is also included in the transition as an opening window, + // we would like to animate the parent window instead. + final TransitionInfo.Change parentChange = info.getChange(parentToken); + if (parentChange != null && Transitions.isOpeningType(parentChange.getMode())) { + // We won't create a separate animation for the parent, but to animate the + // parent for the child resizing. + handledChanges.add(parentChange); + boundsAnimationChange = parentChange; } - final Animation[] animations = - mAnimationSpec.createChangeBoundsChangeAnimations(change, parentBounds); + } + + final Animation[] animations = mAnimationSpec.createChangeBoundsChangeAnimations(change, + boundsAnimationChange.getEndAbsBounds()); + + // Create a screenshot based on change, but attach it to the top of the + // boundsAnimationChange. + final SurfaceControl screenshotLeash = getOrCreateScreenshot(change, + boundsAnimationChange, startTransaction); + if (screenshotLeash != null) { // Adapter for the starting screenshot leash. - final SurfaceControl screenshotLeash = createScreenshot(change, startTransaction); - if (screenshotLeash != null) { - // The screenshot leash will be removed in SnapshotAdapter#onAnimationEnd - adapters.add(new ActivityEmbeddingAnimationAdapter.SnapshotAdapter( - animations[0], change, screenshotLeash)); - } else { - Log.e(TAG, "Failed to take screenshot for change=" + change); - } - // Adapter for the ending bounds changed leash. - adapters.add(new ActivityEmbeddingAnimationAdapter.BoundsChangeAdapter( - animations[1], change)); + // The screenshot leash will be removed in SnapshotAdapter#onAnimationEnd + adapters.add(new ActivityEmbeddingAnimationAdapter.SnapshotAdapter( + animations[0], change, screenshotLeash)); + } else { + Log.e(TAG, "Failed to take screenshot for change=" + change); + } + // Adapter for the ending bounds changed leash. + adapters.add(new ActivityEmbeddingAnimationAdapter.BoundsChangeAdapter( + animations[1], boundsAnimationChange)); + } + + // Handle the other windows that don't have bounds change in the same transition. + for (TransitionInfo.Change change : info.getChanges()) { + if (handledChanges.contains(change)) { + // Skip windows that we have already handled in the previous iteration. continue; } - // These are the other windows that don't have bounds change in the same transition. final Animation animation; if (!TransitionInfo.isIndependent(change, info)) { // No-op if it will be covered by the changing parent window. @@ -278,13 +289,27 @@ class ActivityEmbeddingAnimationRunner { return adapters; } - /** Takes a screenshot of the given {@link TransitionInfo.Change} surface. */ + /** + * Takes a screenshot of the given {@code screenshotChange} surface if WM Core hasn't taken one. + * The screenshot leash should be attached to the {@code animationChange} surface which we will + * animate later. + */ @Nullable - private SurfaceControl createScreenshot(@NonNull TransitionInfo.Change change, - @NonNull SurfaceControl.Transaction startTransaction) { - final Rect cropBounds = new Rect(change.getStartAbsBounds()); + private SurfaceControl getOrCreateScreenshot(@NonNull TransitionInfo.Change screenshotChange, + @NonNull TransitionInfo.Change animationChange, + @NonNull SurfaceControl.Transaction t) { + final SurfaceControl screenshotLeash = screenshotChange.getSnapshot(); + if (screenshotLeash != null) { + // If WM Core has already taken a screenshot, make sure it is reparented to the + // animation leash. + t.reparent(screenshotLeash, animationChange.getLeash()); + return screenshotLeash; + } + + // If WM Core hasn't taken a screenshot, take a screenshot now. + final Rect cropBounds = new Rect(screenshotChange.getStartAbsBounds()); cropBounds.offsetTo(0, 0); - return ScreenshotUtils.takeScreenshot(startTransaction, change.getLeash(), cropBounds, - Integer.MAX_VALUE); + return ScreenshotUtils.takeScreenshot(t, screenshotChange.getLeash(), + animationChange.getLeash(), cropBounds, Integer.MAX_VALUE); } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java index 6f06f28caff2..ad0dddf77002 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationSpec.java @@ -185,8 +185,10 @@ class ActivityEmbeddingAnimationSpec { animation = mTransitionAnimation.loadDefaultAnimationRes(isEnter ? R.anim.task_fragment_open_enter : R.anim.task_fragment_open_exit); - final Rect bounds = change.getEndAbsBounds(); - animation.initialize(bounds.width(), bounds.height(), + // Use the whole animation bounds instead of the change bounds, so that when multiple change + // targets are opening at the same time, the animation applied to each will be the same. + // Otherwise, we may see gap between the activities that are launching together. + animation.initialize(wholeAnimationBounds.width(), wholeAnimationBounds.height(), wholeAnimationBounds.width(), wholeAnimationBounds.height()); animation.scaleCurrentDuration(mTransitionAnimationScaleSetting); return animation; @@ -203,8 +205,10 @@ class ActivityEmbeddingAnimationSpec { animation = mTransitionAnimation.loadDefaultAnimationRes(isEnter ? R.anim.task_fragment_close_enter : R.anim.task_fragment_close_exit); - final Rect bounds = change.getEndAbsBounds(); - animation.initialize(bounds.width(), bounds.height(), + // Use the whole animation bounds instead of the change bounds, so that when multiple change + // targets are closing at the same time, the animation applied to each will be the same. + // Otherwise, we may see gap between the activities that are finishing together. + animation.initialize(wholeAnimationBounds.width(), wholeAnimationBounds.height(), wholeAnimationBounds.width(), wholeAnimationBounds.height()); animation.scaleCurrentDuration(mTransitionAnimationScaleSetting); return animation; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingController.java index e0004fcaa060..521a65cc4df6 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingController.java @@ -16,7 +16,8 @@ package com.android.wm.shell.activityembedding; -import static android.window.TransitionInfo.FLAG_IS_EMBEDDED; +import static android.window.TransitionInfo.FLAG_FILLS_TASK; +import static android.window.TransitionInfo.FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY; import static java.util.Objects.requireNonNull; @@ -84,12 +85,23 @@ public class ActivityEmbeddingController implements Transitions.TransitionHandle @NonNull SurfaceControl.Transaction startTransaction, @NonNull SurfaceControl.Transaction finishTransaction, @NonNull Transitions.TransitionFinishCallback finishCallback) { - // TODO(b/207070762) Handle AE animation as a part of other transitions. - // Only handle the transition if all containers are embedded. + boolean containsEmbeddingSplit = false; for (TransitionInfo.Change change : info.getChanges()) { - if (!isEmbedded(change)) { + if (!change.hasFlags(FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY)) { + // Only animate the transition if all changes are in a Task with ActivityEmbedding. return false; } + if (!containsEmbeddingSplit && !change.hasFlags(FLAG_FILLS_TASK)) { + // Whether the Task contains any ActivityEmbedding split before or after the + // transition. + containsEmbeddingSplit = true; + } + } + if (!containsEmbeddingSplit) { + // Let the system to play the default animation if there is no ActivityEmbedding split + // window. This allows to play the app customized animation when there is no embedding, + // such as the device is in a folded state. + return false; } // Start ActivityEmbedding animation. @@ -119,8 +131,4 @@ public class ActivityEmbeddingController implements Transitions.TransitionHandle } callback.onTransitionFinished(null /* wct */, null /* wctCB */); } - - private static boolean isEmbedded(@NonNull TransitionInfo.Change change) { - return (change.getFlags() & FLAG_IS_EMBEDDED) != 0; - } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java index 99b8885acdef..b5a575499a3a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubble.java @@ -170,7 +170,8 @@ public class Bubble implements BubbleViewProvider { @VisibleForTesting(visibility = PRIVATE) public Bubble(@NonNull final String key, @NonNull final ShortcutInfo shortcutInfo, final int desiredHeight, final int desiredHeightResId, @Nullable final String title, - int taskId, @Nullable final String locus, Executor mainExecutor) { + int taskId, @Nullable final String locus, Executor mainExecutor, + final Bubbles.BubbleMetadataFlagListener listener) { Objects.requireNonNull(key); Objects.requireNonNull(shortcutInfo); mMetadataShortcutId = shortcutInfo.getId(); @@ -188,11 +189,12 @@ public class Bubble implements BubbleViewProvider { mShowBubbleUpdateDot = false; mMainExecutor = mainExecutor; mTaskId = taskId; + mBubbleMetadataFlagListener = listener; } @VisibleForTesting(visibility = PRIVATE) public Bubble(@NonNull final BubbleEntry entry, - @Nullable final Bubbles.BubbleMetadataFlagListener listener, + final Bubbles.BubbleMetadataFlagListener listener, final Bubbles.PendingIntentCanceledListener intentCancelListener, Executor mainExecutor) { mKey = entry.getKey(); @@ -830,6 +832,7 @@ public class Bubble implements BubbleViewProvider { pw.print(" desiredHeight: "); pw.println(getDesiredHeightString()); pw.print(" suppressNotif: "); pw.println(shouldSuppressNotification()); pw.print(" autoExpand: "); pw.println(shouldAutoExpand()); + pw.print(" bubbleMetadataFlagListener null: " + (mBubbleMetadataFlagListener == null)); if (mExpandedView != null) { mExpandedView.dump(pw); } 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 d63c25d07485..0dfba3464f23 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 @@ -309,6 +309,7 @@ public class BubbleController implements ConfigurationChangeListener { protected void onInit() { mBubbleData.setListener(mBubbleDataListener); mBubbleData.setSuppressionChangedListener(this::onBubbleMetadataFlagChanged); + mDataRepository.setSuppressionChangedListener(this::onBubbleMetadataFlagChanged); mBubbleData.setPendingIntentCancelledListener(bubble -> { if (bubble.getBubbleIntent() == null) { @@ -1336,19 +1337,7 @@ public class BubbleController implements ConfigurationChangeListener { } mSysuiProxy.updateNotificationBubbleButton(bubble.getKey()); } - } - mSysuiProxy.getPendingOrActiveEntry(bubble.getKey(), (entry) -> { - mMainExecutor.execute(() -> { - if (entry != null) { - final String groupKey = entry.getStatusBarNotification().getGroupKey(); - if (getBubblesInGroup(groupKey).isEmpty()) { - // Time to potentially remove the summary - mSysuiProxy.notifyMaybeCancelSummary(bubble.getKey()); - } - } - }); - }); } mDataRepository.removeBubbles(mCurrentUserId, bubblesToBeRemovedFromRepository); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java index c64133f0b668..af31391fec96 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleData.java @@ -158,7 +158,6 @@ public class BubbleData { @Nullable private Listener mListener; - @Nullable private Bubbles.BubbleMetadataFlagListener mBubbleMetadataFlagListener; private Bubbles.PendingIntentCanceledListener mCancelledListener; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleDataRepository.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleDataRepository.kt index 97560f44fb06..3a5961462c87 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleDataRepository.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleDataRepository.kt @@ -25,6 +25,7 @@ import android.content.pm.LauncherApps.ShortcutQuery.FLAG_MATCH_PINNED_BY_ANY_LA import android.content.pm.UserInfo import android.os.UserHandle import android.util.Log +import com.android.wm.shell.bubbles.Bubbles.BubbleMetadataFlagListener import com.android.wm.shell.bubbles.storage.BubbleEntity import com.android.wm.shell.bubbles.storage.BubblePersistentRepository import com.android.wm.shell.bubbles.storage.BubbleVolatileRepository @@ -47,6 +48,13 @@ internal class BubbleDataRepository( private val ioScope = CoroutineScope(Dispatchers.IO) private var job: Job? = null + // For use in Bubble construction. + private lateinit var bubbleMetadataFlagListener: BubbleMetadataFlagListener + + fun setSuppressionChangedListener(listener: BubbleMetadataFlagListener) { + bubbleMetadataFlagListener = listener + } + /** * Adds the bubble in memory, then persists the snapshot after adding the bubble to disk * asynchronously. @@ -197,7 +205,8 @@ internal class BubbleDataRepository( entity.title, entity.taskId, entity.locus, - mainExecutor + mainExecutor, + bubbleMetadataFlagListener ) } } 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 aeaf6eda9809..be100bb1dd34 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 @@ -1270,7 +1270,7 @@ public class BubbleStackView extends FrameLayout } final boolean seen = getPrefBoolean(ManageEducationViewKt.PREF_MANAGED_EDUCATION); final boolean shouldShow = (!seen || BubbleDebugConfig.forceShowUserEducation(mContext)) - && mExpandedBubble != null; + && mExpandedBubble != null && mExpandedBubble.getExpandedView() != null; if (BubbleDebugConfig.DEBUG_USER_EDUCATION) { Log.d(TAG, "Show manage edu: " + shouldShow); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java index 453b34eb445c..b3104b518440 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/Bubbles.java @@ -276,8 +276,6 @@ public interface Bubbles { void notifyInvalidateNotifications(String reason); - void notifyMaybeCancelSummary(String key); - void updateNotificationBubbleButton(String key); void onStackExpandChanged(boolean shouldExpand); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/DismissView.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/DismissView.kt index 063dac3d4109..ab194dfb3ce9 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/DismissView.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/DismissView.kt @@ -24,8 +24,8 @@ import android.util.IntProperty import android.view.Gravity import android.view.View import android.view.ViewGroup -import android.view.WindowManager import android.view.WindowInsets +import android.view.WindowManager import android.widget.FrameLayout import androidx.dynamicanimation.animation.DynamicAnimation import androidx.dynamicanimation.animation.SpringForce.DAMPING_RATIO_LOW_BOUNCY @@ -41,6 +41,7 @@ class DismissView(context: Context) : FrameLayout(context) { var circle = DismissCircleView(context) var isShowing = false + var targetSizeResId: Int private val animator = PhysicsAnimator.getInstance(circle) private val spring = PhysicsAnimator.SpringConfig(STIFFNESS_LOW, DAMPING_RATIO_LOW_BOUNCY) @@ -70,7 +71,8 @@ class DismissView(context: Context) : FrameLayout(context) { setVisibility(View.INVISIBLE) setBackgroundDrawable(gradientDrawable) - val targetSize: Int = resources.getDimensionPixelSize(R.dimen.dismiss_circle_size) + targetSizeResId = R.dimen.dismiss_circle_size + val targetSize: Int = resources.getDimensionPixelSize(targetSizeResId) addView(circle, LayoutParams(targetSize, targetSize, Gravity.BOTTOM or Gravity.CENTER_HORIZONTAL)) // start with circle offscreen so it's animated up @@ -126,7 +128,7 @@ class DismissView(context: Context) : FrameLayout(context) { layoutParams.height = resources.getDimensionPixelSize( R.dimen.floating_dismiss_gradient_height) - val targetSize: Int = resources.getDimensionPixelSize(R.dimen.dismiss_circle_size) + val targetSize = resources.getDimensionPixelSize(targetSizeResId) circle.layoutParams.width = targetSize circle.layoutParams.height = targetSize circle.requestLayout() @@ -153,4 +155,4 @@ class DismissView(context: Context) : FrameLayout(context) { setPadding(0, 0, 0, navInset.bottom + resources.getDimensionPixelSize(R.dimen.floating_dismiss_bottom_margin)) } -}
\ No newline at end of file +} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java index 47f1e2e18255..96efeeb0c5eb 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java @@ -96,7 +96,8 @@ public class DisplayLayout { /** * Different from {@link #equals(Object)}, this method compares the basic geometry properties - * of two {@link DisplayLayout} objects including width, height, rotation, density and cutout. + * of two {@link DisplayLayout} objects including width, height, rotation, density, cutout and + * insets. * @return {@code true} if the given {@link DisplayLayout} is identical geometry wise. */ public boolean isSameGeometry(@NonNull DisplayLayout other) { @@ -104,7 +105,8 @@ public class DisplayLayout { && mHeight == other.mHeight && mRotation == other.mRotation && mDensityDpi == other.mDensityDpi - && Objects.equals(mCutout, other.mCutout); + && Objects.equals(mCutout, other.mCutout) + && Objects.equals(mStableInsets, other.mStableInsets); } @Override diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/ScreenshotUtils.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/ScreenshotUtils.java index c4bd73ba1b4a..2a1bf0ee42ba 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/ScreenshotUtils.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/ScreenshotUtils.java @@ -28,7 +28,7 @@ import java.util.function.Consumer; public class ScreenshotUtils { /** - * Take a screenshot of the specified SurfaceControl. + * Takes a screenshot of the specified SurfaceControl. * * @param sc the SurfaceControl to take a screenshot of * @param crop the crop to use when capturing the screenshot @@ -49,11 +49,14 @@ public class ScreenshotUtils { SurfaceControl mScreenshot = null; SurfaceControl.Transaction mTransaction; SurfaceControl mSurfaceControl; + SurfaceControl mParentSurfaceControl; int mLayer; - BufferConsumer(SurfaceControl.Transaction t, SurfaceControl sc, int layer) { + BufferConsumer(SurfaceControl.Transaction t, SurfaceControl sc, SurfaceControl parentSc, + int layer) { mTransaction = t; mSurfaceControl = sc; + mParentSurfaceControl = parentSc; mLayer = layer; } @@ -72,7 +75,7 @@ public class ScreenshotUtils { mTransaction.setBuffer(mScreenshot, buffer.getHardwareBuffer()); mTransaction.setColorSpace(mScreenshot, buffer.getColorSpace()); - mTransaction.reparent(mScreenshot, mSurfaceControl); + mTransaction.reparent(mScreenshot, mParentSurfaceControl); mTransaction.setLayer(mScreenshot, mLayer); mTransaction.show(mScreenshot); mTransaction.apply(); @@ -80,7 +83,7 @@ public class ScreenshotUtils { } /** - * Take a screenshot of the specified SurfaceControl. + * Takes a screenshot of the specified SurfaceControl. * * @param t the transaction used to set changes on the resulting screenshot. * @param sc the SurfaceControl to take a screenshot of @@ -91,7 +94,23 @@ public class ScreenshotUtils { */ public static SurfaceControl takeScreenshot(SurfaceControl.Transaction t, SurfaceControl sc, Rect crop, int layer) { - BufferConsumer consumer = new BufferConsumer(t, sc, layer); + return takeScreenshot(t, sc, sc /* parentSc */, crop, layer); + } + + /** + * Takes a screenshot of the specified SurfaceControl. + * + * @param t the transaction used to set changes on the resulting screenshot. + * @param sc the SurfaceControl to take a screenshot of + * @param parentSc the SurfaceControl to attach the screenshot to. + * @param crop the crop to use when capturing the screenshot + * @param layer the layer to place the screenshot + * + * @return A SurfaceControl where the screenshot will be attached, or null if failed. + */ + public static SurfaceControl takeScreenshot(SurfaceControl.Transaction t, SurfaceControl sc, + SurfaceControl parentSc, Rect crop, int layer) { + BufferConsumer consumer = new BufferConsumer(t, sc, parentSc, layer); captureLayer(sc, crop, consumer); return consumer.mScreenshot; } 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 4c85d2090ec5..419e62daf586 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 @@ -561,6 +561,10 @@ public final class SplitLayout implements DisplayInsetsController.OnInsetsChange if (from == to) { // No animation run, still callback to stop resizing. mSplitLayoutHandler.onLayoutSizeChanged(this); + + if (flingFinishedCallback != null) { + flingFinishedCallback.run(); + } InteractionJankMonitorUtils.endTracing( CUJ_SPLIT_SCREEN_RESIZE); return; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java index b7656dec5d6a..247ba605ae58 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java @@ -82,7 +82,7 @@ import com.android.wm.shell.splitscreen.SplitScreenController; import com.android.wm.shell.sysui.ShellCommandHandler; import com.android.wm.shell.sysui.ShellController; import com.android.wm.shell.sysui.ShellInit; -import com.android.wm.shell.transition.SplitscreenPipMixedHandler; +import com.android.wm.shell.transition.DefaultMixedHandler; import com.android.wm.shell.transition.Transitions; import com.android.wm.shell.unfold.ShellUnfoldProgressProvider; import com.android.wm.shell.unfold.UnfoldAnimationController; @@ -220,13 +220,14 @@ public abstract class WMShellModule { Context context, ShellInit shellInit, ShellTaskOrganizer shellTaskOrganizer, + Optional<RecentTasksController> recentTasksController, WindowDecorViewModel<?> windowDecorViewModel) { // TODO(b/238217847): Temporarily add this check here until we can remove the dynamic // override for this controller from the base module ShellInit init = FreeformComponents.isFreeformEnabled(context) ? shellInit : null; - return new FreeformTaskListener<>(init, shellTaskOrganizer, + return new FreeformTaskListener<>(init, shellTaskOrganizer, recentTasksController, windowDecorViewModel); } @@ -332,6 +333,7 @@ public abstract class WMShellModule { WindowManagerShellWrapper windowManagerShellWrapper, TaskStackListenerImpl taskStackListener, PipParamsChangedForwarder pipParamsChangedForwarder, + DisplayInsetsController displayInsetsController, Optional<OneHandedController> oneHandedController, @ShellMainThread ShellExecutor mainExecutor) { return Optional.ofNullable(PipController.create( @@ -340,7 +342,7 @@ public abstract class WMShellModule { pipBoundsState, pipMotionHelper, pipMediaController, phonePipMenuController, pipTaskOrganizer, pipTransitionState, pipTouchHandler, pipTransitionController, windowManagerShellWrapper, taskStackListener, pipParamsChangedForwarder, - oneHandedController, mainExecutor)); + displayInsetsController, oneHandedController, mainExecutor)); } @WMSingleton @@ -483,13 +485,13 @@ public abstract class WMShellModule { @WMSingleton @Provides - static SplitscreenPipMixedHandler provideSplitscreenPipMixedHandler( + static DefaultMixedHandler provideDefaultMixedHandler( ShellInit shellInit, Optional<SplitScreenController> splitScreenOptional, Optional<PipTouchHandler> pipTouchHandlerOptional, Transitions transitions) { - return new SplitscreenPipMixedHandler(shellInit, splitScreenOptional, - pipTouchHandlerOptional, transitions); + return new DefaultMixedHandler(shellInit, transitions, splitScreenOptional, + pipTouchHandlerOptional); } // @@ -597,12 +599,12 @@ public abstract class WMShellModule { Context context, ShellInit shellInit, ShellTaskOrganizer shellTaskOrganizer, RootDisplayAreaOrganizer rootDisplayAreaOrganizer, - @ShellMainThread Handler mainHandler + @ShellMainThread Handler mainHandler, + Transitions transitions ) { if (DesktopMode.IS_SUPPORTED) { return Optional.of(new DesktopModeController(context, shellInit, shellTaskOrganizer, - rootDisplayAreaOrganizer, - mainHandler)); + rootDisplayAreaOrganizer, mainHandler, transitions)); } else { return Optional.empty(); } @@ -618,7 +620,7 @@ public abstract class WMShellModule { @ShellCreateTriggerOverride @Provides static Object provideIndependentShellComponentsToCreate( - SplitscreenPipMixedHandler splitscreenPipMixedHandler, + DefaultMixedHandler defaultMixedHandler, Optional<DesktopModeController> desktopModeController) { return new Object(); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMode.java b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMode.java index 64cec2a270ea..8993d549964c 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMode.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopMode.java @@ -50,7 +50,7 @@ public class DesktopMode { Settings.System.DESKTOP_MODE, UserHandle.USER_CURRENT); ProtoLog.d(WM_SHELL_DESKTOP_MODE, "isDesktopModeEnabled=%s", result); return result != 0; - } catch (Settings.SettingNotFoundException e) { + } catch (Exception e) { ProtoLog.e(WM_SHELL_DESKTOP_MODE, "Failed to read DESKTOP_MODE setting %s", e); return false; } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeController.java index 7d34ea481de6..c07ce1065302 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeController.java @@ -18,6 +18,7 @@ package com.android.wm.shell.desktopmode; import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; +import static android.view.WindowManager.TRANSIT_CHANGE; import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE; @@ -37,6 +38,7 @@ import com.android.wm.shell.RootDisplayAreaOrganizer; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.common.annotations.ShellMainThread; import com.android.wm.shell.sysui.ShellInit; +import com.android.wm.shell.transition.Transitions; /** * Handles windowing changes when desktop mode system setting changes @@ -47,15 +49,18 @@ public class DesktopModeController { private final ShellTaskOrganizer mShellTaskOrganizer; private final RootDisplayAreaOrganizer mRootDisplayAreaOrganizer; private final SettingsObserver mSettingsObserver; + private final Transitions mTransitions; public DesktopModeController(Context context, ShellInit shellInit, ShellTaskOrganizer shellTaskOrganizer, RootDisplayAreaOrganizer rootDisplayAreaOrganizer, - @ShellMainThread Handler mainHandler) { + @ShellMainThread Handler mainHandler, + Transitions transitions) { mContext = context; mShellTaskOrganizer = shellTaskOrganizer; mRootDisplayAreaOrganizer = rootDisplayAreaOrganizer; mSettingsObserver = new SettingsObserver(mContext, mainHandler); + mTransitions = transitions; shellInit.addInitCallback(this::onInit, this); } @@ -89,7 +94,11 @@ public class DesktopModeController { } wct.merge(mRootDisplayAreaOrganizer.prepareWindowingModeChange(displayId, targetWindowingMode), true /* transfer */); - mRootDisplayAreaOrganizer.applyTransaction(wct); + if (Transitions.ENABLE_SHELL_TRANSITIONS) { + mTransitions.startTransition(TRANSIT_CHANGE, wct, null); + } else { + mRootDisplayAreaOrganizer.applyTransaction(wct); + } } /** diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java index 4697a0184eb4..b59fe1818780 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java @@ -258,12 +258,12 @@ public class DragAndDropController implements DisplayController.OnDisplaysChange break; case ACTION_DRAG_ENTERED: pd.dragLayout.show(); - pd.dragLayout.update(event); break; case ACTION_DRAG_LOCATION: pd.dragLayout.update(event); break; case ACTION_DROP: { + pd.dragLayout.update(event); return handleDrop(event, pd); } case ACTION_DRAG_EXITED: { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java index 8dcdda1895e6..1baac718ee95 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskListener.java @@ -28,12 +28,15 @@ import androidx.annotation.Nullable; import com.android.internal.protolog.common.ProtoLog; import com.android.wm.shell.ShellTaskOrganizer; +import com.android.wm.shell.desktopmode.DesktopMode; import com.android.wm.shell.protolog.ShellProtoLogGroup; +import com.android.wm.shell.recents.RecentTasksController; import com.android.wm.shell.sysui.ShellInit; import com.android.wm.shell.transition.Transitions; import com.android.wm.shell.windowdecor.WindowDecorViewModel; import java.io.PrintWriter; +import java.util.Optional; /** * {@link ShellTaskOrganizer.TaskListener} for {@link @@ -46,6 +49,7 @@ public class FreeformTaskListener<T extends AutoCloseable> private static final String TAG = "FreeformTaskListener"; private final ShellTaskOrganizer mShellTaskOrganizer; + private final Optional<RecentTasksController> mRecentTasksOptional; private final WindowDecorViewModel<T> mWindowDecorationViewModel; private final SparseArray<State<T>> mTasks = new SparseArray<>(); @@ -60,9 +64,11 @@ public class FreeformTaskListener<T extends AutoCloseable> public FreeformTaskListener( ShellInit shellInit, ShellTaskOrganizer shellTaskOrganizer, + Optional<RecentTasksController> recentTasksController, WindowDecorViewModel<T> windowDecorationViewModel) { mShellTaskOrganizer = shellTaskOrganizer; mWindowDecorationViewModel = windowDecorationViewModel; + mRecentTasksOptional = recentTasksController; if (shellInit != null) { shellInit.addInitCallback(this::onInit, this); } @@ -83,6 +89,12 @@ public class FreeformTaskListener<T extends AutoCloseable> mWindowDecorationViewModel.createWindowDecoration(taskInfo, leash, t, t); t.apply(); } + + if (DesktopMode.IS_SUPPORTED && taskInfo.isVisible) { + ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE, + "Adding active freeform task: #%d", taskInfo.taskId); + mRecentTasksOptional.ifPresent(rt -> rt.addActiveFreeformTask(taskInfo.taskId)); + } } private State<T> createOrUpdateTaskState(RunningTaskInfo taskInfo, SurfaceControl leash) { @@ -111,6 +123,12 @@ public class FreeformTaskListener<T extends AutoCloseable> taskInfo.taskId); mTasks.remove(taskInfo.taskId); + if (DesktopMode.IS_SUPPORTED) { + ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE, + "Removing active freeform task: #%d", taskInfo.taskId); + mRecentTasksOptional.ifPresent(rt -> rt.removeActiveFreeformTask(taskInfo.taskId)); + } + if (Transitions.ENABLE_SHELL_TRANSITIONS) { // Save window decorations of closing tasks so that we can hand them over to the // transition system if this method happens before the transition. In case where the @@ -131,6 +149,14 @@ public class FreeformTaskListener<T extends AutoCloseable> if (state.mWindowDecoration != null) { mWindowDecorationViewModel.onTaskInfoChanged(state.mTaskInfo, state.mWindowDecoration); } + + if (DesktopMode.IS_SUPPORTED) { + if (taskInfo.isVisible) { + ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DESKTOP_MODE, + "Adding active freeform task: #%d", taskInfo.taskId); + mRecentTasksOptional.ifPresent(rt -> rt.addActiveFreeformTask(taskInfo.taskId)); + } + } } private State<T> updateTaskInfo(RunningTaskInfo taskInfo) { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/fullscreen/FullscreenTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/fullscreen/FullscreenTaskListener.java index e9f9bb5d7327..7d1259a732c9 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/fullscreen/FullscreenTaskListener.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/fullscreen/FullscreenTaskListener.java @@ -16,8 +16,6 @@ package com.android.wm.shell.fullscreen; -import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; - import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_FULLSCREEN; import static com.android.wm.shell.ShellTaskOrganizer.taskListenerTypeToString; @@ -107,13 +105,14 @@ public class FullscreenTaskListener<T extends AutoCloseable> if (Transitions.ENABLE_SHELL_TRANSITIONS) return; updateRecentsForVisibleFullscreenTask(taskInfo); - if (shouldShowWindowDecor(taskInfo) && mWindowDecorViewModelOptional.isPresent()) { + if (mWindowDecorViewModelOptional.isPresent()) { SurfaceControl.Transaction t = new SurfaceControl.Transaction(); state.mWindowDecoration = mWindowDecorViewModelOptional.get().createWindowDecoration(taskInfo, leash, t, t); t.apply(); - } else { + } + if (state.mWindowDecoration == null) { mSyncQueue.runInSync(t -> { // Reset several properties back to fullscreen (PiP, for example, leaves all these // properties in a bad state). @@ -178,13 +177,12 @@ public class FullscreenTaskListener<T extends AutoCloseable> public void createWindowDecoration(TransitionInfo.Change change, SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT) { final State<T> state = createOrUpdateTaskState(change.getTaskInfo(), change.getLeash()); - if (!mWindowDecorViewModelOptional.isPresent() - || !shouldShowWindowDecor(state.mTaskInfo)) { - return; - } - - state.mWindowDecoration = mWindowDecorViewModelOptional.get().createWindowDecoration( + if (!mWindowDecorViewModelOptional.isPresent()) return; + T newWindowDecor = mWindowDecorViewModelOptional.get().createWindowDecoration( state.mTaskInfo, state.mLeash, startT, finishT); + if (newWindowDecor != null) { + state.mWindowDecoration = newWindowDecor; + } } /** @@ -202,8 +200,7 @@ public class FullscreenTaskListener<T extends AutoCloseable> SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT, @Nullable AutoCloseable windowDecor) { - if (!mWindowDecorViewModelOptional.isPresent() - || !shouldShowWindowDecor(change.getTaskInfo())) { + if (!mWindowDecorViewModelOptional.isPresent()) { return false; } final State<T> state = createOrUpdateTaskState(change.getTaskInfo(), change.getLeash()); @@ -214,8 +211,11 @@ public class FullscreenTaskListener<T extends AutoCloseable> state.mTaskInfo, startT, finishT, state.mWindowDecoration); return true; } else { - state.mWindowDecoration = mWindowDecorViewModelOptional.get().createWindowDecoration( + T newWindowDecor = mWindowDecorViewModelOptional.get().createWindowDecoration( state.mTaskInfo, state.mLeash, startT, finishT); + if (newWindowDecor != null) { + state.mWindowDecoration = newWindowDecor; + } return false; } } @@ -256,7 +256,7 @@ public class FullscreenTaskListener<T extends AutoCloseable> windowDecor = mWindowDecorOfVanishedTasks.removeReturnOld(taskInfo.taskId); } - if (mWindowDecorViewModelOptional.isPresent()) { + if (mWindowDecorViewModelOptional.isPresent() && windowDecor != null) { mWindowDecorViewModelOptional.get().setupWindowDecorationForTransition( taskInfo, startT, finishT, windowDecor); } @@ -336,10 +336,5 @@ public class FullscreenTaskListener<T extends AutoCloseable> return TAG + ":" + taskListenerTypeToString(TASK_LISTENER_TYPE_FULLSCREEN); } - private static boolean shouldShowWindowDecor(RunningTaskInfo taskInfo) { - return taskInfo.getConfiguration().windowConfiguration.getDisplayWindowingMode() - == WINDOWING_MODE_FREEFORM; - } - } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java index 297c79e86ad1..f170e774739f 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java @@ -966,7 +966,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener, // Re-set the PIP bounds to none. mPipBoundsState.setBounds(new Rect()); mPipUiEventLoggerLogger.setTaskInfo(null); - mMainExecutor.executeDelayed(() -> mPipMenuController.detach(), 0); + mPipMenuController.detach(); mLeash = null; if (info.displayId != Display.DEFAULT_DISPLAY && mOnDisplayIdChangeCallback != null) { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java index 6c9a6b64c864..3d879b685706 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java @@ -49,6 +49,7 @@ import android.os.UserManager; import android.util.Pair; import android.util.Size; import android.view.DisplayInfo; +import android.view.InsetsState; import android.view.SurfaceControl; import android.view.WindowManagerGlobal; import android.window.WindowContainerTransaction; @@ -64,6 +65,7 @@ import com.android.wm.shell.R; import com.android.wm.shell.WindowManagerShellWrapper; import com.android.wm.shell.common.DisplayChangeController; import com.android.wm.shell.common.DisplayController; +import com.android.wm.shell.common.DisplayInsetsController; import com.android.wm.shell.common.DisplayLayout; import com.android.wm.shell.common.RemoteCallable; import com.android.wm.shell.common.ShellExecutor; @@ -112,6 +114,9 @@ public class PipController implements PipTransitionController.PipTransitionCallb UserChangeListener { private static final String TAG = "PipController"; + private static final long PIP_KEEP_CLEAR_AREAS_DELAY = + SystemProperties.getLong("persist.wm.debug.pip_keep_clear_areas_delay", 200); + private boolean mEnablePipKeepClearAlgorithm = SystemProperties.getBoolean("persist.wm.debug.enable_pip_keep_clear_algorithm", false); @@ -135,6 +140,7 @@ public class PipController implements PipTransitionController.PipTransitionCallb private PipTransitionController mPipTransitionController; private TaskStackListenerImpl mTaskStackListener; private PipParamsChangedForwarder mPipParamsChangedForwarder; + private DisplayInsetsController mDisplayInsetsController; private Optional<OneHandedController> mOneHandedController; private final ShellCommandHandler mShellCommandHandler; private final ShellController mShellController; @@ -143,6 +149,8 @@ public class PipController implements PipTransitionController.PipTransitionCallb private final Rect mTmpInsetBounds = new Rect(); private final int mEnterAnimationDuration; + private final Runnable mMovePipInResponseToKeepClearAreasChangeCallback; + private boolean mIsInFixedRotation; private PipAnimationListener mPinnedStackAnimationRecentsCallback; @@ -274,14 +282,12 @@ public class PipController implements PipTransitionController.PipTransitionCallb if (mPipBoundsState.getDisplayId() == displayId) { if (mEnablePipKeepClearAlgorithm) { mPipBoundsState.setKeepClearAreas(restricted, unrestricted); - // only move if already in pip, other transitions account for keep clear - // areas - if (mPipTransitionState.hasEnteredPip()) { - Rect destBounds = mPipKeepClearAlgorithm.adjust(mPipBoundsState, - mPipBoundsAlgorithm); - mPipTaskOrganizer.scheduleAnimateResizePip(destBounds, - mEnterAnimationDuration, null); - } + + mMainExecutor.removeCallbacks( + mMovePipInResponseToKeepClearAreasChangeCallback); + mMainExecutor.executeDelayed( + mMovePipInResponseToKeepClearAreasChangeCallback, + PIP_KEEP_CLEAR_AREAS_DELAY); } } } @@ -338,6 +344,7 @@ public class PipController implements PipTransitionController.PipTransitionCallb WindowManagerShellWrapper windowManagerShellWrapper, TaskStackListenerImpl taskStackListener, PipParamsChangedForwarder pipParamsChangedForwarder, + DisplayInsetsController displayInsetsController, Optional<OneHandedController> oneHandedController, ShellExecutor mainExecutor) { if (!context.getPackageManager().hasSystemFeature(FEATURE_PICTURE_IN_PICTURE)) { @@ -351,7 +358,7 @@ public class PipController implements PipTransitionController.PipTransitionCallb pipBoundsState, pipMotionHelper, pipMediaController, phonePipMenuController, pipTaskOrganizer, pipTransitionState, pipTouchHandler, pipTransitionController, windowManagerShellWrapper, taskStackListener, pipParamsChangedForwarder, - oneHandedController, mainExecutor) + displayInsetsController, oneHandedController, mainExecutor) .mImpl; } @@ -374,6 +381,7 @@ public class PipController implements PipTransitionController.PipTransitionCallb WindowManagerShellWrapper windowManagerShellWrapper, TaskStackListenerImpl taskStackListener, PipParamsChangedForwarder pipParamsChangedForwarder, + DisplayInsetsController displayInsetsController, Optional<OneHandedController> oneHandedController, ShellExecutor mainExecutor ) { @@ -406,7 +414,17 @@ public class PipController implements PipTransitionController.PipTransitionCallb mEnterAnimationDuration = mContext.getResources() .getInteger(R.integer.config_pipEnterAnimationDuration); + mMovePipInResponseToKeepClearAreasChangeCallback = () -> { + // only move if already in pip, other transitions account for keep clear areas + if (mPipTransitionState.hasEnteredPip()) { + Rect destBounds = mPipKeepClearAlgorithm.adjust(mPipBoundsState, + mPipBoundsAlgorithm); + mPipTaskOrganizer.scheduleAnimateResizePip(destBounds, + mEnterAnimationDuration, null); + } + }; mPipParamsChangedForwarder = pipParamsChangedForwarder; + mDisplayInsetsController = displayInsetsController; shellInit.addInitCallback(this::onInit, this); } @@ -549,6 +567,16 @@ public class PipController implements PipTransitionController.PipTransitionCallb } }); + mDisplayInsetsController.addInsetsChangedListener(mPipBoundsState.getDisplayId(), + new DisplayInsetsController.OnInsetsChangedListener() { + @Override + public void insetsChanged(InsetsState insetsState) { + onDisplayChanged( + mDisplayController.getDisplayLayout(mPipBoundsState.getDisplayId()), + false /* saveRestoreSnapFraction */); + } + }); + mOneHandedController.ifPresent(controller -> { controller.registerTransitionCallback( new OneHandedTransitionCallback() { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipDoubleTapHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipDoubleTapHelper.java new file mode 100644 index 000000000000..acc0caf95e35 --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipDoubleTapHelper.java @@ -0,0 +1,123 @@ +/* + * 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.wm.shell.pip.phone; + +import android.annotation.IntDef; +import android.annotation.NonNull; +import android.graphics.Rect; + +import com.android.wm.shell.pip.PipBoundsState; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Static utilities to get appropriate {@link PipDoubleTapHelper.PipSizeSpec} on a double tap. + */ +public class PipDoubleTapHelper { + + /** + * Should not be instantiated as a stateless class. + */ + private PipDoubleTapHelper() {} + + /** + * A constant that represents a pip screen size. + * + * <p>CUSTOM - user resized screen size (by pinching in/out)</p> + * <p>DEFAULT - normal screen size used as default when entering pip mode</p> + * <p>MAX - maximum allowed screen size</p> + */ + @IntDef(value = { + SIZE_SPEC_CUSTOM, + SIZE_SPEC_DEFAULT, + SIZE_SPEC_MAX + }) + @Retention(RetentionPolicy.SOURCE) + @interface PipSizeSpec {} + + static final int SIZE_SPEC_CUSTOM = 2; + static final int SIZE_SPEC_DEFAULT = 0; + static final int SIZE_SPEC_MAX = 1; + + /** + * Returns MAX or DEFAULT {@link PipSizeSpec} to toggle to/from. + * + * <p>Each double tap toggles back and forth between {@code PipSizeSpec.CUSTOM} and + * either {@code PipSizeSpec.MAX} or {@code PipSizeSpec.DEFAULT}. The choice between + * the latter two sizes is determined based on the current state of the pip screen.</p> + * + * @param mPipBoundsState current state of the pip screen + */ + @PipSizeSpec + private static int getMaxOrDefaultPipSizeSpec(@NonNull PipBoundsState mPipBoundsState) { + // determine the average pip screen width + int averageWidth = (mPipBoundsState.getMaxSize().x + + mPipBoundsState.getMinSize().x) / 2; + + // If pip screen width is above average, DEFAULT is the size spec we need to + // toggle to. Otherwise, we choose MAX. + return (mPipBoundsState.getBounds().width() > averageWidth) + ? SIZE_SPEC_DEFAULT + : SIZE_SPEC_MAX; + } + + /** + * Determines the {@link PipSizeSpec} to toggle to on double tap. + * + * @param mPipBoundsState current state of the pip screen + * @param userResizeBounds latest user resized bounds (by pinching in/out) + * @return pip screen size to switch to + */ + @PipSizeSpec + static int nextSizeSpec(@NonNull PipBoundsState mPipBoundsState, + @NonNull Rect userResizeBounds) { + // is pip screen at its maximum + boolean isScreenMax = mPipBoundsState.getBounds().width() + == mPipBoundsState.getMaxSize().x; + + // is pip screen at its normal default size + boolean isScreenDefault = (mPipBoundsState.getBounds().width() + == mPipBoundsState.getNormalBounds().width()) + && (mPipBoundsState.getBounds().height() + == mPipBoundsState.getNormalBounds().height()); + + // edge case 1 + // if user hasn't resized screen yet, i.e. CUSTOM size does not exist yet + // or if user has resized exactly to DEFAULT, then we just want to maximize + if (isScreenDefault + && userResizeBounds.width() == mPipBoundsState.getNormalBounds().width()) { + return SIZE_SPEC_MAX; + } + + // edge case 2 + // if user has maximized, then we want to toggle to DEFAULT + if (isScreenMax + && userResizeBounds.width() == mPipBoundsState.getMaxSize().x) { + return SIZE_SPEC_DEFAULT; + } + + // otherwise in general we want to toggle back to user's CUSTOM size + if (isScreenDefault || isScreenMax) { + return SIZE_SPEC_CUSTOM; + } + + // if we are currently in user resized CUSTOM size state + // then we toggle either to MAX or DEFAULT depending on the current pip screen state + return getMaxOrDefaultPipSizeSpec(mPipBoundsState); + } +} 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 a2fa058e97b7..84d9217e6fb3 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 @@ -929,9 +929,18 @@ public class PipTouchHandler { if (mMenuController.isMenuVisible()) { mMenuController.hideMenu(ANIM_TYPE_NONE, false /* resize */); } - if (toExpand) { + + // the size to toggle to after a double tap + int nextSize = PipDoubleTapHelper + .nextSizeSpec(mPipBoundsState, getUserResizeBounds()); + + // actually toggle to the size chosen + if (nextSize == PipDoubleTapHelper.SIZE_SPEC_MAX) { mPipResizeGestureHandler.setUserResizeBounds(mPipBoundsState.getBounds()); animateToMaximizedState(null); + } else if (nextSize == PipDoubleTapHelper.SIZE_SPEC_DEFAULT) { + mPipResizeGestureHandler.setUserResizeBounds(mPipBoundsState.getBounds()); + animateToNormalSize(null); } else { animateToUnexpandedState(getUserResizeBounds()); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogGroup.java b/libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogGroup.java index 93c75299a64b..3fef82352728 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogGroup.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogGroup.java @@ -32,7 +32,7 @@ public enum ShellProtoLogGroup implements IProtoLogGroup { Consts.TAG_WM_SHELL), WM_SHELL_TRANSITIONS(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, true, Consts.TAG_WM_SHELL), - WM_SHELL_DRAG_AND_DROP(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false, + WM_SHELL_DRAG_AND_DROP(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, true, Consts.TAG_WM_SHELL), WM_SHELL_STARTING_WINDOW(Consts.ENABLE_DEBUG, Consts.ENABLE_LOG_TO_PROTO_DEBUG, false, Consts.TAG_WM_STARTING_WINDOW), diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java index 7b42350b1365..27bc1a189086 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentTasksController.java @@ -43,6 +43,7 @@ import com.android.wm.shell.common.TaskStackListenerCallback; import com.android.wm.shell.common.TaskStackListenerImpl; import com.android.wm.shell.common.annotations.ExternalThread; import com.android.wm.shell.common.annotations.ShellMainThread; +import com.android.wm.shell.desktopmode.DesktopMode; import com.android.wm.shell.protolog.ShellProtoLogGroup; import com.android.wm.shell.sysui.ShellCommandHandler; import com.android.wm.shell.sysui.ShellInit; @@ -52,6 +53,7 @@ import com.android.wm.shell.util.SplitBounds; import java.io.PrintWriter; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; @@ -82,6 +84,15 @@ public class RecentTasksController implements TaskStackListenerCallback, private final Map<Integer, SplitBounds> mTaskSplitBoundsMap = new HashMap<>(); /** + * Set of taskId's that have been launched in freeform mode. + * This includes tasks that are currently running, visible and in freeform mode. And also + * includes tasks that are running in the background, are no longer visible, but at some point + * were visible to the user. + * This is used to decide which freeform apps belong to the user's desktop. + */ + private final HashSet<Integer> mActiveFreeformTasks = new HashSet<>(); + + /** * Creates {@link RecentTasksController}, returns {@code null} if the feature is not * supported. */ @@ -206,6 +217,22 @@ public class RecentTasksController implements TaskStackListenerCallback, notifyRecentTasksChanged(); } + /** + * Mark a task with given {@code taskId} as active in freeform + */ + public void addActiveFreeformTask(int taskId) { + mActiveFreeformTasks.add(taskId); + notifyRecentTasksChanged(); + } + + /** + * Remove task with given {@code taskId} from active freeform tasks + */ + public void removeActiveFreeformTask(int taskId) { + mActiveFreeformTasks.remove(taskId); + notifyRecentTasksChanged(); + } + @VisibleForTesting void notifyRecentTasksChanged() { ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENT_TASKS, "Notify recent tasks changed"); @@ -273,6 +300,9 @@ public class RecentTasksController implements TaskStackListenerCallback, rawMapping.put(taskInfo.taskId, taskInfo); } + boolean desktopModeActive = DesktopMode.isActive(mContext); + ArrayList<ActivityManager.RecentTaskInfo> freeformTasks = new ArrayList<>(); + // Pull out the pairs as we iterate back in the list ArrayList<GroupedRecentTaskInfo> recentTasks = new ArrayList<>(); for (int i = 0; i < rawList.size(); i++) { @@ -282,16 +312,31 @@ public class RecentTasksController implements TaskStackListenerCallback, continue; } + if (desktopModeActive && mActiveFreeformTasks.contains(taskInfo.taskId)) { + // Freeform tasks will be added as a separate entry + freeformTasks.add(taskInfo); + continue; + } + final int pairedTaskId = mSplitTasks.get(taskInfo.taskId); - if (pairedTaskId != INVALID_TASK_ID && rawMapping.contains(pairedTaskId)) { + if (!desktopModeActive && pairedTaskId != INVALID_TASK_ID && rawMapping.contains( + pairedTaskId)) { final ActivityManager.RecentTaskInfo pairedTaskInfo = rawMapping.get(pairedTaskId); rawMapping.remove(pairedTaskId); - recentTasks.add(new GroupedRecentTaskInfo(taskInfo, pairedTaskInfo, + recentTasks.add(GroupedRecentTaskInfo.forSplitTasks(taskInfo, pairedTaskInfo, mTaskSplitBoundsMap.get(pairedTaskId))); } else { - recentTasks.add(new GroupedRecentTaskInfo(taskInfo)); + recentTasks.add(GroupedRecentTaskInfo.forSingleTask(taskInfo)); } } + + // Add a special entry for freeform tasks + if (!freeformTasks.isEmpty()) { + // First task is added separately + recentTasks.add(0, GroupedRecentTaskInfo.forFreeformTasks( + freeformTasks.toArray(new ActivityManager.RecentTaskInfo[0]))); + } + return recentTasks; } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ISplitScreen.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ISplitScreen.aidl index 3714fe713288..ecdafa9a63f4 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ISplitScreen.aidl +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ISplitScreen.aidl @@ -21,6 +21,7 @@ import android.content.Intent; import android.content.pm.ShortcutInfo; import android.os.Bundle; import android.os.UserHandle; +import com.android.internal.logging.InstanceId; import android.view.RemoteAnimationAdapter; import android.view.RemoteAnimationTarget; import android.window.RemoteTransition; @@ -67,34 +68,35 @@ interface ISplitScreen { * Starts a shortcut in a stage. */ oneway void startShortcut(String packageName, String shortcutId, int position, - in Bundle options, in UserHandle user) = 8; + in Bundle options, in UserHandle user, in InstanceId instanceId) = 8; /** * Starts an activity in a stage. */ oneway void startIntent(in PendingIntent intent, in Intent fillInIntent, int position, - in Bundle options) = 9; + in Bundle options, in InstanceId instanceId) = 9; /** * Starts tasks simultaneously in one transition. */ oneway void startTasks(int mainTaskId, in Bundle mainOptions, int sideTaskId, in Bundle sideOptions, int sidePosition, float splitRatio, - in RemoteTransition remoteTransition) = 10; + in RemoteTransition remoteTransition, in InstanceId instanceId) = 10; /** * Version of startTasks using legacy transition system. */ oneway void startTasksWithLegacyTransition(int mainTaskId, in Bundle mainOptions, int sideTaskId, in Bundle sideOptions, int sidePosition, - float splitRatio, in RemoteAnimationAdapter adapter) = 11; + float splitRatio, in RemoteAnimationAdapter adapter, in InstanceId instanceId) = 11; /** * Starts a pair of intent and task using legacy transition system. */ oneway void startIntentAndTaskWithLegacyTransition(in PendingIntent pendingIntent, in Intent fillInIntent, int taskId, in Bundle mainOptions,in Bundle sideOptions, - int sidePosition, float splitRatio, in RemoteAnimationAdapter adapter) = 12; + int sidePosition, float splitRatio, in RemoteAnimationAdapter adapter, + in InstanceId instanceId) = 12; /** * Blocking call that notifies and gets additional split-screen targets when entering @@ -115,5 +117,5 @@ interface ISplitScreen { */ oneway void startShortcutAndTaskWithLegacyTransition(in ShortcutInfo shortcutInfo, int taskId, in Bundle mainOptions, in Bundle sideOptions, int sidePosition, float splitRatio, - in RemoteAnimationAdapter adapter) = 15; + in RemoteAnimationAdapter adapter, in InstanceId instanceId) = 15; } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MainStage.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MainStage.java index b0080b24c609..e7ec15e70c11 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MainStage.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MainStage.java @@ -45,11 +45,6 @@ class MainStage extends StageTaskListener { iconProvider); } - @Override - void dismiss(WindowContainerTransaction wct, boolean toTop) { - deactivate(wct, toTop); - } - boolean isActive() { return mIsActive; } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java index 86efbe0af79c..8639b36faf4c 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java @@ -42,11 +42,6 @@ class SideStage extends StageTaskListener { iconProvider); } - @Override - void dismiss(WindowContainerTransaction wct, boolean toTop) { - removeAllTasks(wct, toTop); - } - boolean removeAllTasks(WindowContainerTransaction wct, boolean toTop) { if (mChildrenTaskInfo.size() == 0) return false; wct.reparentTasks( diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java index 169e17b770f3..025e5592e367 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java @@ -147,7 +147,6 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, private final DragAndDropController mDragAndDropController; private final Transitions mTransitions; private final TransactionPool mTransactionPool; - private final SplitscreenEventLogger mLogger; private final IconProvider mIconProvider; private final Optional<RecentTasksController> mRecentTasksOptional; private final SplitScreenShellCommandHandler mSplitScreenShellCommandHandler; @@ -186,7 +185,6 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, mDragAndDropController = dragAndDropController; mTransitions = transitions; mTransactionPool = transactionPool; - mLogger = new SplitscreenEventLogger(); mIconProvider = iconProvider; mRecentTasksOptional = recentTasks; mSplitScreenShellCommandHandler = new SplitScreenShellCommandHandler(this); @@ -213,14 +211,18 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, mShellController.addKeyguardChangeListener(this); if (mStageCoordinator == null) { // TODO: Multi-display - mStageCoordinator = new StageCoordinator(mContext, DEFAULT_DISPLAY, mSyncQueue, - mTaskOrganizer, mDisplayController, mDisplayImeController, - mDisplayInsetsController, mTransitions, mTransactionPool, mLogger, - mIconProvider, mMainExecutor, mRecentTasksOptional); + mStageCoordinator = createStageCoordinator(); } mDragAndDropController.setSplitScreenController(this); } + protected StageCoordinator createStageCoordinator() { + return new StageCoordinator(mContext, DEFAULT_DISPLAY, mSyncQueue, + mTaskOrganizer, mDisplayController, mDisplayImeController, + mDisplayInsetsController, mTransitions, mTransactionPool, + mIconProvider, mMainExecutor, mRecentTasksOptional); + } + @Override public Context getContext() { return mContext; @@ -385,6 +387,17 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, } } + /** + * See {@link #startShortcut(String, String, int, Bundle, UserHandle)} + * @param instanceId to be used by {@link SplitscreenEventLogger} + */ + public void startShortcut(String packageName, String shortcutId, @SplitPosition int position, + @Nullable Bundle options, UserHandle user, @NonNull InstanceId instanceId) { + mStageCoordinator.getLogger().enterRequested(instanceId); + startShortcut(packageName, shortcutId, position, options, user); + } + + @Override public void startShortcut(String packageName, String shortcutId, @SplitPosition int position, @Nullable Bundle options, UserHandle user) { IRemoteAnimationRunner wrapper = new IRemoteAnimationRunner.Stub() { @@ -413,7 +426,6 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, 0 /* duration */, 0 /* statusBarTransitionDelay */); ActivityOptions activityOptions = ActivityOptions.fromBundle(options); activityOptions.update(ActivityOptions.makeRemoteAnimation(wrappedAdapter)); - try { LauncherApps launcherApps = mContext.getSystemService(LauncherApps.class); launcherApps.startShortcut(packageName, shortcutId, null /* sourceBounds */, @@ -423,6 +435,17 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, } } + /** + * See {@link #startIntent(PendingIntent, Intent, int, Bundle)} + * @param instanceId to be used by {@link SplitscreenEventLogger} + */ + public void startIntent(PendingIntent intent, @Nullable Intent fillInIntent, + @SplitPosition int position, @Nullable Bundle options, @NonNull InstanceId instanceId) { + mStageCoordinator.getLogger().enterRequested(instanceId); + startIntent(intent, fillInIntent, position, options); + } + + @Override public void startIntent(PendingIntent intent, @Nullable Intent fillInIntent, @SplitPosition int position, @Nullable Bundle options) { if (fillInIntent == null) { @@ -444,7 +467,6 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, mStageCoordinator.startIntentLegacy(intent, fillInIntent, position, options); return; } - mStageCoordinator.startIntent(intent, fillInIntent, position, options); } @@ -770,60 +792,64 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, @Override public void startTasksWithLegacyTransition(int mainTaskId, @Nullable Bundle mainOptions, int sideTaskId, @Nullable Bundle sideOptions, @SplitPosition int sidePosition, - float splitRatio, RemoteAnimationAdapter adapter) { + float splitRatio, RemoteAnimationAdapter adapter, InstanceId instanceId) { executeRemoteCallWithTaskPermission(mController, "startTasks", (controller) -> controller.mStageCoordinator.startTasksWithLegacyTransition( mainTaskId, mainOptions, sideTaskId, sideOptions, sidePosition, - splitRatio, adapter)); + splitRatio, adapter, instanceId)); } @Override public void startIntentAndTaskWithLegacyTransition(PendingIntent pendingIntent, Intent fillInIntent, int taskId, Bundle mainOptions, Bundle sideOptions, - int sidePosition, float splitRatio, RemoteAnimationAdapter adapter) { + int sidePosition, float splitRatio, RemoteAnimationAdapter adapter, + InstanceId instanceId) { executeRemoteCallWithTaskPermission(mController, "startIntentAndTaskWithLegacyTransition", (controller) -> controller.mStageCoordinator.startIntentAndTaskWithLegacyTransition( pendingIntent, fillInIntent, taskId, mainOptions, sideOptions, - sidePosition, splitRatio, adapter)); + sidePosition, splitRatio, adapter, instanceId)); } @Override public void startShortcutAndTaskWithLegacyTransition(ShortcutInfo shortcutInfo, int taskId, @Nullable Bundle mainOptions, @Nullable Bundle sideOptions, - @SplitPosition int sidePosition, float splitRatio, RemoteAnimationAdapter adapter) { + @SplitPosition int sidePosition, float splitRatio, RemoteAnimationAdapter adapter, + InstanceId instanceId) { executeRemoteCallWithTaskPermission(mController, "startShortcutAndTaskWithLegacyTransition", (controller) -> controller.mStageCoordinator.startShortcutAndTaskWithLegacyTransition( shortcutInfo, taskId, mainOptions, sideOptions, sidePosition, - splitRatio, adapter)); + splitRatio, adapter, instanceId)); } @Override public void startTasks(int mainTaskId, @Nullable Bundle mainOptions, int sideTaskId, @Nullable Bundle sideOptions, @SplitPosition int sidePosition, float splitRatio, - @Nullable RemoteTransition remoteTransition) { + @Nullable RemoteTransition remoteTransition, InstanceId instanceId) { executeRemoteCallWithTaskPermission(mController, "startTasks", (controller) -> controller.mStageCoordinator.startTasks(mainTaskId, mainOptions, - sideTaskId, sideOptions, sidePosition, splitRatio, remoteTransition)); + sideTaskId, sideOptions, sidePosition, splitRatio, remoteTransition, + instanceId)); } @Override public void startShortcut(String packageName, String shortcutId, int position, - @Nullable Bundle options, UserHandle user) { + @Nullable Bundle options, UserHandle user, InstanceId instanceId) { executeRemoteCallWithTaskPermission(mController, "startShortcut", (controller) -> { - controller.startShortcut(packageName, shortcutId, position, options, user); + controller.startShortcut(packageName, shortcutId, position, options, user, + instanceId); }); } @Override public void startIntent(PendingIntent intent, Intent fillInIntent, int position, - @Nullable Bundle options) { + @Nullable Bundle options, InstanceId instanceId) { executeRemoteCallWithTaskPermission(mController, "startIntent", (controller) -> { - controller.startIntent(intent, fillInIntent, position, options); + controller.startIntent(intent, fillInIntent, position, options, instanceId); }); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitscreenEventLogger.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitscreenEventLogger.java index 3e7a1004ed7a..626ccb1d2890 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitscreenEventLogger.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitscreenEventLogger.java @@ -16,7 +16,7 @@ package com.android.wm.shell.splitscreen; -import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__ENTER_REASON__OVERVIEW; +import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__ENTER_REASON__LAUNCHER; import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__APP_DOES_NOT_SUPPORT_MULTIWINDOW; import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__APP_FINISHED; import static com.android.internal.util.FrameworkStatsLog.SPLITSCREEN_UICHANGED__EXIT_REASON__DEVICE_FOLDED; @@ -59,7 +59,7 @@ public class SplitscreenEventLogger { // Drag info private @SplitPosition int mDragEnterPosition; - private InstanceId mDragEnterSessionId; + private InstanceId mEnterSessionId; // For deduping async events private int mLastMainStagePosition = -1; @@ -82,9 +82,17 @@ public class SplitscreenEventLogger { /** * May be called before logEnter() to indicate that the session was started from a drag. */ - public void enterRequestedByDrag(@SplitPosition int position, InstanceId dragSessionId) { + public void enterRequestedByDrag(@SplitPosition int position, InstanceId enterSessionId) { mDragEnterPosition = position; - mDragEnterSessionId = dragSessionId; + enterRequested(enterSessionId); + } + + /** + * May be called before logEnter() to indicate that the session was started from launcher. + * This specifically is for all the scenarios where split started without a drag interaction + */ + public void enterRequested(InstanceId enterSessionId) { + mEnterSessionId = enterSessionId; } /** @@ -97,7 +105,7 @@ public class SplitscreenEventLogger { mLoggerSessionId = mIdSequence.newInstanceId(); int enterReason = mDragEnterPosition != SPLIT_POSITION_UNDEFINED ? getDragEnterReasonFromSplitPosition(mDragEnterPosition, isLandscape) - : SPLITSCREEN_UICHANGED__ENTER_REASON__OVERVIEW; + : SPLITSCREEN_UICHANGED__ENTER_REASON__LAUNCHER; updateMainStageState(getMainStagePositionFromSplitPosition(mainStagePosition, isLandscape), mainStageUid); updateSideStageState(getSideStagePositionFromSplitPosition(sideStagePosition, isLandscape), @@ -112,7 +120,7 @@ public class SplitscreenEventLogger { mLastMainStageUid, mLastSideStagePosition, mLastSideStageUid, - mDragEnterSessionId != null ? mDragEnterSessionId.getId() : 0, + mEnterSessionId != null ? mEnterSessionId.getId() : 0, mLoggerSessionId.getId()); } @@ -176,7 +184,7 @@ public class SplitscreenEventLogger { // Reset states mLoggerSessionId = null; mDragEnterPosition = SPLIT_POSITION_UNDEFINED; - mDragEnterSessionId = null; + mEnterSessionId = null; mLastMainStagePosition = -1; mLastMainStageUid = -1; mLastSideStagePosition = -1; 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 dcfe08d7a329..db35b48eb898 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 @@ -69,6 +69,8 @@ import android.annotation.CallSuper; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager; +import android.app.ActivityOptions; +import android.app.IActivityTaskManager; import android.app.PendingIntent; import android.app.WindowConfiguration; import android.content.Context; @@ -81,10 +83,12 @@ import android.os.Bundle; import android.os.Debug; import android.os.IBinder; import android.os.RemoteException; +import android.os.ServiceManager; import android.util.Log; import android.util.Slog; import android.view.Choreographer; import android.view.IRemoteAnimationFinishedCallback; +import android.view.IRemoteAnimationRunner; import android.view.RemoteAnimationAdapter; import android.view.RemoteAnimationTarget; import android.view.SurfaceControl; @@ -119,6 +123,7 @@ import com.android.wm.shell.protolog.ShellProtoLogGroup; import com.android.wm.shell.recents.RecentTasksController; import com.android.wm.shell.splitscreen.SplitScreen.StageType; import com.android.wm.shell.splitscreen.SplitScreenController.ExitReason; +import com.android.wm.shell.transition.DefaultMixedHandler; import com.android.wm.shell.transition.LegacyTransitions; import com.android.wm.shell.transition.Transitions; import com.android.wm.shell.util.SplitBounds; @@ -199,6 +204,8 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, @StageType private int mTopStageAfterFoldDismiss = STAGE_TYPE_UNDEFINED; + private DefaultMixedHandler mMixedHandler; + private final SplitWindowManager.ParentContainerCallbacks mParentContainerCallbacks = new SplitWindowManager.ParentContainerCallbacks() { @Override @@ -244,18 +251,18 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, } }; - StageCoordinator(Context context, int displayId, SyncTransactionQueue syncQueue, + protected StageCoordinator(Context context, int displayId, SyncTransactionQueue syncQueue, ShellTaskOrganizer taskOrganizer, DisplayController displayController, DisplayImeController displayImeController, DisplayInsetsController displayInsetsController, Transitions transitions, - TransactionPool transactionPool, SplitscreenEventLogger logger, + TransactionPool transactionPool, IconProvider iconProvider, ShellExecutor mainExecutor, Optional<RecentTasksController> recentTasks) { mContext = context; mDisplayId = displayId; mSyncQueue = syncQueue; mTaskOrganizer = taskOrganizer; - mLogger = logger; + mLogger = new SplitscreenEventLogger(); mMainExecutor = mainExecutor; mRecentTasks = recentTasks; @@ -299,7 +306,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, DisplayController displayController, DisplayImeController displayImeController, DisplayInsetsController displayInsetsController, SplitLayout splitLayout, Transitions transitions, TransactionPool transactionPool, - SplitscreenEventLogger logger, ShellExecutor mainExecutor, + ShellExecutor mainExecutor, Optional<RecentTasksController> recentTasks) { mContext = context; mDisplayId = displayId; @@ -314,7 +321,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, mSplitLayout = splitLayout; mSplitTransitions = new SplitScreenTransitions(transactionPool, transitions, this::onTransitionAnimationComplete, this); - mLogger = logger; + mLogger = new SplitscreenEventLogger(); mMainExecutor = mainExecutor; mRecentTasks = recentTasks; mDisplayController.addDisplayWindowListener(this); @@ -322,6 +329,10 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, transitions.addHandler(this); } + public void setMixedHandler(DefaultMixedHandler mixedHandler) { + mMixedHandler = mixedHandler; + } + @VisibleForTesting SplitScreenTransitions getSplitTransitions() { return mSplitTransitions; @@ -403,6 +414,10 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, return result; } + SplitscreenEventLogger getLogger() { + return mLogger; + } + /** Launches an activity into split. */ void startIntent(PendingIntent intent, Intent fillInIntent, @SplitPosition int position, @Nullable Bundle options) { @@ -495,7 +510,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, /** Starts 2 tasks in one transition. */ void startTasks(int mainTaskId, @Nullable Bundle mainOptions, int sideTaskId, @Nullable Bundle sideOptions, @SplitPosition int sidePosition, float splitRatio, - @Nullable RemoteTransition remoteTransition) { + @Nullable RemoteTransition remoteTransition, InstanceId instanceId) { final WindowContainerTransaction wct = new WindowContainerTransaction(); mainOptions = mainOptions != null ? mainOptions : new Bundle(); sideOptions = sideOptions != null ? sideOptions : new Bundle(); @@ -524,46 +539,57 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, mSplitTransitions.startEnterTransition( TRANSIT_SPLIT_SCREEN_PAIR_OPEN, wct, remoteTransition, this, null); + setEnterInstanceId(instanceId); } /** Starts 2 tasks in one legacy transition. */ void startTasksWithLegacyTransition(int mainTaskId, @Nullable Bundle mainOptions, int sideTaskId, @Nullable Bundle sideOptions, @SplitPosition int sidePosition, - float splitRatio, RemoteAnimationAdapter adapter) { + float splitRatio, RemoteAnimationAdapter adapter, + InstanceId instanceId) { final WindowContainerTransaction wct = new WindowContainerTransaction(); if (sideOptions == null) sideOptions = new Bundle(); addActivityOptions(sideOptions, mSideStage); wct.startTask(sideTaskId, sideOptions); - startWithLegacyTransition(wct, mainTaskId, mainOptions, sidePosition, splitRatio, adapter); + startWithLegacyTransition(wct, mainTaskId, mainOptions, sidePosition, splitRatio, adapter, + instanceId); } /** Start an intent and a task ordered by {@code intentFirst}. */ void startIntentAndTaskWithLegacyTransition(PendingIntent pendingIntent, Intent fillInIntent, int taskId, @Nullable Bundle mainOptions, @Nullable Bundle sideOptions, - @SplitPosition int sidePosition, float splitRatio, RemoteAnimationAdapter adapter) { + @SplitPosition int sidePosition, float splitRatio, RemoteAnimationAdapter adapter, + InstanceId instanceId) { final WindowContainerTransaction wct = new WindowContainerTransaction(); if (sideOptions == null) sideOptions = new Bundle(); addActivityOptions(sideOptions, mSideStage); wct.sendPendingIntent(pendingIntent, fillInIntent, sideOptions); - startWithLegacyTransition(wct, taskId, mainOptions, sidePosition, splitRatio, adapter); + startWithLegacyTransition(wct, taskId, mainOptions, sidePosition, splitRatio, adapter, + instanceId); } void startShortcutAndTaskWithLegacyTransition(ShortcutInfo shortcutInfo, int taskId, @Nullable Bundle mainOptions, @Nullable Bundle sideOptions, - @SplitPosition int sidePosition, float splitRatio, RemoteAnimationAdapter adapter) { + @SplitPosition int sidePosition, float splitRatio, RemoteAnimationAdapter adapter, + InstanceId instanceId) { final WindowContainerTransaction wct = new WindowContainerTransaction(); if (sideOptions == null) sideOptions = new Bundle(); addActivityOptions(sideOptions, mSideStage); wct.startShortcut(mContext.getPackageName(), shortcutInfo, sideOptions); - startWithLegacyTransition(wct, taskId, mainOptions, sidePosition, splitRatio, adapter); + startWithLegacyTransition(wct, taskId, mainOptions, sidePosition, splitRatio, adapter, + instanceId); } - private void startWithLegacyTransition(WindowContainerTransaction sideWct, int mainTaskId, + /** + * @param instanceId if {@code null}, will not log. Otherwise it will be used in + * {@link SplitscreenEventLogger#logEnter(float, int, int, int, int, boolean)} + */ + private void startWithLegacyTransition(WindowContainerTransaction wct, int mainTaskId, @Nullable Bundle mainOptions, @SplitPosition int sidePosition, float splitRatio, - RemoteAnimationAdapter adapter) { + RemoteAnimationAdapter adapter, InstanceId instanceId) { // Init divider first to make divider leash for remote animation target. mSplitLayout.init(); mSplitLayout.setDivideRatio(splitRatio); @@ -572,59 +598,56 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, mShouldUpdateRecents = false; mIsDividerRemoteAnimating = true; - LegacyTransitions.ILegacyTransition transition = new LegacyTransitions.ILegacyTransition() { - @Override - public void onAnimationStart(int transit, RemoteAnimationTarget[] apps, - RemoteAnimationTarget[] wallpapers, RemoteAnimationTarget[] nonApps, - IRemoteAnimationFinishedCallback finishedCallback, - SurfaceControl.Transaction t) { - if (apps == null || apps.length == 0) { - updateSurfaceBounds(mSplitLayout, t, false /* applyResizingOffset */); - setDividerVisibility(true, t); - t.apply(); - onRemoteAnimationFinished(apps); - try { - adapter.getRunner().onAnimationCancelled(mKeyguardShowing); - } catch (RemoteException e) { - Slog.e(TAG, "Error starting remote animation", e); - } - return; - } - - // Wrap the divider bar into non-apps target to animate together. - nonApps = ArrayUtils.appendElement(RemoteAnimationTarget.class, nonApps, - getDividerBarLegacyTarget()); - - updateSurfaceBounds(mSplitLayout, t, false /* applyResizingOffset */); - setDividerVisibility(true, t); - for (int i = 0; i < apps.length; ++i) { - if (apps[i].mode == MODE_OPENING) { - t.show(apps[i].leash); - // Reset the surface position of the opening app to prevent double-offset. - t.setPosition(apps[i].leash, 0, 0); - } - } - t.apply(); + final WindowContainerTransaction evictWct = new WindowContainerTransaction(); + prepareEvictChildTasks(SPLIT_POSITION_TOP_OR_LEFT, evictWct); + prepareEvictChildTasks(SPLIT_POSITION_BOTTOM_OR_RIGHT, evictWct); + IRemoteAnimationRunner wrapper = new IRemoteAnimationRunner.Stub() { + @Override + public void onAnimationStart(@WindowManager.TransitionOldType int transit, + RemoteAnimationTarget[] apps, + RemoteAnimationTarget[] wallpapers, + RemoteAnimationTarget[] nonApps, + final IRemoteAnimationFinishedCallback finishedCallback) { IRemoteAnimationFinishedCallback wrapCallback = new IRemoteAnimationFinishedCallback.Stub() { @Override public void onAnimationFinished() throws RemoteException { - onRemoteAnimationFinished(apps); + onRemoteAnimationFinishedOrCancelled(false /* cancel */, evictWct); finishedCallback.onAnimationFinished(); } }; Transitions.setRunningRemoteTransitionDelegate(adapter.getCallingApplication()); try { - adapter.getRunner().onAnimationStart( - transit, apps, wallpapers, nonApps, wrapCallback); + adapter.getRunner().onAnimationStart(transit, apps, wallpapers, + ArrayUtils.appendElement(RemoteAnimationTarget.class, nonApps, + getDividerBarLegacyTarget()), wrapCallback); + } catch (RemoteException e) { + Slog.e(TAG, "Error starting remote animation", e); + } + } + + @Override + public void onAnimationCancelled(boolean isKeyguardOccluded) { + onRemoteAnimationFinishedOrCancelled(true /* cancel */, evictWct); + try { + adapter.getRunner().onAnimationCancelled(isKeyguardOccluded); } catch (RemoteException e) { Slog.e(TAG, "Error starting remote animation", e); } } }; + RemoteAnimationAdapter wrappedAdapter = new RemoteAnimationAdapter( + wrapper, adapter.getDuration(), adapter.getStatusBarTransitionDelay()); + + if (mainOptions == null) { + mainOptions = ActivityOptions.makeRemoteAnimation(wrappedAdapter).toBundle(); + } else { + ActivityOptions mainActivityOptions = ActivityOptions.fromBundle(mainOptions); + mainActivityOptions.update(ActivityOptions.makeRemoteAnimation(wrappedAdapter)); + mainOptions = mainActivityOptions.toBundle(); + } - final WindowContainerTransaction wct = new WindowContainerTransaction(); setSideStagePosition(sidePosition, wct); if (!mMainStage.isActive()) { mMainStage.activate(wct, false /* reparent */); @@ -632,34 +655,40 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, if (mainOptions == null) mainOptions = new Bundle(); addActivityOptions(mainOptions, mMainStage); - wct.startTask(mainTaskId, mainOptions); - wct.merge(sideWct, true); - updateWindowBounds(mSplitLayout, wct); + wct.startTask(mainTaskId, mainOptions); wct.reorder(mRootTaskInfo.token, true); wct.setForceTranslucent(mRootTaskInfo.token, false); - mSyncQueue.queue(transition, WindowManager.TRANSIT_OPEN, wct); + mSyncQueue.queue(wct); + mSyncQueue.runInSync(t -> { + setDividerVisibility(true, t); + updateSurfaceBounds(mSplitLayout, t, false /* applyResizingOffset */); + }); + + setEnterInstanceId(instanceId); + } + + private void setEnterInstanceId(InstanceId instanceId) { + if (instanceId != null) { + mLogger.enterRequested(instanceId); + } } - private void onRemoteAnimationFinished(RemoteAnimationTarget[] apps) { + private void onRemoteAnimationFinishedOrCancelled(boolean cancel, + WindowContainerTransaction evictWct) { mIsDividerRemoteAnimating = false; mShouldUpdateRecents = true; - if (apps == null || apps.length == 0) return; - - // If any stage has no child after finished animation, that side of the split will display - // nothing. This might happen if starting the same app on the both sides while not - // supporting multi-instance. Exit the split screen and expand that app to full screen. - if (mMainStage.getChildCount() == 0 || mSideStage.getChildCount() == 0) { - mMainExecutor.execute(() -> exitSplitScreen(mMainStage.getChildCount() == 0 - ? mSideStage : mMainStage, EXIT_REASON_UNKNOWN)); - return; + // If any stage has no child after animation finished, it means that split will display + // nothing, such status will happen if task and intent is same app but not support + // multi-instance, we should exit split and expand that app as full screen. + if (!cancel && (mMainStage.getChildCount() == 0 || mSideStage.getChildCount() == 0)) { + mMainExecutor.execute(() -> + exitSplitScreen(mMainStage.getChildCount() == 0 + ? mSideStage : mMainStage, EXIT_REASON_UNKNOWN)); + } else { + mSyncQueue.queue(evictWct); } - - final WindowContainerTransaction evictWct = new WindowContainerTransaction(); - prepareEvictNonOpeningChildTasks(SPLIT_POSITION_TOP_OR_LEFT, apps, evictWct); - prepareEvictNonOpeningChildTasks(SPLIT_POSITION_BOTTOM_OR_RIGHT, apps, evictWct); - mSyncQueue.queue(evictWct); } /** @@ -880,6 +909,8 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, WindowContainerTransaction wct, @ExitReason int exitReason) { if (!mMainStage.isActive() || mIsExiting) return; + onSplitScreenExit(); + mRecentTasks.ifPresent(recentTasks -> { // Notify recents if we are exiting in a way that breaks the pair, and disable further // updates to splits in the recents until we enter split again @@ -903,13 +934,10 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, // Expand to top side split as full screen for fading out decor animation and dismiss // another side split(Moving its children to bottom). mIsExiting = true; - final StageTaskListener tempFullStage = childrenToTop; - final StageTaskListener dismissStage = mMainStage == childrenToTop - ? mSideStage : mMainStage; - tempFullStage.resetBounds(wct); - wct.setSmallestScreenWidthDp(tempFullStage.mRootTaskInfo.token, + childrenToTop.resetBounds(wct); + wct.reorder(childrenToTop.mRootTaskInfo.token, true); + wct.setSmallestScreenWidthDp(childrenToTop.mRootTaskInfo.token, SMALLEST_SCREEN_WIDTH_DP_UNDEFINED); - dismissStage.dismiss(wct, false /* toTop */); } mSyncQueue.queue(wct); mSyncQueue.runInSync(t -> { @@ -926,7 +954,8 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, childrenToTop.fadeOutDecor(() -> { WindowContainerTransaction finishedWCT = new WindowContainerTransaction(); mIsExiting = false; - childrenToTop.dismiss(finishedWCT, true /* toTop */); + mMainStage.deactivate(finishedWCT, childrenToTop == mMainStage /* toTop */); + mSideStage.removeAllTasks(finishedWCT, childrenToTop == mSideStage /* toTop */); finishedWCT.reorder(mRootTaskInfo.token, false /* toTop */); finishedWCT.setForceTranslucent(mRootTaskInfo.token, true); finishedWCT.setBounds(mSideStage.mRootTaskInfo.token, mTempRect1); @@ -949,6 +978,47 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, } /** + * Overridden by child classes. + */ + protected void onSplitScreenEnter() { + } + + /** + * Overridden by child classes. + */ + protected void onSplitScreenExit() { + } + + /** + * Exits the split screen by finishing one of the tasks. + */ + protected void exitStage(@SplitPosition int stageToClose) { + if (ENABLE_SHELL_TRANSITIONS) { + StageTaskListener stageToTop = mSideStagePosition == stageToClose + ? mMainStage + : mSideStage; + exitSplitScreen(stageToTop, EXIT_REASON_APP_FINISHED); + } else { + boolean toEnd = stageToClose == SPLIT_POSITION_BOTTOM_OR_RIGHT; + mSplitLayout.flingDividerToDismiss(toEnd, EXIT_REASON_APP_FINISHED); + } + } + + /** + * Grants focus to the main or the side stages. + */ + protected void grantFocusToStage(@SplitPosition int stageToFocus) { + IActivityTaskManager activityTaskManagerService = IActivityTaskManager.Stub.asInterface( + ServiceManager.getService(Context.ACTIVITY_TASK_SERVICE)); + try { + activityTaskManagerService.setFocusedTask(getTaskId(stageToFocus)); + } catch (RemoteException | NullPointerException e) { + ProtoLog.e(ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN, + "%s: Unable to update focus on the chosen stage, %s", TAG, e); + } + } + + /** * Returns whether the split pair in the recent tasks list should be broken. */ private boolean shouldBreakPairedTaskInRecents(@ExitReason int exitReason) { @@ -995,6 +1065,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, @Nullable ActivityManager.RunningTaskInfo taskInfo, @SplitPosition int startPosition) { if (mMainStage.isActive()) return; + onSplitScreenEnter(); if (taskInfo != null) { setSideStagePosition(startPosition, wct); mSideStage.addTask(taskInfo, wct); @@ -1388,6 +1459,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, } } else if (isSideStage && hasChildren && !mMainStage.isActive()) { // TODO (b/238697912) : Add the validation to prevent entering non-recovered status + onSplitScreenEnter(); final WindowContainerTransaction wct = new WindowContainerTransaction(); mSplitLayout.init(); mSplitLayout.setDividerAtBorder(mSideStagePosition == SPLIT_POSITION_TOP_OR_LEFT); @@ -1812,8 +1884,25 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, // Use normal animations. return false; + } else if (mMixedHandler != null && hasDisplayChange(info)) { + // A display-change has been un-expectedly inserted into the transition. Redirect + // handling to the mixed-handler to deal with splitting it up. + if (mMixedHandler.animatePendingSplitWithDisplayChange(transition, info, + startTransaction, finishTransaction, finishCallback)) { + return true; + } } + return startPendingAnimation(transition, info, startTransaction, finishTransaction, + finishCallback); + } + + /** Starts the pending transition animation. */ + public boolean startPendingAnimation(@NonNull IBinder transition, + @NonNull TransitionInfo info, + @NonNull SurfaceControl.Transaction startTransaction, + @NonNull SurfaceControl.Transaction finishTransaction, + @NonNull Transitions.TransitionFinishCallback finishCallback) { boolean shouldAnimate = true; if (mSplitTransitions.isPendingEnter(transition)) { shouldAnimate = startPendingEnterAnimation( @@ -1832,6 +1921,15 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, return true; } + private boolean hasDisplayChange(TransitionInfo info) { + boolean has = false; + for (int iC = 0; iC < info.getChanges().size() && !has; ++iC) { + final TransitionInfo.Change change = info.getChanges().get(iC); + has = change.getMode() == TRANSIT_CHANGE && (change.getFlags() & FLAG_IS_DISPLAY) != 0; + } + return has; + } + /** Called to clean-up state and do house-keeping after the animation is done. */ public void onTransitionAnimationComplete() { // If still playing, let it finish. @@ -1840,7 +1938,6 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, // properly for the animation itself. mSplitLayout.release(); mSplitLayout.resetDividerPosition(); - mSideStagePosition = SPLIT_POSITION_BOTTOM_OR_RIGHT; mTopStageAfterFoldDismiss = STAGE_TYPE_UNDEFINED; } } 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 1af9415fca3a..6b90eabe3bd2 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 @@ -106,11 +106,6 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener { taskOrganizer.createRootTask(displayId, WINDOWING_MODE_MULTI_WINDOW, this); } - /** - * General function for dismiss this stage. - */ - void dismiss(WindowContainerTransaction wct, boolean toTop) {} - int getChildCount() { return mChildrenTaskInfo.size(); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java index e26c259b2397..3cba92956f95 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java @@ -17,6 +17,7 @@ package com.android.wm.shell.transition; import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; +import static android.view.WindowManager.TRANSIT_CHANGE; import static android.view.WindowManager.TRANSIT_TO_BACK; import static android.window.TransitionInfo.FLAG_IS_WALLPAPER; @@ -35,10 +36,14 @@ import android.window.WindowContainerTransaction; import com.android.internal.protolog.common.ProtoLog; import com.android.wm.shell.pip.PipTransitionController; +import com.android.wm.shell.pip.phone.PipTouchHandler; import com.android.wm.shell.protolog.ShellProtoLogGroup; +import com.android.wm.shell.splitscreen.SplitScreenController; import com.android.wm.shell.splitscreen.StageCoordinator; +import com.android.wm.shell.sysui.ShellInit; import java.util.ArrayList; +import java.util.Optional; /** * A handler for dealing with transitions involving multiple other handlers. For example: an @@ -47,12 +52,15 @@ import java.util.ArrayList; public class DefaultMixedHandler implements Transitions.TransitionHandler { private final Transitions mPlayer; - private final PipTransitionController mPipHandler; - private final StageCoordinator mSplitHandler; + private PipTransitionController mPipHandler; + private StageCoordinator mSplitHandler; private static class MixedTransition { static final int TYPE_ENTER_PIP_FROM_SPLIT = 1; + /** Both the display and split-state (enter/exit) is changing */ + static final int TYPE_DISPLAY_AND_SPLIT_CHANGE = 2; + /** The default animation for this mixed transition. */ static final int ANIM_TYPE_DEFAULT = 0; @@ -65,6 +73,7 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler { Transitions.TransitionFinishCallback mFinishCallback = null; Transitions.TransitionHandler mLeftoversHandler = null; + WindowContainerTransaction mFinishWCT = null; /** * Mixed transitions are made up of multiple "parts". This keeps track of how many @@ -77,13 +86,25 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler { mTransition = transition; } } + private final ArrayList<MixedTransition> mActiveTransitions = new ArrayList<>(); - public DefaultMixedHandler(@NonNull Transitions player, - @NonNull PipTransitionController pipHandler, @NonNull StageCoordinator splitHandler) { + public DefaultMixedHandler(@NonNull ShellInit shellInit, @NonNull Transitions player, + Optional<SplitScreenController> splitScreenControllerOptional, + Optional<PipTouchHandler> pipTouchHandlerOptional) { mPlayer = player; - mPipHandler = pipHandler; - mSplitHandler = splitHandler; + if (Transitions.ENABLE_SHELL_TRANSITIONS && pipTouchHandlerOptional.isPresent() + && splitScreenControllerOptional.isPresent()) { + // Add after dependencies because it is higher priority + shellInit.addInitCallback(() -> { + mPipHandler = pipTouchHandlerOptional.get().getTransitionHandler(); + mSplitHandler = splitScreenControllerOptional.get().getTransitionHandler(); + mPlayer.addHandler(this); + if (mSplitHandler != null) { + mSplitHandler.setMixedHandler(this); + } + }, this); + } } @Nullable @@ -109,10 +130,12 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler { } private TransitionInfo subCopy(@NonNull TransitionInfo info, - @WindowManager.TransitionType int newType) { - final TransitionInfo out = new TransitionInfo(newType, info.getFlags()); - for (int i = 0; i < info.getChanges().size(); ++i) { - out.getChanges().add(info.getChanges().get(i)); + @WindowManager.TransitionType int newType, boolean withChanges) { + final TransitionInfo out = new TransitionInfo(newType, withChanges ? info.getFlags() : 0); + if (withChanges) { + for (int i = 0; i < info.getChanges().size(); ++i) { + out.getChanges().add(info.getChanges().get(i)); + } } out.setRootLeash(info.getRootLeash(), info.getRootOffset().x, info.getRootOffset().y); out.setAnimationOptions(info.getAnimationOptions()); @@ -144,6 +167,8 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler { if (mixed.mType == MixedTransition.TYPE_ENTER_PIP_FROM_SPLIT) { return animateEnterPipFromSplit(mixed, info, startTransaction, finishTransaction, finishCallback); + } else if (mixed.mType == MixedTransition.TYPE_DISPLAY_AND_SPLIT_CHANGE) { + return false; } else { mActiveTransitions.remove(mixed); throw new IllegalStateException("Starting mixed animation without a known mixed type? " @@ -160,7 +185,7 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler { + "entering PIP while Split-Screen is active."); TransitionInfo.Change pipChange = null; TransitionInfo.Change wallpaper = null; - final TransitionInfo everythingElse = subCopy(info, TRANSIT_TO_BACK); + final TransitionInfo everythingElse = subCopy(info, TRANSIT_TO_BACK, true /* changes */); boolean homeIsOpening = false; for (int i = info.getChanges().size() - 1; i >= 0; --i) { TransitionInfo.Change change = info.getChanges().get(i); @@ -241,6 +266,87 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler { return true; } + private void unlinkMissingParents(TransitionInfo from) { + for (int i = 0; i < from.getChanges().size(); ++i) { + final TransitionInfo.Change chg = from.getChanges().get(i); + if (chg.getParent() == null) continue; + if (from.getChange(chg.getParent()) == null) { + from.getChanges().get(i).setParent(null); + } + } + } + + private boolean isWithinTask(TransitionInfo info, TransitionInfo.Change chg) { + TransitionInfo.Change curr = chg; + while (curr != null) { + if (curr.getTaskInfo() != null) return true; + if (curr.getParent() == null) break; + curr = info.getChange(curr.getParent()); + } + return false; + } + + /** + * This is intended to be called by SplitCoordinator as a helper to mix an already-pending + * split transition with a display-change. The use-case for this is when a display + * change/rotation gets collected into a split-screen enter/exit transition which has already + * been claimed by StageCoordinator.handleRequest . This happens during launcher tests. + */ + public boolean animatePendingSplitWithDisplayChange(@NonNull IBinder transition, + @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction startT, + @NonNull SurfaceControl.Transaction finishT, + @NonNull Transitions.TransitionFinishCallback finishCallback) { + final TransitionInfo everythingElse = subCopy(info, info.getType(), true /* withChanges */); + final TransitionInfo displayPart = subCopy(info, TRANSIT_CHANGE, false /* withChanges */); + for (int i = info.getChanges().size() - 1; i >= 0; --i) { + TransitionInfo.Change change = info.getChanges().get(i); + if (isWithinTask(info, change)) continue; + displayPart.addChange(change); + everythingElse.getChanges().remove(i); + } + if (displayPart.getChanges().isEmpty()) return false; + unlinkMissingParents(everythingElse); + final MixedTransition mixed = new MixedTransition( + MixedTransition.TYPE_DISPLAY_AND_SPLIT_CHANGE, transition); + mixed.mFinishCallback = finishCallback; + mActiveTransitions.add(mixed); + ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, " Animation is a mix of display change " + + "and split change."); + // We need to split the transition into 2 parts: the split part and the display part. + mixed.mInFlightSubAnimations = 2; + + Transitions.TransitionFinishCallback finishCB = (wct, wctCB) -> { + --mixed.mInFlightSubAnimations; + if (wctCB != null) { + throw new IllegalArgumentException("Can't mix transitions that require finish" + + " sync callback"); + } + if (wct != null) { + if (mixed.mFinishWCT == null) { + mixed.mFinishWCT = wct; + } else { + mixed.mFinishWCT.merge(wct, true /* transfer */); + } + } + if (mixed.mInFlightSubAnimations > 0) return; + mActiveTransitions.remove(mixed); + mixed.mFinishCallback.onTransitionFinished(mixed.mFinishWCT, null /* wctCB */); + }; + + // Dispatch the display change. This will most-likely be taken by the default handler. + // Do this first since the first handler used will apply the startT; the display change + // needs to take a screenshot before that happens so we need it to be the first handler. + mixed.mLeftoversHandler = mPlayer.dispatchTransition(mixed.mTransition, displayPart, + startT, finishT, finishCB, mSplitHandler); + + // Note: at this point, startT has probably already been applied, so we are basically + // giving splitHandler an empty startT. This is currently OK because display-change will + // grab a screenshot and paste it on top anyways. + mSplitHandler.startPendingAnimation( + transition, everythingElse, startT, finishT, finishCB); + return true; + } + @Override public void mergeAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info, @NonNull SurfaceControl.Transaction t, @NonNull IBinder mergeTarget, @@ -266,6 +372,8 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler { } else { mPipHandler.end(); } + } else if (mixed.mType == MixedTransition.TYPE_DISPLAY_AND_SPLIT_CHANGE) { + // queue } else { throw new IllegalStateException("Playing a mixed transition with unknown type? " + mixed.mType); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java index cff60f5e5b6c..4c927b6e84b8 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java @@ -554,6 +554,12 @@ public class DefaultTransitionHandler implements Transitions.TransitionHandler { private void edgeExtendWindow(TransitionInfo.Change change, Animation a, SurfaceControl.Transaction startTransaction, SurfaceControl.Transaction finishTransaction) { + // Do not create edge extension surface for transfer starting window change. + // The app surface could be empty thus nothing can draw on the hardware renderer, which will + // block this thread when calling Surface#unlockCanvasAndPost. + if ((change.getFlags() & FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT) != 0) { + return; + } final Transformation transformationAtStart = new Transformation(); a.getTransformationAt(0, transformationAtStart); final Transformation transformationAtEnd = new Transformation(); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/SplitscreenPipMixedHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/SplitscreenPipMixedHandler.java deleted file mode 100644 index 678e91fd8829..000000000000 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/SplitscreenPipMixedHandler.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.wm.shell.transition; - -import com.android.wm.shell.pip.phone.PipTouchHandler; -import com.android.wm.shell.splitscreen.SplitScreenController; -import com.android.wm.shell.sysui.ShellInit; - -import java.util.Optional; - -/** - * Handles transitions between the Splitscreen and PIP components. - */ -public class SplitscreenPipMixedHandler { - - private final Optional<SplitScreenController> mSplitScreenOptional; - private final Optional<PipTouchHandler> mPipTouchHandlerOptional; - private final Transitions mTransitions; - - public SplitscreenPipMixedHandler(ShellInit shellInit, - Optional<SplitScreenController> splitScreenControllerOptional, - Optional<PipTouchHandler> pipTouchHandlerOptional, - Transitions transitions) { - mSplitScreenOptional = splitScreenControllerOptional; - mPipTouchHandlerOptional = pipTouchHandlerOptional; - mTransitions = transitions; - if (Transitions.ENABLE_SHELL_TRANSITIONS - && mSplitScreenOptional.isPresent() && mPipTouchHandlerOptional.isPresent()) { - shellInit.addInitCallback(this::onInit, this); - } - } - - private void onInit() { - // Special handling for initializing based on multiple components - final DefaultMixedHandler mixedHandler = new DefaultMixedHandler(mTransitions, - mPipTouchHandlerOptional.get().getTransitionHandler(), - mSplitScreenOptional.get().getTransitionHandler()); - // Added at end so that it has highest priority. - mTransitions.addHandler(mixedHandler); - } -} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/util/GroupedRecentTaskInfo.java b/libs/WindowManager/Shell/src/com/android/wm/shell/util/GroupedRecentTaskInfo.java index 2cff1714aff6..c045cebdf4e0 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/util/GroupedRecentTaskInfo.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/util/GroupedRecentTaskInfo.java @@ -16,6 +16,7 @@ package com.android.wm.shell.util; +import android.annotation.IntDef; import android.app.ActivityManager; import android.app.WindowConfiguration; import android.os.Parcel; @@ -24,40 +25,143 @@ import android.os.Parcelable; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import java.util.Arrays; +import java.util.List; + /** * Simple container for recent tasks. May contain either a single or pair of tasks. */ public class GroupedRecentTaskInfo implements Parcelable { - public @NonNull ActivityManager.RecentTaskInfo mTaskInfo1; - public @Nullable ActivityManager.RecentTaskInfo mTaskInfo2; - public @Nullable SplitBounds mSplitBounds; - public GroupedRecentTaskInfo(@NonNull ActivityManager.RecentTaskInfo task1) { - this(task1, null, null); + public static final int TYPE_SINGLE = 1; + public static final int TYPE_SPLIT = 2; + public static final int TYPE_FREEFORM = 3; + + @IntDef(prefix = {"TYPE_"}, value = { + TYPE_SINGLE, + TYPE_SPLIT, + TYPE_FREEFORM + }) + public @interface GroupType {} + + @NonNull + private final ActivityManager.RecentTaskInfo[] mTasks; + @Nullable + private final SplitBounds mSplitBounds; + @GroupType + private final int mType; + + /** + * Create new for a single task + */ + public static GroupedRecentTaskInfo forSingleTask( + @NonNull ActivityManager.RecentTaskInfo task) { + return new GroupedRecentTaskInfo(new ActivityManager.RecentTaskInfo[]{task}, null, + TYPE_SINGLE); + } + + /** + * Create new for a pair of tasks in split screen + */ + public static GroupedRecentTaskInfo forSplitTasks(@NonNull ActivityManager.RecentTaskInfo task1, + @NonNull ActivityManager.RecentTaskInfo task2, @Nullable SplitBounds splitBounds) { + return new GroupedRecentTaskInfo(new ActivityManager.RecentTaskInfo[]{task1, task2}, + splitBounds, TYPE_SPLIT); } - public GroupedRecentTaskInfo(@NonNull ActivityManager.RecentTaskInfo task1, - @Nullable ActivityManager.RecentTaskInfo task2, - @Nullable SplitBounds splitBounds) { - mTaskInfo1 = task1; - mTaskInfo2 = task2; + /** + * Create new for a group of freeform tasks + */ + public static GroupedRecentTaskInfo forFreeformTasks( + @NonNull ActivityManager.RecentTaskInfo... tasks) { + return new GroupedRecentTaskInfo(tasks, null, TYPE_FREEFORM); + } + + private GroupedRecentTaskInfo(@NonNull ActivityManager.RecentTaskInfo[] tasks, + @Nullable SplitBounds splitBounds, @GroupType int type) { + mTasks = tasks; mSplitBounds = splitBounds; + mType = type; } GroupedRecentTaskInfo(Parcel parcel) { - mTaskInfo1 = parcel.readTypedObject(ActivityManager.RecentTaskInfo.CREATOR); - mTaskInfo2 = parcel.readTypedObject(ActivityManager.RecentTaskInfo.CREATOR); + mTasks = parcel.createTypedArray(ActivityManager.RecentTaskInfo.CREATOR); mSplitBounds = parcel.readTypedObject(SplitBounds.CREATOR); + mType = parcel.readInt(); + } + + /** + * Get primary {@link ActivityManager.RecentTaskInfo} + */ + @NonNull + public ActivityManager.RecentTaskInfo getTaskInfo1() { + return mTasks[0]; + } + + /** + * Get secondary {@link ActivityManager.RecentTaskInfo}. + * + * Used in split screen. + */ + @Nullable + public ActivityManager.RecentTaskInfo getTaskInfo2() { + if (mTasks.length > 1) { + return mTasks[1]; + } + return null; + } + + /** + * Get all {@link ActivityManager.RecentTaskInfo}s grouped together. + */ + @NonNull + public List<ActivityManager.RecentTaskInfo> getTaskInfoList() { + return Arrays.asList(mTasks); + } + + /** + * Return {@link SplitBounds} if this is a split screen entry or {@code null} + */ + @Nullable + public SplitBounds getSplitBounds() { + return mSplitBounds; + } + + /** + * Get type of this recents entry. One of {@link GroupType} + */ + @GroupType + public int getType() { + return mType; } @Override public String toString() { - String taskString = "Task1: " + getTaskInfo(mTaskInfo1) - + ", Task2: " + getTaskInfo(mTaskInfo2); + StringBuilder taskString = new StringBuilder(); + for (int i = 0; i < mTasks.length; i++) { + if (i == 0) { + taskString.append("Task"); + } else { + taskString.append(", Task"); + } + taskString.append(i + 1).append(": ").append(getTaskInfo(mTasks[i])); + } if (mSplitBounds != null) { - taskString += ", SplitBounds: " + mSplitBounds.toString(); + taskString.append(", SplitBounds: ").append(mSplitBounds); + } + taskString.append(", Type="); + switch (mType) { + case TYPE_SINGLE: + taskString.append("TYPE_SINGLE"); + break; + case TYPE_SPLIT: + taskString.append("TYPE_SPLIT"); + break; + case TYPE_FREEFORM: + taskString.append("TYPE_FREEFORM"); + break; } - return taskString; + return taskString.toString(); } private String getTaskInfo(ActivityManager.RecentTaskInfo taskInfo) { @@ -74,9 +178,9 @@ public class GroupedRecentTaskInfo implements Parcelable { @Override public void writeToParcel(Parcel parcel, int flags) { - parcel.writeTypedObject(mTaskInfo1, flags); - parcel.writeTypedObject(mTaskInfo2, flags); + parcel.writeTypedArray(mTasks, flags); parcel.writeTypedObject(mSplitBounds, flags); + parcel.writeInt(mType); } @Override diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java index 83aa539d24d6..e8a2cb160880 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java @@ -36,6 +36,7 @@ import com.android.wm.shell.R; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.SyncTransactionQueue; +import com.android.wm.shell.desktopmode.DesktopMode; import com.android.wm.shell.freeform.FreeformTaskTransitionStarter; import com.android.wm.shell.transition.Transitions; @@ -80,6 +81,7 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel<Caption SurfaceControl taskSurface, SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT) { + if (!shouldShowWindowDecor(taskInfo)) return null; final CaptionWindowDecoration windowDecoration = new CaptionWindowDecoration( mContext, mDisplayController, @@ -101,9 +103,12 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel<Caption @Override public CaptionWindowDecoration adoptWindowDecoration(AutoCloseable windowDecor) { - return (windowDecor instanceof CaptionWindowDecoration) - ? (CaptionWindowDecoration) windowDecor - : null; + if (!(windowDecor instanceof CaptionWindowDecoration)) return null; + final CaptionWindowDecoration captionWindowDecor = (CaptionWindowDecoration) windowDecor; + if (!shouldShowWindowDecor(captionWindowDecor.mTaskInfo)) { + return null; + } + return captionWindowDecor; } @Override @@ -231,4 +236,11 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel<Caption } } } + + private boolean shouldShowWindowDecor(RunningTaskInfo taskInfo) { + if (taskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM) return true; + return DesktopMode.IS_SUPPORTED + && mDisplayController.getDisplayContext(taskInfo.displayId) + .getResources().getConfiguration().smallestScreenWidthDp >= 600; + } } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecorViewModel.java index c234949572bf..d9697d288ab6 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecorViewModel.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecorViewModel.java @@ -42,6 +42,7 @@ public interface WindowDecorViewModel<T extends AutoCloseable> { /** * Creates a window decoration for the given task. + * Can be {@code null} for Fullscreen tasks but not Freeform ones. * * @param taskInfo the initial task info of the task * @param taskSurface the surface of the task @@ -49,7 +50,7 @@ public interface WindowDecorViewModel<T extends AutoCloseable> { * @param finishT the finish transaction to restore states after the transition * @return the window decoration object */ - T createWindowDecoration( + @Nullable T createWindowDecoration( ActivityManager.RunningTaskInfo taskInfo, SurfaceControl taskSurface, SurfaceControl.Transaction startT, @@ -57,11 +58,12 @@ public interface WindowDecorViewModel<T extends AutoCloseable> { /** * Adopts the window decoration if possible. + * May be {@code null} if a window decor is not needed or the given one is incompatible. * * @param windowDecor the potential window decoration to adopt * @return the window decoration if it can be adopted, or {@code null} otherwise. */ - T adoptWindowDecoration(@Nullable AutoCloseable windowDecor); + @Nullable T adoptWindowDecoration(@Nullable AutoCloseable windowDecor); /** * Notifies a task info update on the given task, with the window decoration created previously diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunnerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunnerTests.java index b2e45a6b3a5c..a7234c1d3cb8 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunnerTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunnerTests.java @@ -17,7 +17,7 @@ package com.android.wm.shell.activityembedding; import static android.view.WindowManager.TRANSIT_OPEN; -import static android.window.TransitionInfo.FLAG_IS_EMBEDDED; +import static android.window.TransitionInfo.FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; @@ -57,7 +57,7 @@ public class ActivityEmbeddingAnimationRunnerTests extends ActivityEmbeddingAnim public void testStartAnimation() { final TransitionInfo info = new TransitionInfo(TRANSIT_OPEN, 0); final TransitionInfo.Change embeddingChange = createChange(); - embeddingChange.setFlags(FLAG_IS_EMBEDDED); + embeddingChange.setFlags(FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY); info.addChange(embeddingChange); doReturn(mAnimator).when(mAnimRunner).createAnimator(any(), any(), any(), any()); diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationTestBase.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationTestBase.java index 84befdddabdb..3792e8361284 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationTestBase.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationTestBase.java @@ -16,6 +16,9 @@ package com.android.wm.shell.activityembedding; +import static android.window.TransitionInfo.FLAG_FILLS_TASK; +import static android.window.TransitionInfo.FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY; + import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; import static org.junit.Assert.assertNotNull; @@ -24,6 +27,8 @@ import static org.mockito.Mockito.mock; import android.animation.Animator; import android.annotation.CallSuper; +import android.annotation.NonNull; +import android.graphics.Rect; import android.os.IBinder; import android.view.SurfaceControl; import android.window.TransitionInfo; @@ -80,4 +85,23 @@ abstract class ActivityEmbeddingAnimationTestBase extends ShellTestCase { return new TransitionInfo.Change(mock(WindowContainerToken.class), mock(SurfaceControl.class)); } + + /** + * Creates a mock {@link TransitionInfo.Change} with + * {@link TransitionInfo#FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY} flag. + */ + static TransitionInfo.Change createEmbeddedChange(@NonNull Rect startBounds, + @NonNull Rect endBounds, @NonNull Rect taskBounds) { + final TransitionInfo.Change change = createChange(); + change.setFlags(FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY); + change.setStartAbsBounds(startBounds); + change.setEndAbsBounds(endBounds); + if (taskBounds.width() == startBounds.width() + && taskBounds.height() == startBounds.height() + && taskBounds.width() == endBounds.width() + && taskBounds.height() == endBounds.height()) { + change.setFlags(FLAG_FILLS_TASK); + } + return change; + } } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/activityembedding/ActivityEmbeddingControllerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/activityembedding/ActivityEmbeddingControllerTests.java index cf43b0030d2a..baecf6fe6673 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/activityembedding/ActivityEmbeddingControllerTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/activityembedding/ActivityEmbeddingControllerTests.java @@ -17,7 +17,6 @@ package com.android.wm.shell.activityembedding; import static android.view.WindowManager.TRANSIT_OPEN; -import static android.window.TransitionInfo.FLAG_IS_EMBEDDED; import static com.android.dx.mockito.inline.extended.ExtendedMockito.never; @@ -29,6 +28,7 @@ import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; +import android.graphics.Rect; import android.window.TransitionInfo; import androidx.test.ext.junit.runners.AndroidJUnit4; @@ -48,6 +48,10 @@ import org.junit.runner.RunWith; @RunWith(AndroidJUnit4.class) public class ActivityEmbeddingControllerTests extends ActivityEmbeddingAnimationTestBase { + private static final Rect TASK_BOUNDS = new Rect(0, 0, 1000, 500); + private static final Rect EMBEDDED_LEFT_BOUNDS = new Rect(0, 0, 500, 500); + private static final Rect EMBEDDED_RIGHT_BOUNDS = new Rect(500, 0, 1000, 500); + @Before public void setup() { super.setUp(); @@ -77,13 +81,13 @@ public class ActivityEmbeddingControllerTests extends ActivityEmbeddingAnimation @Test public void testStartAnimation_containsNonActivityEmbeddingChange() { final TransitionInfo info = new TransitionInfo(TRANSIT_OPEN, 0); - final TransitionInfo.Change embeddingChange = createChange(); - embeddingChange.setFlags(FLAG_IS_EMBEDDED); + final TransitionInfo.Change embeddingChange = createEmbeddedChange(EMBEDDED_LEFT_BOUNDS, + EMBEDDED_LEFT_BOUNDS, TASK_BOUNDS); final TransitionInfo.Change nonEmbeddingChange = createChange(); info.addChange(embeddingChange); info.addChange(nonEmbeddingChange); - // No-op + // No-op because it contains non-embedded change. assertFalse(mController.startAnimation(mTransition, info, mStartTransaction, mFinishTransaction, mFinishCallback)); verify(mAnimRunner, never()).startAnimation(any(), any(), any(), any()); @@ -93,13 +97,65 @@ public class ActivityEmbeddingControllerTests extends ActivityEmbeddingAnimation } @Test - public void testStartAnimation_onlyActivityEmbeddingChange() { + public void testStartAnimation_containsOnlyFillTaskActivityEmbeddingChange() { + final TransitionInfo info = new TransitionInfo(TRANSIT_OPEN, 0); + final TransitionInfo.Change embeddingChange = createEmbeddedChange(TASK_BOUNDS, TASK_BOUNDS, + TASK_BOUNDS); + info.addChange(embeddingChange); + + // No-op because it only contains embedded change that fills the Task. We will let the + // default handler to animate such transition. + assertFalse(mController.startAnimation(mTransition, info, mStartTransaction, + mFinishTransaction, mFinishCallback)); + verify(mAnimRunner, never()).startAnimation(any(), any(), any(), any()); + verifyNoMoreInteractions(mStartTransaction); + verifyNoMoreInteractions(mFinishTransaction); + verifyNoMoreInteractions(mFinishCallback); + } + + @Test + public void testStartAnimation_containsActivityEmbeddingSplitChange() { + // Change that occupies only part of the Task. + final TransitionInfo info = new TransitionInfo(TRANSIT_OPEN, 0); + final TransitionInfo.Change embeddingChange = createEmbeddedChange(EMBEDDED_LEFT_BOUNDS, + EMBEDDED_LEFT_BOUNDS, TASK_BOUNDS); + info.addChange(embeddingChange); + + // ActivityEmbeddingController will handle such transition. + assertTrue(mController.startAnimation(mTransition, info, mStartTransaction, + mFinishTransaction, mFinishCallback)); + verify(mAnimRunner).startAnimation(mTransition, info, mStartTransaction, + mFinishTransaction); + verify(mStartTransaction).apply(); + verifyNoMoreInteractions(mFinishTransaction); + } + + @Test + public void testStartAnimation_containsChangeEnterActivityEmbeddingSplit() { + // Change that is entering ActivityEmbedding split. + final TransitionInfo info = new TransitionInfo(TRANSIT_OPEN, 0); + final TransitionInfo.Change embeddingChange = createEmbeddedChange(TASK_BOUNDS, + EMBEDDED_LEFT_BOUNDS, TASK_BOUNDS); + info.addChange(embeddingChange); + + // ActivityEmbeddingController will handle such transition. + assertTrue(mController.startAnimation(mTransition, info, mStartTransaction, + mFinishTransaction, mFinishCallback)); + verify(mAnimRunner).startAnimation(mTransition, info, mStartTransaction, + mFinishTransaction); + verify(mStartTransaction).apply(); + verifyNoMoreInteractions(mFinishTransaction); + } + + @Test + public void testStartAnimation_containsChangeExitActivityEmbeddingSplit() { + // Change that is exiting ActivityEmbedding split. final TransitionInfo info = new TransitionInfo(TRANSIT_OPEN, 0); - final TransitionInfo.Change embeddingChange = createChange(); - embeddingChange.setFlags(FLAG_IS_EMBEDDED); + final TransitionInfo.Change embeddingChange = createEmbeddedChange(EMBEDDED_RIGHT_BOUNDS, + TASK_BOUNDS, TASK_BOUNDS); info.addChange(embeddingChange); - // No-op + // ActivityEmbeddingController will handle such transition. assertTrue(mController.startAnimation(mTransition, info, mStartTransaction, mFinishTransaction, mFinishCallback)); verify(mAnimRunner).startAnimation(mTransition, info, mStartTransaction, @@ -115,8 +171,8 @@ public class ActivityEmbeddingControllerTests extends ActivityEmbeddingAnimation () -> mController.onAnimationFinished(mTransition)); final TransitionInfo info = new TransitionInfo(TRANSIT_OPEN, 0); - final TransitionInfo.Change embeddingChange = createChange(); - embeddingChange.setFlags(FLAG_IS_EMBEDDED); + final TransitionInfo.Change embeddingChange = createEmbeddedChange(EMBEDDED_LEFT_BOUNDS, + EMBEDDED_LEFT_BOUNDS, TASK_BOUNDS); info.addChange(embeddingChange); mController.startAnimation(mTransition, info, mStartTransaction, mFinishTransaction, mFinishCallback); diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeControllerTest.java index ef532e449bd6..577942505b13 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeControllerTest.java @@ -43,6 +43,7 @@ import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.ShellTestCase; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.sysui.ShellInit; +import com.android.wm.shell.transition.Transitions; import org.junit.Before; import org.junit.Test; @@ -63,6 +64,8 @@ public class DesktopModeControllerTest extends ShellTestCase { private ShellExecutor mTestExecutor; @Mock private Handler mMockHandler; + @Mock + private Transitions mMockTransitions; private DesktopModeController mController; private ShellInit mShellInit; @@ -72,7 +75,7 @@ public class DesktopModeControllerTest extends ShellTestCase { mShellInit = Mockito.spy(new ShellInit(mTestExecutor)); mController = new DesktopModeController(mContext, mShellInit, mShellTaskOrganizer, - mRootDisplayAreaOrganizer, mMockHandler); + mRootDisplayAreaOrganizer, mMockHandler, mMockTransitions); mShellInit.init(); } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java index 1b5091f58f26..a8d3bdcb7c96 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipControllerTest.java @@ -43,6 +43,7 @@ import android.util.Size; import com.android.wm.shell.ShellTestCase; import com.android.wm.shell.WindowManagerShellWrapper; import com.android.wm.shell.common.DisplayController; +import com.android.wm.shell.common.DisplayInsetsController; import com.android.wm.shell.common.DisplayLayout; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.TaskStackListenerImpl; @@ -99,7 +100,8 @@ public class PipControllerTest extends ShellTestCase { @Mock private TaskStackListenerImpl mMockTaskStackListener; @Mock private ShellExecutor mMockExecutor; @Mock private Optional<OneHandedController> mMockOneHandedController; - @Mock private PipParamsChangedForwarder mPipParamsChangedForwarder; + @Mock private PipParamsChangedForwarder mMockPipParamsChangedForwarder; + @Mock private DisplayInsetsController mMockDisplayInsetsController; @Mock private DisplayLayout mMockDisplayLayout1; @Mock private DisplayLayout mMockDisplayLayout2; @@ -120,8 +122,8 @@ public class PipControllerTest extends ShellTestCase { mMockPipBoundsState, mMockPipMotionHelper, mMockPipMediaController, mMockPhonePipMenuController, mMockPipTaskOrganizer, mMockPipTransitionState, mMockPipTouchHandler, mMockPipTransitionController, mMockWindowManagerShellWrapper, - mMockTaskStackListener, mPipParamsChangedForwarder, - mMockOneHandedController, mMockExecutor); + mMockTaskStackListener, mMockPipParamsChangedForwarder, + mMockDisplayInsetsController, mMockOneHandedController, mMockExecutor); mShellInit.init(); when(mMockPipBoundsAlgorithm.getSnapAlgorithm()).thenReturn(mMockPipSnapAlgorithm); when(mMockPipTouchHandler.getMotionHelper()).thenReturn(mMockPipMotionHelper); @@ -186,8 +188,8 @@ public class PipControllerTest extends ShellTestCase { mMockPipBoundsState, mMockPipMotionHelper, mMockPipMediaController, mMockPhonePipMenuController, mMockPipTaskOrganizer, mMockPipTransitionState, mMockPipTouchHandler, mMockPipTransitionController, mMockWindowManagerShellWrapper, - mMockTaskStackListener, mPipParamsChangedForwarder, - mMockOneHandedController, mMockExecutor)); + mMockTaskStackListener, mMockPipParamsChangedForwarder, + mMockDisplayInsetsController, mMockOneHandedController, mMockExecutor)); } @Test diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipDoubleTapHelperTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipDoubleTapHelperTest.java new file mode 100644 index 000000000000..8ce3ca4bdc00 --- /dev/null +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/phone/PipDoubleTapHelperTest.java @@ -0,0 +1,172 @@ +/* + * 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.wm.shell.pip.phone; + +import static com.android.wm.shell.pip.phone.PipDoubleTapHelper.SIZE_SPEC_CUSTOM; +import static com.android.wm.shell.pip.phone.PipDoubleTapHelper.SIZE_SPEC_DEFAULT; +import static com.android.wm.shell.pip.phone.PipDoubleTapHelper.SIZE_SPEC_MAX; +import static com.android.wm.shell.pip.phone.PipDoubleTapHelper.nextSizeSpec; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import android.graphics.Point; +import android.graphics.Rect; +import android.testing.AndroidTestingRunner; + +import com.android.wm.shell.ShellTestCase; +import com.android.wm.shell.pip.PipBoundsState; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; + +/** + * Unit test against {@link PipDoubleTapHelper}. + */ +@RunWith(AndroidTestingRunner.class) +public class PipDoubleTapHelperTest extends ShellTestCase { + // represents the current pip window state and has information on current + // max, min, and normal sizes + @Mock private PipBoundsState mBoundStateMock; + // tied to boundsStateMock.getBounds() in setUp() + @Mock private Rect mBoundsMock; + + // represents the most recent manually resized bounds + // i.e. dimensions from the most recent pinch in/out + @Mock private Rect mUserResizeBoundsMock; + + // actual dimensions of the pip screen bounds + private static final int MAX_WIDTH = 100; + private static final int DEFAULT_WIDTH = 40; + private static final int MIN_WIDTH = 10; + + private static final int AVERAGE_WIDTH = (MAX_WIDTH + MIN_WIDTH) / 2; + + /** + * Initializes mocks and assigns values for different pip screen bounds. + */ + @Before + public void setUp() { + // define pip bounds + when(mBoundStateMock.getMaxSize()).thenReturn(new Point(MAX_WIDTH, 20)); + when(mBoundStateMock.getMinSize()).thenReturn(new Point(MIN_WIDTH, 2)); + + Rect rectMock = mock(Rect.class); + when(rectMock.width()).thenReturn(DEFAULT_WIDTH); + when(mBoundStateMock.getNormalBounds()).thenReturn(rectMock); + + when(mBoundsMock.width()).thenReturn(DEFAULT_WIDTH); + when(mBoundStateMock.getBounds()).thenReturn(mBoundsMock); + } + + /** + * Tests {@link PipDoubleTapHelper#nextSizeSpec(PipBoundsState, Rect)}. + * + * <p>when the user resizes the screen to a larger than the average but not the maximum width, + * then we toggle between {@code PipSizeSpec.CUSTOM} and {@code PipSizeSpec.DEFAULT} + */ + @Test + public void testNextScreenSize_resizedWiderThanAverage_returnDefaultThenCustom() { + // make the user resize width in between MAX and average + when(mUserResizeBoundsMock.width()).thenReturn((MAX_WIDTH + AVERAGE_WIDTH) / 2); + // make current bounds same as resized bound since no double tap yet + when(mBoundsMock.width()).thenReturn((MAX_WIDTH + AVERAGE_WIDTH) / 2); + + // then nextScreenSize() i.e. double tapping should + // toggle to DEFAULT state + Assert.assertSame(nextSizeSpec(mBoundStateMock, mUserResizeBoundsMock), + SIZE_SPEC_DEFAULT); + + // once we toggle to DEFAULT our screen size gets updated + // but not the user resize bounds + when(mBoundsMock.width()).thenReturn(DEFAULT_WIDTH); + + // then nextScreenSize() i.e. double tapping should + // toggle to CUSTOM state + Assert.assertSame(nextSizeSpec(mBoundStateMock, mUserResizeBoundsMock), + SIZE_SPEC_CUSTOM); + } + + /** + * Tests {@link PipDoubleTapHelper#nextSizeSpec(PipBoundsState, Rect)}. + * + * <p>when the user resizes the screen to a smaller than the average but not the default width, + * then we toggle between {@code PipSizeSpec.CUSTOM} and {@code PipSizeSpec.MAX} + */ + @Test + public void testNextScreenSize_resizedNarrowerThanAverage_returnMaxThenCustom() { + // make the user resize width in between MIN and average + when(mUserResizeBoundsMock.width()).thenReturn((MIN_WIDTH + AVERAGE_WIDTH) / 2); + // make current bounds same as resized bound since no double tap yet + when(mBoundsMock.width()).thenReturn((MIN_WIDTH + AVERAGE_WIDTH) / 2); + + // then nextScreenSize() i.e. double tapping should + // toggle to MAX state + Assert.assertSame(nextSizeSpec(mBoundStateMock, mUserResizeBoundsMock), + SIZE_SPEC_MAX); + + // once we toggle to MAX our screen size gets updated + // but not the user resize bounds + when(mBoundsMock.width()).thenReturn(MAX_WIDTH); + + // then nextScreenSize() i.e. double tapping should + // toggle to CUSTOM state + Assert.assertSame(nextSizeSpec(mBoundStateMock, mUserResizeBoundsMock), + SIZE_SPEC_CUSTOM); + } + + /** + * Tests {@link PipDoubleTapHelper#nextSizeSpec(PipBoundsState, Rect)}. + * + * <p>when the user resizes the screen to exactly the maximum width + * then we toggle to {@code PipSizeSpec.DEFAULT} + */ + @Test + public void testNextScreenSize_resizedToMax_returnDefault() { + // the resized width is the same as MAX_WIDTH + when(mUserResizeBoundsMock.width()).thenReturn(MAX_WIDTH); + // the current bounds are also at MAX_WIDTH + when(mBoundsMock.width()).thenReturn(MAX_WIDTH); + + // then nextScreenSize() i.e. double tapping should + // toggle to DEFAULT state + Assert.assertSame(nextSizeSpec(mBoundStateMock, mUserResizeBoundsMock), + SIZE_SPEC_DEFAULT); + } + + /** + * Tests {@link PipDoubleTapHelper#nextSizeSpec(PipBoundsState, Rect)}. + * + * <p>when the user resizes the screen to exactly the default width + * then we toggle to {@code PipSizeSpec.MAX} + */ + @Test + public void testNextScreenSize_resizedToDefault_returnMax() { + // the resized width is the same as DEFAULT_WIDTH + when(mUserResizeBoundsMock.width()).thenReturn(DEFAULT_WIDTH); + // the current bounds are also at DEFAULT_WIDTH + when(mBoundsMock.width()).thenReturn(DEFAULT_WIDTH); + + // then nextScreenSize() i.e. double tapping should + // toggle to MAX state + Assert.assertSame(nextSizeSpec(mBoundStateMock, mUserResizeBoundsMock), + SIZE_SPEC_MAX); + } +} diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/GroupedRecentTaskInfoTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/GroupedRecentTaskInfoTest.kt new file mode 100644 index 000000000000..baa06f2f0c45 --- /dev/null +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/GroupedRecentTaskInfoTest.kt @@ -0,0 +1,169 @@ +/* + * 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.wm.shell.recents + +import android.app.ActivityManager +import android.graphics.Rect +import android.os.Parcel +import android.testing.AndroidTestingRunner +import android.window.IWindowContainerToken +import android.window.WindowContainerToken +import androidx.test.filters.SmallTest +import com.android.wm.shell.ShellTestCase +import com.android.wm.shell.util.GroupedRecentTaskInfo +import com.android.wm.shell.util.GroupedRecentTaskInfo.CREATOR +import com.android.wm.shell.util.GroupedRecentTaskInfo.TYPE_FREEFORM +import com.android.wm.shell.util.GroupedRecentTaskInfo.TYPE_SINGLE +import com.android.wm.shell.util.GroupedRecentTaskInfo.TYPE_SPLIT +import com.android.wm.shell.util.SplitBounds +import com.google.common.truth.Correspondence +import com.google.common.truth.Truth.assertThat +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mockito.mock + +/** + * Tests for [GroupedRecentTaskInfo] + */ +@SmallTest +@RunWith(AndroidTestingRunner::class) +class GroupedRecentTaskInfoTest : ShellTestCase() { + + @Test + fun testSingleTask_hasCorrectType() { + assertThat(singleTaskGroupInfo().type).isEqualTo(TYPE_SINGLE) + } + + @Test + fun testSingleTask_task1Set_task2Null() { + val group = singleTaskGroupInfo() + assertThat(group.taskInfo1.taskId).isEqualTo(1) + assertThat(group.taskInfo2).isNull() + } + + @Test + fun testSingleTask_taskInfoList_hasOneTask() { + val list = singleTaskGroupInfo().taskInfoList + assertThat(list).hasSize(1) + assertThat(list[0].taskId).isEqualTo(1) + } + + @Test + fun testSplitTasks_hasCorrectType() { + assertThat(splitTasksGroupInfo().type).isEqualTo(TYPE_SPLIT) + } + + @Test + fun testSplitTasks_task1Set_task2Set_boundsSet() { + val group = splitTasksGroupInfo() + assertThat(group.taskInfo1.taskId).isEqualTo(1) + assertThat(group.taskInfo2?.taskId).isEqualTo(2) + assertThat(group.splitBounds).isNotNull() + } + + @Test + fun testSplitTasks_taskInfoList_hasTwoTasks() { + val list = splitTasksGroupInfo().taskInfoList + assertThat(list).hasSize(2) + assertThat(list[0].taskId).isEqualTo(1) + assertThat(list[1].taskId).isEqualTo(2) + } + + @Test + fun testFreeformTasks_hasCorrectType() { + assertThat(freeformTasksGroupInfo().type).isEqualTo(TYPE_FREEFORM) + } + + @Test + fun testSplitTasks_taskInfoList_hasThreeTasks() { + val list = freeformTasksGroupInfo().taskInfoList + assertThat(list).hasSize(3) + assertThat(list[0].taskId).isEqualTo(1) + assertThat(list[1].taskId).isEqualTo(2) + assertThat(list[2].taskId).isEqualTo(3) + } + + @Test + fun testParcelling_singleTask() { + val recentTaskInfo = singleTaskGroupInfo() + val parcel = Parcel.obtain() + recentTaskInfo.writeToParcel(parcel, 0) + parcel.setDataPosition(0) + // Read the object back from the parcel + val recentTaskInfoParcel = CREATOR.createFromParcel(parcel) + assertThat(recentTaskInfoParcel.type).isEqualTo(TYPE_SINGLE) + assertThat(recentTaskInfoParcel.taskInfo1.taskId).isEqualTo(1) + assertThat(recentTaskInfoParcel.taskInfo2).isNull() + } + + @Test + fun testParcelling_splitTasks() { + val recentTaskInfo = splitTasksGroupInfo() + val parcel = Parcel.obtain() + recentTaskInfo.writeToParcel(parcel, 0) + parcel.setDataPosition(0) + // Read the object back from the parcel + val recentTaskInfoParcel = CREATOR.createFromParcel(parcel) + assertThat(recentTaskInfoParcel.type).isEqualTo(TYPE_SPLIT) + assertThat(recentTaskInfoParcel.taskInfo1.taskId).isEqualTo(1) + assertThat(recentTaskInfoParcel.taskInfo2).isNotNull() + assertThat(recentTaskInfoParcel.taskInfo2!!.taskId).isEqualTo(2) + assertThat(recentTaskInfoParcel.splitBounds).isNotNull() + } + + @Test + fun testParcelling_freeformTasks() { + val recentTaskInfo = freeformTasksGroupInfo() + val parcel = Parcel.obtain() + recentTaskInfo.writeToParcel(parcel, 0) + parcel.setDataPosition(0) + // Read the object back from the parcel + val recentTaskInfoParcel = CREATOR.createFromParcel(parcel) + assertThat(recentTaskInfoParcel.type).isEqualTo(TYPE_FREEFORM) + assertThat(recentTaskInfoParcel.taskInfoList).hasSize(3) + // Only compare task ids + val taskIdComparator = Correspondence.transforming<ActivityManager.RecentTaskInfo, Int>( + { it?.taskId }, "has taskId of" + ) + assertThat(recentTaskInfoParcel.taskInfoList).comparingElementsUsing(taskIdComparator) + .containsExactly(1, 2, 3) + } + + private fun createTaskInfo(id: Int) = ActivityManager.RecentTaskInfo().apply { + taskId = id + token = WindowContainerToken(mock(IWindowContainerToken::class.java)) + } + + private fun singleTaskGroupInfo(): GroupedRecentTaskInfo { + val task = createTaskInfo(id = 1) + return GroupedRecentTaskInfo.forSingleTask(task) + } + + private fun splitTasksGroupInfo(): GroupedRecentTaskInfo { + val task1 = createTaskInfo(id = 1) + val task2 = createTaskInfo(id = 2) + val splitBounds = SplitBounds(Rect(), Rect(), 1, 2) + return GroupedRecentTaskInfo.forSplitTasks(task1, task2, splitBounds) + } + + private fun freeformTasksGroupInfo(): GroupedRecentTaskInfo { + val task1 = createTaskInfo(id = 1) + val task2 = createTaskInfo(id = 2) + val task3 = createTaskInfo(id = 3) + return GroupedRecentTaskInfo.forFreeformTasks(task1, task2, task3) + } +} diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java index 81bb609cc711..e9a1e2523a86 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentTasksControllerTest.java @@ -20,6 +20,9 @@ import static android.app.ActivityManager.RECENT_IGNORE_UNAVAILABLE; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; + +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; @@ -45,11 +48,13 @@ import android.view.SurfaceControl; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; +import com.android.dx.mockito.inline.extended.StaticMockitoSession; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.ShellTestCase; import com.android.wm.shell.TestShellExecutor; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.TaskStackListenerImpl; +import com.android.wm.shell.desktopmode.DesktopMode; import com.android.wm.shell.sysui.ShellCommandHandler; import com.android.wm.shell.sysui.ShellInit; import com.android.wm.shell.util.GroupedRecentTaskInfo; @@ -179,6 +184,46 @@ public class RecentTasksControllerTest extends ShellTestCase { } @Test + public void testGetRecentTasks_groupActiveFreeformTasks() { + StaticMockitoSession mockitoSession = mockitoSession().mockStatic( + DesktopMode.class).startMocking(); + when(DesktopMode.isActive(any())).thenReturn(true); + + ActivityManager.RecentTaskInfo t1 = makeTaskInfo(1); + ActivityManager.RecentTaskInfo t2 = makeTaskInfo(2); + ActivityManager.RecentTaskInfo t3 = makeTaskInfo(3); + ActivityManager.RecentTaskInfo t4 = makeTaskInfo(4); + setRawList(t1, t2, t3, t4); + + mRecentTasksController.addActiveFreeformTask(1); + mRecentTasksController.addActiveFreeformTask(3); + + ArrayList<GroupedRecentTaskInfo> recentTasks = mRecentTasksController.getRecentTasks( + MAX_VALUE, RECENT_IGNORE_UNAVAILABLE, 0); + + // 2 freeform tasks should be grouped into one, 3 total recents entries + assertEquals(3, recentTasks.size()); + GroupedRecentTaskInfo freeformGroup = recentTasks.get(0); + GroupedRecentTaskInfo singleGroup1 = recentTasks.get(1); + GroupedRecentTaskInfo singleGroup2 = recentTasks.get(2); + + // Check that groups have expected types + assertEquals(GroupedRecentTaskInfo.TYPE_FREEFORM, freeformGroup.getType()); + assertEquals(GroupedRecentTaskInfo.TYPE_SINGLE, singleGroup1.getType()); + assertEquals(GroupedRecentTaskInfo.TYPE_SINGLE, singleGroup2.getType()); + + // Check freeform group entries + assertEquals(t1, freeformGroup.getTaskInfoList().get(0)); + assertEquals(t3, freeformGroup.getTaskInfoList().get(1)); + + // Check single entries + assertEquals(t2, singleGroup1.getTaskInfo1()); + assertEquals(t4, singleGroup2.getTaskInfo1()); + + mockitoSession.finishMocking(); + } + + @Test public void testRemovedTaskRemovesSplit() { ActivityManager.RecentTaskInfo t1 = makeTaskInfo(1); ActivityManager.RecentTaskInfo t2 = makeTaskInfo(2); @@ -254,6 +299,7 @@ public class RecentTasksControllerTest extends ShellTestCase { /** * Asserts that the recent tasks matches the given task ids. + * * @param expectedTaskIds list of task ids that map to the flattened task ids of the tasks in * the grouped task list */ @@ -262,22 +308,23 @@ public class RecentTasksControllerTest extends ShellTestCase { int[] flattenedTaskIds = new int[recentTasks.size() * 2]; for (int i = 0; i < recentTasks.size(); i++) { GroupedRecentTaskInfo pair = recentTasks.get(i); - int taskId1 = pair.mTaskInfo1.taskId; + int taskId1 = pair.getTaskInfo1().taskId; flattenedTaskIds[2 * i] = taskId1; - flattenedTaskIds[2 * i + 1] = pair.mTaskInfo2 != null - ? pair.mTaskInfo2.taskId + flattenedTaskIds[2 * i + 1] = pair.getTaskInfo2() != null + ? pair.getTaskInfo2().taskId : -1; - if (pair.mTaskInfo2 != null) { - assertNotNull(pair.mSplitBounds); - int leftTopTaskId = pair.mSplitBounds.leftTopTaskId; - int bottomRightTaskId = pair.mSplitBounds.rightBottomTaskId; + if (pair.getTaskInfo2() != null) { + assertNotNull(pair.getSplitBounds()); + int leftTopTaskId = pair.getSplitBounds().leftTopTaskId; + int bottomRightTaskId = pair.getSplitBounds().rightBottomTaskId; // Unclear if pairs are ordered by split position, most likely not. - assertTrue(leftTopTaskId == taskId1 || leftTopTaskId == pair.mTaskInfo2.taskId); + assertTrue(leftTopTaskId == taskId1 + || leftTopTaskId == pair.getTaskInfo2().taskId); assertTrue(bottomRightTaskId == taskId1 - || bottomRightTaskId == pair.mTaskInfo2.taskId); + || bottomRightTaskId == pair.getTaskInfo2().taskId); } else { - assertNull(pair.mSplitBounds); + assertNull(pair.getSplitBounds()); } } assertTrue("Expected: " + Arrays.toString(expectedTaskIds) diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTestUtils.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTestUtils.java index a67853cfe745..ae69b3ddd042 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTestUtils.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTestUtils.java @@ -71,11 +71,11 @@ public class SplitTestUtils { DisplayController displayController, DisplayImeController imeController, DisplayInsetsController insetsController, SplitLayout splitLayout, Transitions transitions, TransactionPool transactionPool, - SplitscreenEventLogger logger, ShellExecutor mainExecutor, + ShellExecutor mainExecutor, Optional<RecentTasksController> recentTasks) { super(context, displayId, syncQueue, taskOrganizer, mainStage, sideStage, displayController, imeController, insetsController, splitLayout, - transitions, transactionPool, logger, mainExecutor, recentTasks); + transitions, transactionPool, mainExecutor, recentTasks); // Prepare root task for testing. mRootTask = new TestRunningTaskInfoBuilder().build(); diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java index 1d038f4ee377..ea0033ba4bbb 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java @@ -95,7 +95,6 @@ public class SplitTransitionTests extends ShellTestCase { @Mock private TransactionPool mTransactionPool; @Mock private Transitions mTransitions; @Mock private SurfaceSession mSurfaceSession; - @Mock private SplitscreenEventLogger mLogger; @Mock private IconProvider mIconProvider; @Mock private ShellExecutor mMainExecutor; private SplitLayout mSplitLayout; @@ -127,7 +126,7 @@ public class SplitTransitionTests extends ShellTestCase { mStageCoordinator = new SplitTestUtils.TestStageCoordinator(mContext, DEFAULT_DISPLAY, mSyncQueue, mTaskOrganizer, mMainStage, mSideStage, mDisplayController, mDisplayImeController, mDisplayInsetsController, mSplitLayout, mTransitions, - mTransactionPool, mLogger, mMainExecutor, Optional.empty()); + mTransactionPool, mMainExecutor, Optional.empty()); mSplitScreenTransitions = mStageCoordinator.getSplitTransitions(); doAnswer((Answer<IBinder>) invocation -> mock(IBinder.class)) .when(mTransitions).startTransition(anyInt(), any(), any()); diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java index 4b68870d4129..9240abfbe47f 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageCoordinatorTests.java @@ -97,8 +97,6 @@ public class StageCoordinatorTests extends ShellTestCase { @Mock private TransactionPool mTransactionPool; @Mock - private SplitscreenEventLogger mLogger; - @Mock private ShellExecutor mMainExecutor; private final Rect mBounds1 = new Rect(10, 20, 30, 40); @@ -115,7 +113,7 @@ public class StageCoordinatorTests extends ShellTestCase { MockitoAnnotations.initMocks(this); mStageCoordinator = spy(new StageCoordinator(mContext, DEFAULT_DISPLAY, mSyncQueue, mTaskOrganizer, mMainStage, mSideStage, mDisplayController, mDisplayImeController, - mDisplayInsetsController, mSplitLayout, mTransitions, mTransactionPool, mLogger, + mDisplayInsetsController, mSplitLayout, mTransitions, mTransactionPool, mMainExecutor, Optional.empty())); doNothing().when(mStageCoordinator).updateActivityOptions(any(), anyInt()); @@ -227,7 +225,6 @@ public class StageCoordinatorTests extends ShellTestCase { mStageCoordinator.exitSplitScreen(testTaskId, EXIT_REASON_RETURN_HOME); verify(mMainStage).reorderChild(eq(testTaskId), eq(true), any(WindowContainerTransaction.class)); - verify(mSideStage).dismiss(any(WindowContainerTransaction.class), eq(false)); verify(mMainStage).resetBounds(any(WindowContainerTransaction.class)); } @@ -241,7 +238,6 @@ public class StageCoordinatorTests extends ShellTestCase { verify(mSideStage).reorderChild(eq(testTaskId), eq(true), any(WindowContainerTransaction.class)); verify(mSideStage).resetBounds(any(WindowContainerTransaction.class)); - verify(mMainStage).dismiss(any(WindowContainerTransaction.class), eq(false)); } @Test diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl index f4e965f422c0..3114be0e9c65 100644 --- a/location/java/android/location/ILocationManager.aidl +++ b/location/java/android/location/ILocationManager.aidl @@ -141,4 +141,5 @@ interface ILocationManager // used by gts tests to verify whitelists String[] getBackgroundThrottlingWhitelist(); PackageTagsList getIgnoreSettingsAllowlist(); + PackageTagsList getAdasAllowlist(); } diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java index 371f5ed4f346..5fe4ffd869ce 100644 --- a/location/java/android/location/LocationManager.java +++ b/location/java/android/location/LocationManager.java @@ -504,6 +504,19 @@ public class LocationManager { } /** + * Returns ADAS packages and their associated attribution tags. + * + * @hide + */ + public @NonNull PackageTagsList getAdasAllowlist() { + try { + return mService.getAdasAllowlist(); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + + /** * Returns the extra location controller package on the device. * * @hide diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java index 650f36059495..7ccbe51bbd49 100644 --- a/media/java/android/media/AudioSystem.java +++ b/media/java/android/media/AudioSystem.java @@ -2385,6 +2385,14 @@ public class AudioSystem return types.size() == 1 && types.contains(type); } + /** + * @hide + * Return true if the audio device type is a Bluetooth LE Audio device. + */ + public static boolean isLeAudioDeviceType(int type) { + return DEVICE_OUT_ALL_BLE_SET.contains(type); + } + /** @hide */ public static final int DEFAULT_MUTE_STREAMS_AFFECTED = (1 << STREAM_MUSIC) | diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java index e18642ce9856..0c8cacd894cf 100644 --- a/media/java/android/media/ExifInterface.java +++ b/media/java/android/media/ExifInterface.java @@ -79,20 +79,24 @@ import java.util.zip.CRC32; /** * This is a class for reading and writing Exif tags in various image file formats. * <p> + * <b>Note:</b> This class has known issues on some versions of Android. It is recommended to use + * the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a> + * <a href="{@docRoot}reference/androidx/exifinterface/media/ExifInterface.html">ExifInterface + * Library</a> since it offers a superset of the functionality of this class and is more easily + * updateable. In addition to the functionality of this class, it supports parsing extra metadata + * such as exposure and data compression information as well as setting extra metadata such as GPS + * and datetime information. + * <p> * Supported for reading: JPEG, PNG, WebP, HEIF, DNG, CR2, NEF, NRW, ARW, RW2, ORF, PEF, SRW, RAF, * AVIF. * <p> - * Supported for writing: JPEG, PNG, WebP, DNG. + * Supported for writing: JPEG, PNG, WebP. * <p> * Note: JPEG and HEIF files may contain XMP data either inside the Exif data chunk or outside of * it. This class will search both locations for XMP data, but if XMP data exist both inside and * outside Exif, will favor the XMP data inside Exif over the one outside. * <p> - * Note: It is recommended to use the <a href="{@docRoot}jetpack/androidx.html">AndroidX</a> - * <a href="{@docRoot}reference/androidx/exifinterface/media/ExifInterface.html">ExifInterface - * Library</a> since it is a superset of this class. In addition to the functionalities of this - * class, it supports parsing extra metadata such as exposure and data compression information - * as well as setting extra metadata such as GPS and datetime information. + */ public class ExifInterface { private static final String TAG = "ExifInterface"; @@ -1294,7 +1298,6 @@ public class ExifInterface { new ExifTag(TAG_Y_CB_CR_SUB_SAMPLING, 530, IFD_FORMAT_USHORT), new ExifTag(TAG_Y_CB_CR_POSITIONING, 531, IFD_FORMAT_USHORT), new ExifTag(TAG_REFERENCE_BLACK_WHITE, 532, IFD_FORMAT_URATIONAL), - new ExifTag(TAG_XMP, 700, IFD_FORMAT_BYTE), new ExifTag(TAG_COPYRIGHT, 33432, IFD_FORMAT_STRING), new ExifTag(TAG_EXIF_IFD_POINTER, 34665, IFD_FORMAT_ULONG), new ExifTag(TAG_GPS_INFO_IFD_POINTER, 34853, IFD_FORMAT_ULONG), @@ -2076,7 +2079,7 @@ public class ExifInterface { * {@link #setAttribute(String,String)} to set all attributes to write and * make a single call rather than multiple calls for each attribute. * <p> - * This method is supported for JPEG, PNG, WebP, and DNG files. + * This method is supported for JPEG, PNG, and WebP files. * <p class="note"> * Note: after calling this method, any attempts to obtain range information * from {@link #getAttributeRange(String)} or {@link #getThumbnailRange()} @@ -2088,11 +2091,15 @@ public class ExifInterface { * <p> * For PNG format, the Exif data will be stored as an "eXIf" chunk as per * "Extensions to the PNG 1.2 Specification, Version 1.5.0". + * <p> + * <b>Warning:</b> Calling this method on a DNG-based instance of {@code ExifInterface} may + * result in the original image file being overwritten with invalid data on some versions of + * Android 13 (API 33). */ public void saveAttributes() throws IOException { if (!isSupportedFormatForSavingAttributes()) { throw new IOException("ExifInterface only supports saving attributes for JPEG, PNG, " - + "WebP, and DNG formats."); + + "and WebP formats."); } if (mIsInputStream || (mSeekableFileDescriptor == null && mFilename == null)) { throw new IOException( @@ -2150,10 +2157,6 @@ public class ExifInterface { savePngAttributes(bufferedIn, bufferedOut); } else if (mMimeType == IMAGE_TYPE_WEBP) { saveWebpAttributes(bufferedIn, bufferedOut); - } else if (mMimeType == IMAGE_TYPE_DNG || mMimeType == IMAGE_TYPE_UNKNOWN) { - ByteOrderedDataOutputStream dataOutputStream = - new ByteOrderedDataOutputStream(bufferedOut, ByteOrder.BIG_ENDIAN); - writeExifSegment(dataOutputStream); } } } catch (Exception e) { @@ -5262,8 +5265,7 @@ public class ExifInterface { private boolean isSupportedFormatForSavingAttributes() { if (mIsSupportedFile && (mMimeType == IMAGE_TYPE_JPEG || mMimeType == IMAGE_TYPE_PNG - || mMimeType == IMAGE_TYPE_WEBP || mMimeType == IMAGE_TYPE_DNG - || mMimeType == IMAGE_TYPE_UNKNOWN)) { + || mMimeType == IMAGE_TYPE_WEBP)) { return true; } return false; diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java index c08f5a293e1d..220232d6e38f 100644 --- a/media/java/android/media/MediaCodec.java +++ b/media/java/android/media/MediaCodec.java @@ -3835,11 +3835,10 @@ final public class MediaCodec { private void invalidateByteBufferLocked( @Nullable ByteBuffer[] buffers, int index, boolean input) { if (buffers == null) { - if (index < 0) { - throw new IllegalStateException("index is negative (" + index + ")"); + if (index >= 0) { + BitSet indices = input ? mValidInputIndices : mValidOutputIndices; + indices.clear(index); } - BitSet indices = input ? mValidInputIndices : mValidOutputIndices; - indices.clear(index); } else if (index >= 0 && index < buffers.length) { ByteBuffer buffer = buffers[index]; if (buffer != null) { @@ -3851,10 +3850,9 @@ final public class MediaCodec { private void validateInputByteBufferLocked( @Nullable ByteBuffer[] buffers, int index) { if (buffers == null) { - if (index < 0) { - throw new IllegalStateException("index is negative (" + index + ")"); + if (index >= 0) { + mValidInputIndices.set(index); } - mValidInputIndices.set(index); } else if (index >= 0 && index < buffers.length) { ByteBuffer buffer = buffers[index]; if (buffer != null) { @@ -3868,11 +3866,10 @@ final public class MediaCodec { @Nullable ByteBuffer[] buffers, int index, boolean input) { synchronized(mBufferLock) { if (buffers == null) { - if (index < 0) { - throw new IllegalStateException("index is negative (" + index + ")"); + if (index >= 0) { + BitSet indices = input ? mValidInputIndices : mValidOutputIndices; + indices.set(index); } - BitSet indices = input ? mValidInputIndices : mValidOutputIndices; - indices.set(index); } else if (index >= 0 && index < buffers.length) { ByteBuffer buffer = buffers[index]; if (buffer != null) { @@ -3885,10 +3882,9 @@ final public class MediaCodec { private void validateOutputByteBufferLocked( @Nullable ByteBuffer[] buffers, int index, @NonNull BufferInfo info) { if (buffers == null) { - if (index < 0) { - throw new IllegalStateException("index is negative (" + index + ")"); + if (index >= 0) { + mValidOutputIndices.set(index); } - mValidOutputIndices.set(index); } else if (index >= 0 && index < buffers.length) { ByteBuffer buffer = buffers[index]; if (buffer != null) { diff --git a/media/java/android/media/Ringtone.java b/media/java/android/media/Ringtone.java index 86a94a9e0662..82c3139bb4d3 100644 --- a/media/java/android/media/Ringtone.java +++ b/media/java/android/media/Ringtone.java @@ -29,11 +29,12 @@ import android.net.Uri; import android.os.Binder; import android.os.Build; import android.os.RemoteException; +import android.os.Trace; import android.provider.MediaStore; import android.provider.MediaStore.MediaColumns; import android.provider.Settings; import android.util.Log; - +import com.android.internal.annotations.VisibleForTesting; import java.io.IOException; import java.util.ArrayList; @@ -136,13 +137,73 @@ public class Ringtone { */ public void setAudioAttributes(AudioAttributes attributes) throws IllegalArgumentException { + setAudioAttributesField(attributes); + // The audio attributes have to be set before the media player is prepared. + // Re-initialize it. + setUri(mUri, mVolumeShaperConfig); + createLocalMediaPlayer(); + } + + /** + * Same as {@link #setAudioAttributes(AudioAttributes)} except this one does not create + * the media player. + * @hide + */ + public void setAudioAttributesField(@Nullable AudioAttributes attributes) { if (attributes == null) { throw new IllegalArgumentException("Invalid null AudioAttributes for Ringtone"); } mAudioAttributes = attributes; - // The audio attributes have to be set before the media player is prepared. - // Re-initialize it. - setUri(mUri, mVolumeShaperConfig); + } + + /** + * Creates a local media player for the ringtone using currently set attributes. + * @hide + */ + public void createLocalMediaPlayer() { + Trace.beginSection("createLocalMediaPlayer"); + if (mUri == null) { + Log.e(TAG, "Could not create media player as no URI was provided."); + return; + } + destroyLocalPlayer(); + // try opening uri locally before delegating to remote player + mLocalPlayer = new MediaPlayer(); + try { + mLocalPlayer.setDataSource(mContext, mUri); + mLocalPlayer.setAudioAttributes(mAudioAttributes); + synchronized (mPlaybackSettingsLock) { + applyPlaybackProperties_sync(); + } + if (mVolumeShaperConfig != null) { + mVolumeShaper = mLocalPlayer.createVolumeShaper(mVolumeShaperConfig); + } + mLocalPlayer.prepare(); + + } catch (SecurityException | IOException e) { + destroyLocalPlayer(); + if (!mAllowRemote) { + Log.w(TAG, "Remote playback not allowed: " + e); + } + } + + if (LOGD) { + if (mLocalPlayer != null) { + Log.d(TAG, "Successfully created local player"); + } else { + Log.d(TAG, "Problem opening; delegating to remote player"); + } + } + Trace.endSection(); + } + + /** + * Returns whether a local player has been created for this ringtone. + * @hide + */ + @VisibleForTesting + public boolean hasLocalPlayer() { + return mLocalPlayer != null; } /** @@ -336,8 +397,7 @@ public class Ringtone { } /** - * Set {@link Uri} to be used for ringtone playback. Attempts to open - * locally, otherwise will delegate playback to remote + * Set {@link Uri} to be used for ringtone playback. * {@link IRingtonePlayer}. * * @hide @@ -348,6 +408,13 @@ public class Ringtone { } /** + * @hide + */ + public void setVolumeShaperConfig(@Nullable VolumeShaper.Configuration volumeShaperConfig) { + mVolumeShaperConfig = volumeShaperConfig; + } + + /** * Set {@link Uri} to be used for ringtone playback. Attempts to open * locally, otherwise will delegate playback to remote * {@link IRingtonePlayer}. Add {@link VolumeShaper} if required. @@ -356,41 +423,10 @@ public class Ringtone { */ public void setUri(Uri uri, @Nullable VolumeShaper.Configuration volumeShaperConfig) { mVolumeShaperConfig = volumeShaperConfig; - destroyLocalPlayer(); mUri = uri; if (mUri == null) { - return; - } - - // TODO: detect READ_EXTERNAL and specific content provider case, instead of relying on throwing - - // try opening uri locally before delegating to remote player - mLocalPlayer = new MediaPlayer(); - try { - mLocalPlayer.setDataSource(mContext, mUri); - mLocalPlayer.setAudioAttributes(mAudioAttributes); - synchronized (mPlaybackSettingsLock) { - applyPlaybackProperties_sync(); - } - if (mVolumeShaperConfig != null) { - mVolumeShaper = mLocalPlayer.createVolumeShaper(mVolumeShaperConfig); - } - mLocalPlayer.prepare(); - - } catch (SecurityException | IOException e) { destroyLocalPlayer(); - if (!mAllowRemote) { - Log.w(TAG, "Remote playback not allowed: " + e); - } - } - - if (LOGD) { - if (mLocalPlayer != null) { - Log.d(TAG, "Successfully created local player"); - } else { - Log.d(TAG, "Problem opening; delegating to remote player"); - } } } diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java index 27727699d05c..27db41cb9f4e 100644 --- a/media/java/android/media/RingtoneManager.java +++ b/media/java/android/media/RingtoneManager.java @@ -480,8 +480,9 @@ public class RingtoneManager { if (mStopPreviousRingtone && mPreviousRingtone != null) { mPreviousRingtone.stop(); } - - mPreviousRingtone = getRingtone(mContext, getRingtoneUri(position), inferStreamType()); + + mPreviousRingtone = + getRingtone(mContext, getRingtoneUri(position), inferStreamType(), true); return mPreviousRingtone; } @@ -677,7 +678,7 @@ public class RingtoneManager { */ public static Ringtone getRingtone(final Context context, Uri ringtoneUri) { // Don't set the stream type - return getRingtone(context, ringtoneUri, -1); + return getRingtone(context, ringtoneUri, -1, true); } /** @@ -698,7 +699,34 @@ public class RingtoneManager { final Context context, Uri ringtoneUri, @Nullable VolumeShaper.Configuration volumeShaperConfig) { // Don't set the stream type - return getRingtone(context, ringtoneUri, -1 /* streamType */, volumeShaperConfig); + return getRingtone(context, ringtoneUri, -1 /* streamType */, volumeShaperConfig, true); + } + + /** + * @hide + */ + public static Ringtone getRingtone(final Context context, Uri ringtoneUri, + @Nullable VolumeShaper.Configuration volumeShaperConfig, + boolean createLocalMediaPlayer) { + // Don't set the stream type + return getRingtone(context, ringtoneUri, -1 /* streamType */, volumeShaperConfig, + createLocalMediaPlayer); + } + + /** + * @hide + */ + public static Ringtone getRingtone(final Context context, Uri ringtoneUri, + @Nullable VolumeShaper.Configuration volumeShaperConfig, + AudioAttributes audioAttributes) { + // Don't set the stream type + Ringtone ringtone = + getRingtone(context, ringtoneUri, -1 /* streamType */, volumeShaperConfig, false); + if (ringtone != null) { + ringtone.setAudioAttributesField(audioAttributes); + ringtone.createLocalMediaPlayer(); + } + return ringtone; } //FIXME bypass the notion of stream types within the class @@ -707,14 +735,19 @@ public class RingtoneManager { * type. Normally, if you change the stream type on the returned * {@link Ringtone}, it will re-create the {@link MediaPlayer}. This is just * an optimized route to avoid that. - * + * * @param streamType The stream type for the ringtone, or -1 if it should * not be set (and the default used instead). + * @param createLocalMediaPlayer when true, the ringtone returned will be fully + * created otherwise, it will require the caller to create the media player manually + * {@link Ringtone#createLocalMediaPlayer()} in order to play the Ringtone. * @see #getRingtone(Context, Uri) */ @UnsupportedAppUsage - private static Ringtone getRingtone(final Context context, Uri ringtoneUri, int streamType) { - return getRingtone(context, ringtoneUri, streamType, null /* volumeShaperConfig */); + private static Ringtone getRingtone(final Context context, Uri ringtoneUri, int streamType, + boolean createLocalMediaPlayer) { + return getRingtone(context, ringtoneUri, streamType, null /* volumeShaperConfig */, + createLocalMediaPlayer); } //FIXME bypass the notion of stream types within the class @@ -730,16 +763,21 @@ public class RingtoneManager { * @see #getRingtone(Context, Uri) */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) - private static Ringtone getRingtone( - final Context context, Uri ringtoneUri, int streamType, - @Nullable VolumeShaper.Configuration volumeShaperConfig) { + private static Ringtone getRingtone(final Context context, Uri ringtoneUri, int streamType, + @Nullable VolumeShaper.Configuration volumeShaperConfig, + boolean createLocalMediaPlayer) { try { final Ringtone r = new Ringtone(context, true); if (streamType >= 0) { //FIXME deprecated call r.setStreamType(streamType); } + + r.setVolumeShaperConfig(volumeShaperConfig); r.setUri(ringtoneUri, volumeShaperConfig); + if (createLocalMediaPlayer) { + r.createLocalMediaPlayer(); + } return r; } catch (Exception ex) { Log.e(TAG, "Failed to open ringtone " + ringtoneUri + ": " + ex); diff --git a/packages/CompanionDeviceManager/res/values-ko/strings.xml b/packages/CompanionDeviceManager/res/values-ko/strings.xml index 4af740ef60bc..525896b300a3 100644 --- a/packages/CompanionDeviceManager/res/values-ko/strings.xml +++ b/packages/CompanionDeviceManager/res/values-ko/strings.xml @@ -23,7 +23,7 @@ <string name="summary_watch" msgid="3002344206574997652">"이 앱은 <xliff:g id="DEVICE_NAME">%1$s</xliff:g> 프로필을 관리하는 데 필요합니다. <xliff:g id="APP_NAME">%2$s</xliff:g>에서 알림과 상호작용하고 내 전화, SMS, 연락처, Calendar, 통화 기록, 근처 기기에 대한 권한을 갖게 됩니다."</string> <string name="permission_apps" msgid="6142133265286656158">"앱"</string> <string name="permission_apps_summary" msgid="798718816711515431">"휴대전화의 앱을 스트리밍합니다."</string> - <string name="title_app_streaming" msgid="2270331024626446950">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> 앱이 휴대전화에서 이 정보에 액세스하도록 허용합니다."</string> + <string name="title_app_streaming" msgid="2270331024626446950">"<strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong>이 휴대전화의 이 정보에 액세스하도록 허용합니다."</string> <string name="helper_title_app_streaming" msgid="4151687003439969765">"교차 기기 서비스"</string> <string name="helper_summary_app_streaming" msgid="5977509499890099">"<xliff:g id="APP_NAME">%1$s</xliff:g>에서 <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> 대신 기기 간에 앱을 스트리밍할 수 있는 권한을 요청하고 있습니다."</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> diff --git a/packages/CompanionDeviceManager/res/values-pl/strings.xml b/packages/CompanionDeviceManager/res/values-pl/strings.xml index 101356670e2d..88c0976c7f17 100644 --- a/packages/CompanionDeviceManager/res/values-pl/strings.xml +++ b/packages/CompanionDeviceManager/res/values-pl/strings.xml @@ -23,7 +23,7 @@ <string name="summary_watch" msgid="3002344206574997652">"Ta aplikacja jest niezbędna do zarządzania profilem <xliff:g id="DEVICE_NAME">%1$s</xliff:g>. Aplikacja <xliff:g id="APP_NAME">%2$s</xliff:g> będzie mogła korzystać z powiadomień oraz uprawnień dotyczących telefonu, SMS-ów, kontaktów, kalendarza, rejestrów połączeń i urządzeń w pobliżu."</string> <string name="permission_apps" msgid="6142133265286656158">"Aplikacje"</string> <string name="permission_apps_summary" msgid="798718816711515431">"Odtwarzaj strumieniowo aplikacje z telefonu"</string> - <string name="title_app_streaming" msgid="2270331024626446950">"Zezwól aplikacji <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> na dostęp do tych informacji na Twoim telefonie"</string> + <string name="title_app_streaming" msgid="2270331024626446950">"Zezwól urządzeniu <strong><xliff:g id="APP_NAME">%1$s</xliff:g></strong> na dostęp do tych informacji na Twoim telefonie"</string> <string name="helper_title_app_streaming" msgid="4151687003439969765">"Usługi na innym urządzeniu"</string> <string name="helper_summary_app_streaming" msgid="5977509499890099">"Aplikacja <xliff:g id="APP_NAME">%1$s</xliff:g> prosi w imieniu urządzenia <xliff:g id="DEVICE_TYPE">%2$s</xliff:g> o uprawnienia dotyczące strumieniowego odtwarzania treści z aplikacji na innym urządzeniu"</string> <string name="title_automotive_projection" msgid="3296005598978412847"></string> diff --git a/packages/InputDevices/res/values-hi/strings.xml b/packages/InputDevices/res/values-hi/strings.xml index 55fc5bfb6152..c3291a0d0a44 100644 --- a/packages/InputDevices/res/values-hi/strings.xml +++ b/packages/InputDevices/res/values-hi/strings.xml @@ -35,7 +35,7 @@ <string name="keyboard_layout_portuguese" msgid="2888198587329660305">"पुर्तगाली"</string> <string name="keyboard_layout_slovak" msgid="2469379934672837296">"स्लोवाक"</string> <string name="keyboard_layout_slovenian" msgid="1735933028924982368">"स्लोवेनियाई"</string> - <string name="keyboard_layout_turkish" msgid="7736163250907964898">"तुर्की"</string> + <string name="keyboard_layout_turkish" msgid="7736163250907964898">"तुर्किये"</string> <string name="keyboard_layout_turkish_f" msgid="9130320856010776018">"Turkish F"</string> <string name="keyboard_layout_ukrainian" msgid="8176637744389480417">"यूक्रेनियाई"</string> <string name="keyboard_layout_arabic" msgid="5671970465174968712">"अरबी"</string> diff --git a/packages/PrintSpooler/res/values-am/strings.xml b/packages/PrintSpooler/res/values-am/strings.xml index 832b8551f5d6..c1cec384be33 100644 --- a/packages/PrintSpooler/res/values-am/strings.xml +++ b/packages/PrintSpooler/res/values-am/strings.xml @@ -41,7 +41,7 @@ <string name="current_page_template" msgid="5145005201131935302">"<xliff:g id="CURRENT_PAGE">%1$d</xliff:g>/<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string> <string name="page_description_template" msgid="6831239682256197161">"ገጽ <xliff:g id="CURRENT_PAGE">%1$d</xliff:g> ከ<xliff:g id="PAGE_COUNT">%2$d</xliff:g>"</string> <string name="summary_template" msgid="8899734908625669193">"ማጠቃለያ፣ ቅጂዎች <xliff:g id="COPIES">%1$s</xliff:g>፣ የወረቀት መጠን <xliff:g id="PAPER_SIZE">%2$s</xliff:g>"</string> - <string name="expand_handle" msgid="7282974448109280522">"እጀታን ወደ ውጪ ላክ"</string> + <string name="expand_handle" msgid="7282974448109280522">"እጀታን ወደ ውጭ ላክ"</string> <string name="collapse_handle" msgid="6886637989442507451">"እጀታን ሰብስብ"</string> <string name="print_button" msgid="645164566271246268">"አትም"</string> <string name="savetopdf_button" msgid="2976186791686924743">"ወደ ፔዲኤፍ አስቀምጥ"</string> diff --git a/packages/PrintSpooler/res/values-es-rUS/strings.xml b/packages/PrintSpooler/res/values-es-rUS/strings.xml index 441ae73877c0..90c1937a2891 100644 --- a/packages/PrintSpooler/res/values-es-rUS/strings.xml +++ b/packages/PrintSpooler/res/values-es-rUS/strings.xml @@ -56,6 +56,7 @@ <string name="print_select_printer" msgid="7388760939873368698">"Seleccionar impresora"</string> <string name="print_forget_printer" msgid="5035287497291910766">"No recordar impresora"</string> <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868"> + <item quantity="many"><xliff:g id="COUNT_1">%1$s</xliff:g> printers found</item> <item quantity="other">Se encontraron <xliff:g id="COUNT_1">%1$s</xliff:g> impresoras.</item> <item quantity="one">Se encontró <xliff:g id="COUNT_0">%1$s</xliff:g> impresora.</item> </plurals> @@ -76,6 +77,7 @@ <string name="disabled_services_title" msgid="7313253167968363211">"Servicios inhabilitados"</string> <string name="all_services_title" msgid="5578662754874906455">"Todos los servicios"</string> <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138"> + <item quantity="many">Install to discover <xliff:g id="COUNT_1">%1$s</xliff:g> printers</item> <item quantity="other">Instala para ver <xliff:g id="COUNT_1">%1$s</xliff:g> impresoras</item> <item quantity="one">Instala para ver <xliff:g id="COUNT_0">%1$s</xliff:g> impresora</item> </plurals> diff --git a/packages/PrintSpooler/res/values-es/strings.xml b/packages/PrintSpooler/res/values-es/strings.xml index c1ff28207ac3..18e56dbcd6fc 100644 --- a/packages/PrintSpooler/res/values-es/strings.xml +++ b/packages/PrintSpooler/res/values-es/strings.xml @@ -56,6 +56,7 @@ <string name="print_select_printer" msgid="7388760939873368698">"Seleccionar impresora"</string> <string name="print_forget_printer" msgid="5035287497291910766">"Olvidar impresora"</string> <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868"> + <item quantity="many"><xliff:g id="COUNT_1">%1$s</xliff:g> printers found</item> <item quantity="other">Se han encontrado <xliff:g id="COUNT_1">%1$s</xliff:g> impresoras</item> <item quantity="one">Se ha encontrado <xliff:g id="COUNT_0">%1$s</xliff:g> impresora</item> </plurals> @@ -76,6 +77,7 @@ <string name="disabled_services_title" msgid="7313253167968363211">"Servicios inhabilitados"</string> <string name="all_services_title" msgid="5578662754874906455">"Todos los servicios"</string> <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138"> + <item quantity="many">Install to discover <xliff:g id="COUNT_1">%1$s</xliff:g> printers</item> <item quantity="other">Instalar para descubrir <xliff:g id="COUNT_1">%1$s</xliff:g> impresoras</item> <item quantity="one">Instalar para descubrir <xliff:g id="COUNT_0">%1$s</xliff:g> impresora</item> </plurals> diff --git a/packages/PrintSpooler/res/values-fr-rCA/strings.xml b/packages/PrintSpooler/res/values-fr-rCA/strings.xml index 3b7775a97dde..082c148746a3 100644 --- a/packages/PrintSpooler/res/values-fr-rCA/strings.xml +++ b/packages/PrintSpooler/res/values-fr-rCA/strings.xml @@ -57,6 +57,7 @@ <string name="print_forget_printer" msgid="5035287497291910766">"Supprimer l\'imprimante"</string> <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868"> <item quantity="one"><xliff:g id="COUNT_1">%1$s</xliff:g> imprimante trouvée</item> + <item quantity="many"><xliff:g id="COUNT_1">%1$s</xliff:g> printers found</item> <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> imprimante trouvées</item> </plurals> <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string> @@ -77,6 +78,7 @@ <string name="all_services_title" msgid="5578662754874906455">"Tous les services"</string> <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138"> <item quantity="one">Installer pour détecter <xliff:g id="COUNT_1">%1$s</xliff:g> imprimante</item> + <item quantity="many">Install to discover <xliff:g id="COUNT_1">%1$s</xliff:g> printers</item> <item quantity="other">Installer pour détecter <xliff:g id="COUNT_1">%1$s</xliff:g> imprimantes</item> </plurals> <string name="printing_notification_title_template" msgid="295903957762447362">"Impression de <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> en cours…"</string> diff --git a/packages/PrintSpooler/res/values-fr/strings.xml b/packages/PrintSpooler/res/values-fr/strings.xml index f6e901de8393..560c5dcfe924 100644 --- a/packages/PrintSpooler/res/values-fr/strings.xml +++ b/packages/PrintSpooler/res/values-fr/strings.xml @@ -57,6 +57,7 @@ <string name="print_forget_printer" msgid="5035287497291910766">"Supprimer l\'imprimante"</string> <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868"> <item quantity="one"><xliff:g id="COUNT_1">%1$s</xliff:g> imprimante trouvée</item> + <item quantity="many"><xliff:g id="COUNT_1">%1$s</xliff:g> printers found</item> <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> imprimantes trouvées</item> </plurals> <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> – <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string> @@ -77,6 +78,7 @@ <string name="all_services_title" msgid="5578662754874906455">"Tous les services"</string> <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138"> <item quantity="one">Installer pour détecter <xliff:g id="COUNT_1">%1$s</xliff:g> imprimante</item> + <item quantity="many">Install to discover <xliff:g id="COUNT_1">%1$s</xliff:g> printers</item> <item quantity="other">Installer pour détecter <xliff:g id="COUNT_1">%1$s</xliff:g> imprimantes</item> </plurals> <string name="printing_notification_title_template" msgid="295903957762447362">"Impression de \"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>\" en cours…"</string> diff --git a/packages/PrintSpooler/res/values-it/strings.xml b/packages/PrintSpooler/res/values-it/strings.xml index 96751ea12081..569bbc2ef045 100644 --- a/packages/PrintSpooler/res/values-it/strings.xml +++ b/packages/PrintSpooler/res/values-it/strings.xml @@ -56,6 +56,7 @@ <string name="print_select_printer" msgid="7388760939873368698">"Seleziona stampante"</string> <string name="print_forget_printer" msgid="5035287497291910766">"Elimina stampante"</string> <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868"> + <item quantity="many"><xliff:g id="COUNT_1">%1$s</xliff:g> printers found</item> <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> stampanti trovate</item> <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> stampante trovata</item> </plurals> @@ -76,6 +77,7 @@ <string name="disabled_services_title" msgid="7313253167968363211">"Servizi disattivati"</string> <string name="all_services_title" msgid="5578662754874906455">"Tutti i servizi"</string> <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138"> + <item quantity="many">Install to discover <xliff:g id="COUNT_1">%1$s</xliff:g> printers</item> <item quantity="other">Installa per rilevare <xliff:g id="COUNT_1">%1$s</xliff:g> stampanti</item> <item quantity="one">Installa per rilevare <xliff:g id="COUNT_0">%1$s</xliff:g> stampante</item> </plurals> diff --git a/packages/PrintSpooler/res/values-pt-rBR/strings.xml b/packages/PrintSpooler/res/values-pt-rBR/strings.xml index 6ce46367d8c1..3b460a1fe6dd 100644 --- a/packages/PrintSpooler/res/values-pt-rBR/strings.xml +++ b/packages/PrintSpooler/res/values-pt-rBR/strings.xml @@ -57,6 +57,7 @@ <string name="print_forget_printer" msgid="5035287497291910766">"Esquecer impressora"</string> <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868"> <item quantity="one"><xliff:g id="COUNT_1">%1$s</xliff:g> impressoras encontradas</item> + <item quantity="many"><xliff:g id="COUNT_1">%1$s</xliff:g> printers found</item> <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> impressoras encontradas</item> </plurals> <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string> @@ -77,6 +78,7 @@ <string name="all_services_title" msgid="5578662754874906455">"Todos os serviços"</string> <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138"> <item quantity="one">Instale para encontrar <xliff:g id="COUNT_1">%1$s</xliff:g> impressoras</item> + <item quantity="many">Install to discover <xliff:g id="COUNT_1">%1$s</xliff:g> printers</item> <item quantity="other">Instale para encontrar <xliff:g id="COUNT_1">%1$s</xliff:g> impressoras</item> </plurals> <string name="printing_notification_title_template" msgid="295903957762447362">"Imprimindo <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string> diff --git a/packages/PrintSpooler/res/values-pt-rPT/strings.xml b/packages/PrintSpooler/res/values-pt-rPT/strings.xml index 4517efe0934a..8c1087e463a0 100644 --- a/packages/PrintSpooler/res/values-pt-rPT/strings.xml +++ b/packages/PrintSpooler/res/values-pt-rPT/strings.xml @@ -56,6 +56,7 @@ <string name="print_select_printer" msgid="7388760939873368698">"Selecionar impressora"</string> <string name="print_forget_printer" msgid="5035287497291910766">"Esquecer impressora"</string> <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868"> + <item quantity="many"><xliff:g id="COUNT_1">%1$s</xliff:g> printers found</item> <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> impressoras encontradas</item> <item quantity="one"><xliff:g id="COUNT_0">%1$s</xliff:g> impressora encontrada</item> </plurals> @@ -76,6 +77,7 @@ <string name="disabled_services_title" msgid="7313253167968363211">"Serviços desativados"</string> <string name="all_services_title" msgid="5578662754874906455">"Todos os serviços"</string> <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138"> + <item quantity="many">Install to discover <xliff:g id="COUNT_1">%1$s</xliff:g> printers</item> <item quantity="other">Instale para detetar <xliff:g id="COUNT_1">%1$s</xliff:g> impressoras</item> <item quantity="one">Instale para detetar <xliff:g id="COUNT_0">%1$s</xliff:g> impressora</item> </plurals> diff --git a/packages/PrintSpooler/res/values-pt/strings.xml b/packages/PrintSpooler/res/values-pt/strings.xml index 6ce46367d8c1..3b460a1fe6dd 100644 --- a/packages/PrintSpooler/res/values-pt/strings.xml +++ b/packages/PrintSpooler/res/values-pt/strings.xml @@ -57,6 +57,7 @@ <string name="print_forget_printer" msgid="5035287497291910766">"Esquecer impressora"</string> <plurals name="print_search_result_count_utterance" formatted="false" msgid="6997663738361080868"> <item quantity="one"><xliff:g id="COUNT_1">%1$s</xliff:g> impressoras encontradas</item> + <item quantity="many"><xliff:g id="COUNT_1">%1$s</xliff:g> printers found</item> <item quantity="other"><xliff:g id="COUNT_1">%1$s</xliff:g> impressoras encontradas</item> </plurals> <string name="printer_extended_description_template" msgid="1366699227703381874">"<xliff:g id="PRINT_SERVICE_LABEL">%1$s</xliff:g> - <xliff:g id="PRINTER_DESCRIPTION">%2$s</xliff:g>"</string> @@ -77,6 +78,7 @@ <string name="all_services_title" msgid="5578662754874906455">"Todos os serviços"</string> <plurals name="print_services_recommendation_subtitle" formatted="false" msgid="5678487708807185138"> <item quantity="one">Instale para encontrar <xliff:g id="COUNT_1">%1$s</xliff:g> impressoras</item> + <item quantity="many">Install to discover <xliff:g id="COUNT_1">%1$s</xliff:g> printers</item> <item quantity="other">Instale para encontrar <xliff:g id="COUNT_1">%1$s</xliff:g> impressoras</item> </plurals> <string name="printing_notification_title_template" msgid="295903957762447362">"Imprimindo <xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g>"</string> diff --git a/packages/SettingsLib/IllustrationPreference/res/values/colors.xml b/packages/SettingsLib/IllustrationPreference/res/values/colors.xml index ead5174f9ee2..0de7be0a5a08 100644 --- a/packages/SettingsLib/IllustrationPreference/res/values/colors.xml +++ b/packages/SettingsLib/IllustrationPreference/res/values/colors.xml @@ -43,6 +43,8 @@ <color name="settingslib_color_grey400">#bdc1c6</color> <color name="settingslib_color_grey300">#dadce0</color> <color name="settingslib_color_grey200">#e8eaed</color> + <color name="settingslib_color_grey100">#f1f3f4</color> + <color name="settingslib_color_grey50">#f8f9fa</color> <color name="settingslib_color_orange600">#e8710a</color> <color name="settingslib_color_orange400">#fa903e</color> <color name="settingslib_color_orange300">#fcad70</color> diff --git a/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/LottieColorUtils.java b/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/LottieColorUtils.java new file mode 100644 index 000000000000..93b6acc9e160 --- /dev/null +++ b/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/LottieColorUtils.java @@ -0,0 +1,88 @@ +/* + * 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.settingslib.widget; + +import android.content.Context; +import android.content.res.Configuration; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffColorFilter; + +import com.airbnb.lottie.LottieAnimationView; +import com.airbnb.lottie.LottieProperty; +import com.airbnb.lottie.model.KeyPath; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * Util class which dynamically changes the color of tags in a lottie json file between Dark Theme + * (DT) and Light Theme (LT). This class assumes the json file is for Dark Theme. + */ +public class LottieColorUtils { + private static final Map<String, Integer> DARK_TO_LIGHT_THEME_COLOR_MAP; + + static { + HashMap<String, Integer> map = new HashMap<>(); + map.put( + ".grey600", + R.color.settingslib_color_grey300); + map.put( + ".grey800", + R.color.settingslib_color_grey200); + map.put( + ".grey900", + R.color.settingslib_color_grey50); + map.put( + ".red400", + R.color.settingslib_color_red600); + map.put( + ".black", + android.R.color.white); + map.put( + ".blue400", + R.color.settingslib_color_blue600); + map.put( + ".green400", + R.color.settingslib_color_green600); + DARK_TO_LIGHT_THEME_COLOR_MAP = Collections.unmodifiableMap(map); + } + + private LottieColorUtils() { + } + + private static boolean isDarkMode(Context context) { + return (context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) + == Configuration.UI_MODE_NIGHT_YES; + } + + /** Applies dynamic colors based on DT vs. LT. The LottieAnimationView should be Dark Theme. */ + public static void applyDynamicColors(Context context, + LottieAnimationView lottieAnimationView) { + // Assume the default for the lottie is dark mode + if (isDarkMode(context)) { + return; + } + for (String key : DARK_TO_LIGHT_THEME_COLOR_MAP.keySet()) { + final int color = context.getColor(DARK_TO_LIGHT_THEME_COLOR_MAP.get(key)); + lottieAnimationView.addValueCallback( + new KeyPath("**", key, "**"), + LottieProperty.COLOR_FILTER, + frameInfo -> new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_ATOP)); + } + } +} diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml index a6ae45395cd0..6565337c1385 100644 --- a/packages/SettingsLib/res/values-ca/strings.xml +++ b/packages/SettingsLib/res/values-ca/strings.xml @@ -668,7 +668,7 @@ <string name="bt_le_audio_broadcast_dialog_sub_title" msgid="268234802198852753">"Si emets <xliff:g id="SWITCHAPP">%1$s</xliff:g> o canvies la sortida, l\'emissió actual s\'aturarà"</string> <string name="bt_le_audio_broadcast_dialog_switch_app" msgid="5749813313369517812">"Emet <xliff:g id="SWITCHAPP">%1$s</xliff:g>"</string> <string name="bt_le_audio_broadcast_dialog_different_output" msgid="2638402023060391333">"Canvia la sortida"</string> - <string name="back_navigation_animation" msgid="8105467568421689484">"Animacions per a les accions de tornada predictives"</string> - <string name="back_navigation_animation_summary" msgid="741292224121599456">"Activa animacions del sistema per a la tornada predictiva."</string> + <string name="back_navigation_animation" msgid="8105467568421689484">"Animacions de retrocés predictiu"</string> + <string name="back_navigation_animation_summary" msgid="741292224121599456">"Activa animacions del sistema de retrocés predictiu."</string> <string name="back_navigation_animation_dialog" msgid="8696966520944625596">"Aquesta configuració activa animacions del sistema per a accions gestuals predictives. Requereix definir enableOnBackInvokedCallback com a \"true\" en cada aplicació al fitxer de manifest."</string> </resources> diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml index 84c5a6959d07..e050ae0e17c2 100644 --- a/packages/SettingsLib/res/values-ta/strings.xml +++ b/packages/SettingsLib/res/values-ta/strings.xml @@ -597,7 +597,7 @@ <string name="guest_reset_guest" msgid="6110013010356013758">"கெஸ்ட் அமர்வை மீட்டமை"</string> <string name="guest_reset_guest_dialog_title" msgid="8047270010895437534">"கெஸ்ட்டை மீட்டமைக்கவா?"</string> <string name="guest_remove_guest_dialog_title" msgid="4548511006624088072">"கெஸ்ட் பயனரை அகற்றவா?"</string> - <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"மீட்டமை"</string> + <string name="guest_reset_guest_confirm_button" msgid="2989915693215617237">"ரீசெட்"</string> <string name="guest_remove_guest_confirm_button" msgid="7858123434954143879">"அகற்று"</string> <string name="guest_resetting" msgid="7822120170191509566">"கெஸ்ட்டை மீட்டமைக்கிறது…"</string> <string name="guest_reset_and_restart_dialog_title" msgid="3396657008451616041">"கெஸ்ட் அமர்வை ரீசெட் செய்யவா?"</string> diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothCallback.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothCallback.java index 3152e65d5a36..fa056e2b77bd 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothCallback.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothCallback.java @@ -16,6 +16,22 @@ package com.android.settingslib.bluetooth; +import static android.bluetooth.BluetoothAdapter.STATE_CONNECTED; +import static android.bluetooth.BluetoothAdapter.STATE_CONNECTING; +import static android.bluetooth.BluetoothAdapter.STATE_DISCONNECTED; +import static android.bluetooth.BluetoothAdapter.STATE_DISCONNECTING; +import static android.bluetooth.BluetoothAdapter.STATE_OFF; +import static android.bluetooth.BluetoothAdapter.STATE_ON; +import static android.bluetooth.BluetoothAdapter.STATE_TURNING_OFF; +import static android.bluetooth.BluetoothAdapter.STATE_TURNING_ON; + +import android.annotation.IntDef; +import android.annotation.Nullable; + +import androidx.annotation.NonNull; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; /** * BluetoothCallback provides a callback interface for the settings @@ -33,7 +49,7 @@ public interface BluetoothCallback { * {@link android.bluetooth.BluetoothAdapter#STATE_ON}, * {@link android.bluetooth.BluetoothAdapter#STATE_TURNING_OFF}. */ - default void onBluetoothStateChanged(int bluetoothState) {} + default void onBluetoothStateChanged(@AdapterState int bluetoothState) {} /** * It will be called when the local Bluetooth adapter has started @@ -54,14 +70,14 @@ public interface BluetoothCallback { * * @param cachedDevice the Bluetooth device. */ - default void onDeviceAdded(CachedBluetoothDevice cachedDevice) {} + default void onDeviceAdded(@NonNull CachedBluetoothDevice cachedDevice) {} /** * It will be called when requiring to remove a remote device from CachedBluetoothDevice list * * @param cachedDevice the Bluetooth device. */ - default void onDeviceDeleted(CachedBluetoothDevice cachedDevice) {} + default void onDeviceDeleted(@NonNull CachedBluetoothDevice cachedDevice) {} /** * It will be called when bond state of a remote device is changed. @@ -73,7 +89,8 @@ public interface BluetoothCallback { * {@link android.bluetooth.BluetoothDevice#BOND_BONDING}, * {@link android.bluetooth.BluetoothDevice#BOND_BONDED}. */ - default void onDeviceBondStateChanged(CachedBluetoothDevice cachedDevice, int bondState) {} + default void onDeviceBondStateChanged( + @NonNull CachedBluetoothDevice cachedDevice, int bondState) {} /** * It will be called in following situations: @@ -89,7 +106,9 @@ public interface BluetoothCallback { * {@link android.bluetooth.BluetoothAdapter#STATE_CONNECTED}, * {@link android.bluetooth.BluetoothAdapter#STATE_DISCONNECTING}. */ - default void onConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) {} + default void onConnectionStateChanged( + @Nullable CachedBluetoothDevice cachedDevice, + @ConnectionState int state) {} /** * It will be called when device been set as active for {@code bluetoothProfile} @@ -101,7 +120,8 @@ public interface BluetoothCallback { * @param activeDevice the active Bluetooth device. * @param bluetoothProfile the profile of active Bluetooth device. */ - default void onActiveDeviceChanged(CachedBluetoothDevice activeDevice, int bluetoothProfile) {} + default void onActiveDeviceChanged( + @Nullable CachedBluetoothDevice activeDevice, int bluetoothProfile) {} /** * It will be called in following situations: @@ -124,8 +144,10 @@ public interface BluetoothCallback { * {@link android.bluetooth.BluetoothProfile#STATE_DISCONNECTING}. * @param bluetoothProfile the BluetoothProfile id. */ - default void onProfileConnectionStateChanged(CachedBluetoothDevice cachedDevice, - int state, int bluetoothProfile) { + default void onProfileConnectionStateChanged( + @NonNull CachedBluetoothDevice cachedDevice, + @ConnectionState int state, + int bluetoothProfile) { } /** @@ -138,6 +160,24 @@ public interface BluetoothCallback { * {@link android.bluetooth.BluetoothAdapter#STATE_DISCONNECTED}, * {@link android.bluetooth.BluetoothAdapter#STATE_CONNECTED} */ - default void onAclConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) { - } + default void onAclConnectionStateChanged( + @NonNull CachedBluetoothDevice cachedDevice, int state) {} + + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = { "STATE_" }, value = { + STATE_DISCONNECTED, + STATE_CONNECTING, + STATE_CONNECTED, + STATE_DISCONNECTING, + }) + @interface ConnectionState {} + + @IntDef(prefix = { "STATE_" }, value = { + STATE_OFF, + STATE_TURNING_ON, + STATE_ON, + STATE_TURNING_OFF, + }) + @Retention(RetentionPolicy.SOURCE) + @interface AdapterState {} } diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java index 51812f043908..a9f4e9c74103 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/BluetoothEventManager.java @@ -32,6 +32,7 @@ import android.os.UserHandle; import android.telephony.TelephonyManager; import android.util.Log; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; @@ -193,19 +194,19 @@ public class BluetoothEventManager { return deviceAdded; } - void dispatchDeviceAdded(CachedBluetoothDevice cachedDevice) { + void dispatchDeviceAdded(@NonNull CachedBluetoothDevice cachedDevice) { for (BluetoothCallback callback : mCallbacks) { callback.onDeviceAdded(cachedDevice); } } - void dispatchDeviceRemoved(CachedBluetoothDevice cachedDevice) { + void dispatchDeviceRemoved(@NonNull CachedBluetoothDevice cachedDevice) { for (BluetoothCallback callback : mCallbacks) { callback.onDeviceDeleted(cachedDevice); } } - void dispatchProfileConnectionStateChanged(CachedBluetoothDevice device, int state, + void dispatchProfileConnectionStateChanged(@NonNull CachedBluetoothDevice device, int state, int bluetoothProfile) { for (BluetoothCallback callback : mCallbacks) { callback.onProfileConnectionStateChanged(device, state, bluetoothProfile); @@ -228,7 +229,8 @@ public class BluetoothEventManager { } @VisibleForTesting - void dispatchActiveDeviceChanged(CachedBluetoothDevice activeDevice, + void dispatchActiveDeviceChanged( + @Nullable CachedBluetoothDevice activeDevice, int bluetoothProfile) { for (CachedBluetoothDevice cachedDevice : mDeviceManager.getCachedDevicesCopy()) { boolean isActive = Objects.equals(cachedDevice, activeDevice); @@ -239,7 +241,7 @@ public class BluetoothEventManager { } } - private void dispatchAclStateChanged(CachedBluetoothDevice activeDevice, int state) { + private void dispatchAclStateChanged(@NonNull CachedBluetoothDevice activeDevice, int state) { for (BluetoothCallback callback : mCallbacks) { callback.onAclConnectionStateChanged(activeDevice, state); } @@ -456,6 +458,7 @@ public class BluetoothEventManager { Log.w(TAG, "ActiveDeviceChangedHandler: action is null"); return; } + @Nullable CachedBluetoothDevice activeDevice = mDeviceManager.findDevice(device); int bluetoothProfile = 0; if (Objects.equals(action, BluetoothA2dp.ACTION_ACTIVE_DEVICE_CHANGED)) { diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java index 3ca94dba027e..a5f3df9f628d 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java @@ -398,6 +398,7 @@ public class CachedBluetoothDevice implements Comparable<CachedBluetoothDevice> * @param id the group id from the CSIP. */ public void setGroupId(int id) { + Log.d(TAG, this.getDevice().getAnonymizedAddress() + " set GroupId " + id); mGroupId = id; } diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java index 26a208026411..5662ce6bd808 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDeviceManager.java @@ -357,8 +357,12 @@ public class CachedBluetoothDeviceManager { * {@code false}. */ public synchronized boolean shouldPairByCsip(BluetoothDevice device, int groupId) { - if (mOngoingSetMemberPair != null || device.getBondState() != BluetoothDevice.BOND_NONE + boolean isOngoingSetMemberPair = mOngoingSetMemberPair != null; + int bondState = device.getBondState(); + if (isOngoingSetMemberPair || bondState != BluetoothDevice.BOND_NONE || !mCsipDeviceManager.isExistedGroupId(groupId)) { + Log.d(TAG, "isOngoingSetMemberPair: " + isOngoingSetMemberPair + + " , device.getBondState: " + bondState); return false; } diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java index 9b38238ca8b8..d5de3f0525a0 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CsipDeviceManager.java @@ -102,9 +102,12 @@ public class CsipDeviceManager { } private CachedBluetoothDevice getCachedDevice(int groupId) { + log("getCachedDevice: groupId: " + groupId); for (int i = mCachedDevices.size() - 1; i >= 0; i--) { CachedBluetoothDevice cachedDevice = mCachedDevices.get(i); if (cachedDevice.getGroupId() == groupId) { + log("getCachedDevice: found cachedDevice with the groupId: " + + cachedDevice.getDevice().getAnonymizedAddress()); return cachedDevice; } } diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidDeviceManager.java index 818f5ca33ebf..cf4e1ee99f92 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidDeviceManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidDeviceManager.java @@ -46,16 +46,43 @@ public class HearingAidDeviceManager { if (isValidHiSyncId(hiSyncId)) { // Once hiSyncId is valid, assign hiSyncId newDevice.setHiSyncId(hiSyncId); + final int side = getDeviceSide(newDevice.getDevice()); + final int mode = getDeviceMode(newDevice.getDevice()); + newDevice.setDeviceSide(side); + newDevice.setDeviceMode(mode); } } private long getHiSyncId(BluetoothDevice device) { - LocalBluetoothProfileManager profileManager = mBtManager.getProfileManager(); - HearingAidProfile profileProxy = profileManager.getHearingAidProfile(); - if (profileProxy != null) { - return profileProxy.getHiSyncId(device); + final LocalBluetoothProfileManager profileManager = mBtManager.getProfileManager(); + final HearingAidProfile profileProxy = profileManager.getHearingAidProfile(); + if (profileProxy == null) { + return BluetoothHearingAid.HI_SYNC_ID_INVALID; } - return BluetoothHearingAid.HI_SYNC_ID_INVALID; + + return profileProxy.getHiSyncId(device); + } + + private int getDeviceSide(BluetoothDevice device) { + final LocalBluetoothProfileManager profileManager = mBtManager.getProfileManager(); + final HearingAidProfile profileProxy = profileManager.getHearingAidProfile(); + if (profileProxy == null) { + Log.w(TAG, "HearingAidProfile is not supported and not ready to fetch device side"); + return HearingAidProfile.DeviceSide.SIDE_INVALID; + } + + return profileProxy.getDeviceSide(device); + } + + private int getDeviceMode(BluetoothDevice device) { + final LocalBluetoothProfileManager profileManager = mBtManager.getProfileManager(); + final HearingAidProfile profileProxy = profileManager.getHearingAidProfile(); + if (profileProxy == null) { + Log.w(TAG, "HearingAidProfile is not supported and not ready to fetch device mode"); + return HearingAidProfile.DeviceMode.MODE_INVALID; + } + + return profileProxy.getDeviceMode(device); } boolean setSubDeviceIfNeeded(CachedBluetoothDevice newDevice) { @@ -98,6 +125,10 @@ public class HearingAidDeviceManager { if (isValidHiSyncId(newHiSyncId)) { cachedDevice.setHiSyncId(newHiSyncId); newSyncIdSet.add(newHiSyncId); + final int side = getDeviceSide(cachedDevice.getDevice()); + final int mode = getDeviceMode(cachedDevice.getDevice()); + cachedDevice.setDeviceSide(side); + cachedDevice.setDeviceMode(mode); } } } diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcast.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcast.java index 01d581ed28db..123c01b6e12f 100644 --- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcast.java +++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/LocalBluetoothLeBroadcast.java @@ -26,11 +26,17 @@ import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothLeAudioContentMetadata; import android.bluetooth.BluetoothLeBroadcast; import android.bluetooth.BluetoothLeBroadcastMetadata; +import android.bluetooth.BluetoothLeBroadcastSubgroup; import android.bluetooth.BluetoothProfile; import android.bluetooth.BluetoothProfile.ServiceListener; +import android.content.ContentResolver; import android.content.Context; -import android.content.SharedPreferences; +import android.database.ContentObserver; +import android.net.Uri; import android.os.Build; +import android.os.Handler; +import android.os.Looper; +import android.provider.Settings; import android.text.TextUtils; import android.util.Log; @@ -40,6 +46,7 @@ import com.android.settingslib.R; import java.nio.charset.StandardCharsets; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.UUID; @@ -54,19 +61,20 @@ import java.util.concurrent.ThreadLocalRandom; */ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile { private static final String TAG = "LocalBluetoothLeBroadcast"; - private static final int UNKNOWN_VALUE_PLACEHOLDER = -1; private static final boolean DEBUG = BluetoothUtils.D; static final String NAME = "LE_AUDIO_BROADCAST"; - // Order of this profile in device profiles list - private static final int ORDINAL = 1; - private static final String PREF_NAME = "LocalBluetoothLeBroadcast"; - private static final String PREF_PROGRAM_INFO = "PrefProgramInfo"; - private static final String PREF_BROADCAST_CODE = "PrefBroadcastCode"; - private static final String PREF_APP_SOURCE_NAME = "PrefAppSourceName"; private static final String UNDERLINE = "_"; - private static final int DEFAULT_CODE_MIN = 1000; private static final int DEFAULT_CODE_MAX = 9999; + private static final int DEFAULT_CODE_MIN = 1000; + // Order of this profile in device profiles list + private static final int ORDINAL = 1; + private static final int UNKNOWN_VALUE_PLACEHOLDER = -1; + private static final Uri[] SETTINGS_URIS = new Uri[]{ + Settings.Secure.getUriFor(Settings.Secure.BLUETOOTH_LE_BROADCAST_PROGRAM_INFO), + Settings.Secure.getUriFor(Settings.Secure.BLUETOOTH_LE_BROADCAST_CODE), + Settings.Secure.getUriFor(Settings.Secure.BLUETOOTH_LE_BROADCAST_APP_SOURCE_NAME), + }; private BluetoothLeBroadcast mService; private BluetoothLeAudioContentMetadata mBluetoothLeAudioContentMetadata; @@ -78,8 +86,9 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile { private boolean mIsProfileReady; private String mProgramInfo; private byte[] mBroadcastCode; - private SharedPreferences mSharedPref; private Executor mExecutor; + private ContentResolver mContentResolver; + private ContentObserver mSettingsObserver; private final ServiceListener mServiceListener = new ServiceListener() { @Override @@ -91,6 +100,11 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile { mService = (BluetoothLeBroadcast) proxy; mIsProfileReady = true; registerServiceCallBack(mExecutor, mBroadcastCallback); + List<BluetoothLeBroadcastMetadata> metadata = getAllBroadcastMetadata(); + if (!metadata.isEmpty()) { + updateBroadcastInfoFromBroadcastMetadata(metadata.get(0)); + } + registerContentObserver(); } } @@ -102,6 +116,7 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile { if(mIsProfileReady) { mIsProfileReady = false; unregisterServiceCallBack(mBroadcastCallback); + unregisterContentObserver(); } } }; @@ -116,7 +131,7 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile { + broadcastId); } setLatestBroadcastId(broadcastId); - setAppSourceName(mNewAppSourceName); + setAppSourceName(mNewAppSourceName, /*updateContentResolver=*/ true); } @Override @@ -160,7 +175,7 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile { + broadcastId); } setLatestBroadcastId(broadcastId); - setAppSourceName(mNewAppSourceName); + setAppSourceName(mNewAppSourceName, /*updateContentResolver=*/ true); } @Override @@ -181,30 +196,27 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile { } }; + private class BroadcastSettingsObserver extends ContentObserver { + BroadcastSettingsObserver(Handler h) { + super(h); + } + + @Override + public void onChange(boolean selfChange) { + Log.d(TAG, "BroadcastSettingsObserver: onChange"); + updateBroadcastInfoFromContentProvider(); + } + } + LocalBluetoothLeBroadcast(Context context) { mExecutor = Executors.newSingleThreadExecutor(); BluetoothAdapter.getDefaultAdapter(). getProfileProxy(context, mServiceListener, BluetoothProfile.LE_AUDIO_BROADCAST); mBuilder = new BluetoothLeAudioContentMetadata.Builder(); - mSharedPref = context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE); - if (mSharedPref != null) { - String programInfo = mSharedPref.getString(PREF_PROGRAM_INFO, ""); - if (programInfo.isEmpty()) { - programInfo = getDefaultValueOfProgramInfo(); - } - setProgramInfo(programInfo); - - String prefBroadcastCode = mSharedPref.getString(PREF_BROADCAST_CODE, ""); - byte[] broadcastCode; - if (prefBroadcastCode.isEmpty()) { - broadcastCode = getDefaultValueOfBroadcastCode(); - } else { - broadcastCode = prefBroadcastCode.getBytes(StandardCharsets.UTF_8); - } - setBroadcastCode(broadcastCode); - - mAppSourceName = mSharedPref.getString(PREF_APP_SOURCE_NAME, ""); - } + mContentResolver = context.getContentResolver(); + Handler handler = new Handler(Looper.getMainLooper()); + mSettingsObserver = new BroadcastSettingsObserver(handler); + updateBroadcastInfoFromContentProvider(); } /** @@ -217,11 +229,12 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile { Log.d(TAG, "The BluetoothLeBroadcast is null when starting the broadcast."); return; } + String programInfo = getProgramInfo(); if (DEBUG) { Log.d(TAG, - "startBroadcast: language = " + language + " ,programInfo = " + mProgramInfo); + "startBroadcast: language = " + language + " ,programInfo = " + programInfo); } - buildContentMetadata(language, mProgramInfo); + buildContentMetadata(language, programInfo); mService.startBroadcast(mBluetoothLeAudioContentMetadata, mBroadcastCode); } @@ -230,21 +243,28 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile { } public void setProgramInfo(String programInfo) { - if (programInfo == null || programInfo.isEmpty()) { + setProgramInfo(programInfo, /*updateContentResolver=*/ true); + } + + private void setProgramInfo(String programInfo, boolean updateContentResolver) { + if (TextUtils.isEmpty(programInfo)) { Log.d(TAG, "setProgramInfo: programInfo is null or empty"); return; } + if (mProgramInfo != null && TextUtils.equals(mProgramInfo, programInfo)) { + Log.d(TAG, "setProgramInfo: programInfo is not changed"); + return; + } Log.d(TAG, "setProgramInfo: " + programInfo); mProgramInfo = programInfo; - - if (mSharedPref == null) { - Log.d(TAG, "setProgramInfo: sharedPref is null"); - return; + if (updateContentResolver) { + if (mContentResolver == null) { + Log.d(TAG, "mContentResolver is null"); + return; + } + Settings.Secure.putString(mContentResolver, + Settings.Secure.BLUETOOTH_LE_BROADCAST_PROGRAM_INFO, programInfo); } - SharedPreferences.Editor editor = mSharedPref.edit(); - editor.putString(PREF_PROGRAM_INFO, mProgramInfo); - editor.apply(); - } public byte[] getBroadcastCode() { @@ -252,22 +272,31 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile { } public void setBroadcastCode(byte[] broadcastCode) { - if (broadcastCode == null || broadcastCode.length == 0) { - Log.d(TAG, "setBroadcastCode: broadcastCode is null or empty"); + setBroadcastCode(broadcastCode, /*updateContentResolver=*/ true); + } + + private void setBroadcastCode(byte[] broadcastCode, boolean updateContentResolver) { + if (broadcastCode == null) { + Log.d(TAG, "setBroadcastCode: broadcastCode is null"); return; } - mBroadcastCode = broadcastCode; - - if (mSharedPref == null) { - Log.d(TAG, "setBroadcastCode: sharedPref is null"); + if (mBroadcastCode != null && Arrays.equals(broadcastCode, mBroadcastCode)) { + Log.d(TAG, "setBroadcastCode: broadcastCode is not changed"); return; } - SharedPreferences.Editor editor = mSharedPref.edit(); - editor.putString(PREF_BROADCAST_CODE, new String(broadcastCode, StandardCharsets.UTF_8)); - editor.apply(); + mBroadcastCode = broadcastCode; + if (updateContentResolver) { + if (mContentResolver == null) { + Log.d(TAG, "mContentResolver is null"); + return; + } + Settings.Secure.putString(mContentResolver, Settings.Secure.BLUETOOTH_LE_BROADCAST_CODE, + new String(broadcastCode, StandardCharsets.UTF_8)); + } } private void setLatestBroadcastId(int broadcastId) { + Log.d(TAG, "setLatestBroadcastId: mBroadcastId is " + broadcastId); mBroadcastId = broadcastId; } @@ -275,19 +304,24 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile { return mBroadcastId; } - private void setAppSourceName(String appSourceName) { + private void setAppSourceName(String appSourceName, boolean updateContentResolver) { if (TextUtils.isEmpty(appSourceName)) { appSourceName = ""; } + if (mAppSourceName != null && TextUtils.equals(mAppSourceName, appSourceName)) { + Log.d(TAG, "setAppSourceName: appSourceName is not changed"); + return; + } mAppSourceName = appSourceName; mNewAppSourceName = ""; - if (mSharedPref == null) { - Log.d(TAG, "setBroadcastCode: sharedPref is null"); - return; + if (updateContentResolver) { + if (mContentResolver == null) { + Log.d(TAG, "mContentResolver is null"); + return; + } + Settings.Secure.putString(mContentResolver, + Settings.Secure.BLUETOOTH_LE_BROADCAST_APP_SOURCE_NAME, mAppSourceName); } - SharedPreferences.Editor editor = mSharedPref.edit(); - editor.putString(PREF_APP_SOURCE_NAME, appSourceName); - editor.apply(); } public String getAppSourceName() { @@ -299,6 +333,7 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile { if (bluetoothLeBroadcastMetadata != null && bluetoothLeBroadcastMetadata.getBroadcastId() == mBroadcastId) { mBluetoothLeBroadcastMetadata = bluetoothLeBroadcastMetadata; + updateBroadcastInfoFromBroadcastMetadata(bluetoothLeBroadcastMetadata); } } @@ -318,6 +353,48 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile { return mBluetoothLeBroadcastMetadata; } + private void updateBroadcastInfoFromContentProvider() { + if (mContentResolver == null) { + Log.d(TAG, "updateBroadcastInfoFromContentProvider: mContentResolver is null"); + return; + } + String programInfo = Settings.Secure.getString(mContentResolver, + Settings.Secure.BLUETOOTH_LE_BROADCAST_PROGRAM_INFO); + if (programInfo == null) { + programInfo = getDefaultValueOfProgramInfo(); + } + setProgramInfo(programInfo, /*updateContentResolver=*/ false); + + String prefBroadcastCode = Settings.Secure.getString(mContentResolver, + Settings.Secure.BLUETOOTH_LE_BROADCAST_CODE); + byte[] broadcastCode = (prefBroadcastCode == null) ? getDefaultValueOfBroadcastCode() + : prefBroadcastCode.getBytes(StandardCharsets.UTF_8); + setBroadcastCode(broadcastCode, /*updateContentResolver=*/ false); + + String appSourceName = Settings.Secure.getString(mContentResolver, + Settings.Secure.BLUETOOTH_LE_BROADCAST_APP_SOURCE_NAME); + setAppSourceName(appSourceName, /*updateContentResolver=*/ false); + } + + private void updateBroadcastInfoFromBroadcastMetadata( + BluetoothLeBroadcastMetadata bluetoothLeBroadcastMetadata) { + if (bluetoothLeBroadcastMetadata == null) { + Log.d(TAG, "The bluetoothLeBroadcastMetadata is null"); + return; + } + setBroadcastCode(bluetoothLeBroadcastMetadata.getBroadcastCode()); + setLatestBroadcastId(bluetoothLeBroadcastMetadata.getBroadcastId()); + + List<BluetoothLeBroadcastSubgroup> subgroup = bluetoothLeBroadcastMetadata.getSubgroups(); + if (subgroup == null || subgroup.size() < 1) { + Log.d(TAG, "The subgroup is not valid value"); + return; + } + BluetoothLeAudioContentMetadata contentMetadata = subgroup.get(0).getContentMetadata(); + setProgramInfo(contentMetadata.getProgramInfo()); + setAppSourceName(getAppSourceName(), /*updateContentResolver=*/ true); + } + /** * Stop the latest LE Broadcast. If the system stopped the LE Broadcast, then the system * calls the corresponding callback {@link BluetoothLeBroadcast.Callback}. @@ -350,12 +427,13 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile { Log.d(TAG, "The BluetoothLeBroadcast is null when updating the broadcast."); return; } + String programInfo = getProgramInfo(); if (DEBUG) { Log.d(TAG, - "updateBroadcast: language = " + language + " ,programInfo = " + mProgramInfo); + "updateBroadcast: language = " + language + " ,programInfo = " + programInfo); } mNewAppSourceName = appSourceName; - mBluetoothLeAudioContentMetadata = mBuilder.setProgramInfo(mProgramInfo).build(); + mBluetoothLeAudioContentMetadata = mBuilder.setProgramInfo(programInfo).build(); mService.updateBroadcast(mBroadcastId, mBluetoothLeAudioContentMetadata); } @@ -517,8 +595,7 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile { if (DEBUG) { Log.d(TAG, "resetCacheInfo:"); } - mNewAppSourceName = ""; - mAppSourceName = ""; + setAppSourceName("", /*updateContentResolver=*/ true); mBluetoothLeBroadcastMetadata = null; mBroadcastId = UNKNOWN_VALUE_PLACEHOLDER; } @@ -528,4 +605,22 @@ public class LocalBluetoothLeBroadcast implements LocalBluetoothProfile { //first 12 chars from xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx return randomUUID.substring(0, 8) + randomUUID.substring(9, 13); } + + private void registerContentObserver() { + if (mContentResolver == null) { + Log.d(TAG, "mContentResolver is null"); + return; + } + for (Uri uri : SETTINGS_URIS) { + mContentResolver.registerContentObserver(uri, false, mSettingsObserver); + } + } + + private void unregisterContentObserver() { + if (mContentResolver == null) { + Log.d(TAG, "mContentResolver is null"); + return; + } + mContentResolver.unregisterContentObserver(mSettingsObserver); + } } diff --git a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java index a72f311e55ed..58c15eb8073c 100644 --- a/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java +++ b/packages/SettingsLib/src/com/android/settingslib/media/InfoMediaManager.java @@ -422,7 +422,7 @@ public class InfoMediaManager extends MediaManager { || sessionInfo.getSelectedRoutes().size() <= 1; } - private void refreshDevices() { + private synchronized void refreshDevices() { mMediaDevices.clear(); mCurrentConnectedDevice = null; if (TextUtils.isEmpty(mPackageName)) { @@ -452,7 +452,7 @@ public class InfoMediaManager extends MediaManager { return infos; } - private void buildAvailableRoutes() { + private synchronized void buildAvailableRoutes() { for (MediaRoute2Info route : getAvailableRoutes(mPackageName)) { if (DEBUG) { Log.d(TAG, "buildAvailableRoutes() route : " + route.getName() + ", volume : " @@ -462,7 +462,7 @@ public class InfoMediaManager extends MediaManager { } } - private List<MediaRoute2Info> getAvailableRoutes(String packageName) { + private synchronized List<MediaRoute2Info> getAvailableRoutes(String packageName) { final List<MediaRoute2Info> infos = new ArrayList<>(); RoutingSessionInfo routingSessionInfo = getRoutingSessionInfo(packageName); if (routingSessionInfo != null) { @@ -596,7 +596,7 @@ public class InfoMediaManager extends MediaManager { @Override public void onSessionUpdated(RoutingSessionInfo sessionInfo) { - dispatchDataChanged(); + refreshDevices(); } } } diff --git a/packages/SettingsLib/src/com/android/settingslib/users/AvatarPhotoController.java b/packages/SettingsLib/src/com/android/settingslib/users/AvatarPhotoController.java index 63a9f0c5c7f4..4ce88ee115a2 100644 --- a/packages/SettingsLib/src/com/android/settingslib/users/AvatarPhotoController.java +++ b/packages/SettingsLib/src/com/android/settingslib/users/AvatarPhotoController.java @@ -21,8 +21,8 @@ import android.content.ClipData; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; -import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; @@ -48,6 +48,7 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.util.List; import java.util.concurrent.ExecutionException; class AvatarPhotoController { @@ -326,13 +327,13 @@ class AvatarPhotoController { @Override public boolean startSystemActivityForResult(Intent intent, int code) { - ActivityInfo info = intent.resolveActivityInfo(mActivity.getPackageManager(), - PackageManager.MATCH_SYSTEM_ONLY); - if (info == null) { + List<ResolveInfo> resolveInfos = mActivity.getPackageManager() + .queryIntentActivities(intent, PackageManager.MATCH_SYSTEM_ONLY); + if (resolveInfos.isEmpty()) { Log.w(TAG, "No system package activity could be found for code " + code); return false; } - intent.setPackage(info.packageName); + intent.setPackage(resolveInfos.get(0).activityInfo.packageName); mActivity.startActivityForResult(intent, code); return true; } diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidDeviceManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidDeviceManagerTest.java index d80a59178c1c..611b0a4a28b8 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidDeviceManagerTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/bluetooth/HearingAidDeviceManagerTest.java @@ -102,16 +102,25 @@ public class HearingAidDeviceManagerTest { } /** - * Test initHearingAidDeviceIfNeeded, a valid HiSyncId will be assigned + * Test initHearingAidDeviceIfNeeded, set HearingAid's information, including HiSyncId, + * deviceSide, deviceMode. */ @Test - public void initHearingAidDeviceIfNeeded_validHiSyncId_verifyHiSyncId() { + public void initHearingAidDeviceIfNeeded_validHiSyncId_setHearingAidInfos() { when(mHearingAidProfile.getHiSyncId(mDevice1)).thenReturn(HISYNCID1); + when(mHearingAidProfile.getDeviceMode(mDevice1)).thenReturn( + HearingAidProfile.DeviceMode.MODE_BINAURAL); + when(mHearingAidProfile.getDeviceSide(mDevice1)).thenReturn( + HearingAidProfile.DeviceSide.SIDE_RIGHT); assertThat(mCachedDevice1.getHiSyncId()).isNotEqualTo(HISYNCID1); mHearingAidDeviceManager.initHearingAidDeviceIfNeeded(mCachedDevice1); assertThat(mCachedDevice1.getHiSyncId()).isEqualTo(HISYNCID1); + assertThat(mCachedDevice1.getDeviceMode()).isEqualTo( + HearingAidProfile.DeviceMode.MODE_BINAURAL); + assertThat(mCachedDevice1.getDeviceSide()).isEqualTo( + HearingAidProfile.DeviceSide.SIDE_RIGHT); } /** @@ -251,6 +260,29 @@ public class HearingAidDeviceManagerTest { } /** + * Test updateHearingAidsDevices, set HearingAid's information, including HiSyncId, deviceSide, + * deviceMode. + */ + @Test + public void updateHearingAidsDevices_validHiSyncId_setHearingAidInfos() { + when(mHearingAidProfile.getHiSyncId(mDevice1)).thenReturn(HISYNCID1); + when(mHearingAidProfile.getDeviceMode(mDevice1)).thenReturn( + HearingAidProfile.DeviceMode.MODE_BINAURAL); + when(mHearingAidProfile.getDeviceSide(mDevice1)).thenReturn( + HearingAidProfile.DeviceSide.SIDE_RIGHT); + mCachedDeviceManager.mCachedDevices.add(mCachedDevice1); + + mHearingAidDeviceManager.updateHearingAidsDevices(); + + assertThat(mCachedDevice1.getHiSyncId()).isEqualTo(HISYNCID1); + assertThat(mCachedDevice1.getDeviceMode()).isEqualTo( + HearingAidProfile.DeviceMode.MODE_BINAURAL); + assertThat(mCachedDevice1.getDeviceSide()).isEqualTo( + HearingAidProfile.DeviceSide.SIDE_RIGHT); + verify(mHearingAidDeviceManager).onHiSyncIdChanged(HISYNCID1); + } + + /** * Test onProfileConnectionStateChangedIfProcessed. * When first hearing aid device is connected, to process it same as other generic devices. * No need to process it. diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaManagerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaManagerTest.java index ee7b7d6b180f..d04d85a70858 100644 --- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaManagerTest.java +++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/media/InfoMediaManagerTest.java @@ -666,12 +666,22 @@ public class InfoMediaManagerTest { } @Test - public void onSessionUpdated_shouldDispatchDataChanged() { + public void onSessionUpdated_shouldDispatchDeviceListAdded() { + final MediaRoute2Info info = mock(MediaRoute2Info.class); + when(info.getId()).thenReturn(TEST_ID); + when(info.getClientPackageName()).thenReturn(TEST_PACKAGE_NAME); + when(info.isSystemRoute()).thenReturn(true); + + final List<MediaRoute2Info> routes = new ArrayList<>(); + routes.add(info); + mShadowRouter2Manager.setAllRoutes(routes); + + mInfoMediaManager.mPackageName = ""; mInfoMediaManager.registerCallback(mCallback); mInfoMediaManager.mMediaRouterCallback.onSessionUpdated(mock(RoutingSessionInfo.class)); - verify(mCallback).onDeviceAttributesChanged(); + verify(mCallback).onDeviceListAdded(any()); } @Test diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java index 36fbf8f850d3..453a71327b50 100644 --- a/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java +++ b/packages/SettingsProvider/src/android/provider/settings/backup/SecureSettings.java @@ -212,6 +212,9 @@ public class SecureSettings { Settings.Secure.LOCKSCREEN_USE_DOUBLE_LINE_CLOCK, Settings.Secure.STATUS_BAR_SHOW_VIBRATE_ICON, Settings.Secure.ASSIST_TOUCH_GESTURE_ENABLED, - Settings.Secure.ASSIST_LONG_PRESS_HOME_ENABLED + Settings.Secure.ASSIST_LONG_PRESS_HOME_ENABLED, + Settings.Secure.BLUETOOTH_LE_BROADCAST_PROGRAM_INFO, + Settings.Secure.BLUETOOTH_LE_BROADCAST_CODE, + Settings.Secure.BLUETOOTH_LE_BROADCAST_APP_SOURCE_NAME }; } diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java index 6a70230701f6..a39735ffe2c7 100644 --- a/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java +++ b/packages/SettingsProvider/src/android/provider/settings/validators/SecureSettingsValidators.java @@ -344,5 +344,8 @@ public class SecureSettingsValidators { return true; }); VALIDATORS.put(Secure.ODI_CAPTIONS_VOLUME_UI_ENABLED, BOOLEAN_VALIDATOR); + VALIDATORS.put(Secure.BLUETOOTH_LE_BROADCAST_PROGRAM_INFO, ANY_STRING_VALIDATOR); + VALIDATORS.put(Secure.BLUETOOTH_LE_BROADCAST_CODE, ANY_STRING_VALIDATOR); + VALIDATORS.put(Secure.BLUETOOTH_LE_BROADCAST_APP_SOURCE_NAME, ANY_STRING_VALIDATOR); } } diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml index 7649de649cf8..2737ecf5ffa6 100644 --- a/packages/SystemUI/AndroidManifest.xml +++ b/packages/SystemUI/AndroidManifest.xml @@ -414,7 +414,7 @@ </intent-filter> </receiver> - <service android:name=".ImageWallpaper" + <service android:name=".wallpapers.ImageWallpaper" android:singleUser="true" android:permission="android.permission.BIND_WALLPAPER" android:exported="true" /> diff --git a/packages/SystemUI/OWNERS b/packages/SystemUI/OWNERS index 546f0d23a5c2..a65f9be3e83f 100644 --- a/packages/SystemUI/OWNERS +++ b/packages/SystemUI/OWNERS @@ -7,6 +7,7 @@ dsandler@android.com aaliomer@google.com adamcohen@google.com alexflo@google.com +arteiro@google.com asc@google.com awickham@google.com beverlyt@google.com diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt index 7d4dcf88542b..ebabdf571dfd 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt +++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ActivityLaunchAnimator.kt @@ -352,8 +352,11 @@ class ActivityLaunchAnimator( * The animation was cancelled. Note that [onLaunchAnimationEnd] will still be called after * this if the animation was already started, i.e. if [onLaunchAnimationStart] was called * before the cancellation. + * + * If this launch animation affected the occlusion state of the keyguard, WM will provide + * us with [newKeyguardOccludedState] so that we can set the occluded state appropriately. */ - fun onLaunchAnimationCancelled() {} + fun onLaunchAnimationCancelled(newKeyguardOccludedState: Boolean? = null) {} } @VisibleForTesting @@ -667,7 +670,7 @@ class ActivityLaunchAnimator( removeTimeout() context.mainExecutor.execute { animation?.cancel() - controller.onLaunchAnimationCancelled() + controller.onLaunchAnimationCancelled(newKeyguardOccludedState = isKeyguardOccluded) } } 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 eac5d275092a..9656b8a99d41 100644 --- a/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt +++ b/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt @@ -238,7 +238,7 @@ constructor( } } - override fun onLaunchAnimationCancelled() { + override fun onLaunchAnimationCancelled(newKeyguardOccludedState: Boolean?) { controller.onLaunchAnimationCancelled() enableDialogDismiss() dialog.dismiss() diff --git a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SlowUserQueryDetector.kt b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SlowUserQueryDetector.kt new file mode 100644 index 000000000000..b00661575c14 --- /dev/null +++ b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SlowUserQueryDetector.kt @@ -0,0 +1,103 @@ +/* + * 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.internal.systemui.lint + +import com.android.tools.lint.detector.api.Category +import com.android.tools.lint.detector.api.Detector +import com.android.tools.lint.detector.api.Implementation +import com.android.tools.lint.detector.api.Issue +import com.android.tools.lint.detector.api.JavaContext +import com.android.tools.lint.detector.api.Scope +import com.android.tools.lint.detector.api.Severity +import com.android.tools.lint.detector.api.SourceCodeScanner +import com.intellij.psi.PsiMethod +import org.jetbrains.uast.UCallExpression + +/** + * Checks for slow calls to ActivityManager.getCurrentUser() or UserManager.getUserInfo() and + * suggests using UserTracker instead. For more info, see: http://go/multi-user-in-systemui-slides. + */ +@Suppress("UnstableApiUsage") +class SlowUserQueryDetector : Detector(), SourceCodeScanner { + + override fun getApplicableMethodNames(): List<String> { + return listOf("getCurrentUser", "getUserInfo") + } + + override fun visitMethodCall(context: JavaContext, node: UCallExpression, method: PsiMethod) { + val evaluator = context.evaluator + if ( + evaluator.isStatic(method) && + method.name == "getCurrentUser" && + method.containingClass?.qualifiedName == "android.app.ActivityManager" + ) { + context.report( + ISSUE_SLOW_USER_ID_QUERY, + method, + context.getNameLocation(node), + "ActivityManager.getCurrentUser() is slow. " + + "Use UserTracker.getUserId() instead." + ) + } + if ( + !evaluator.isStatic(method) && + method.name == "getUserInfo" && + method.containingClass?.qualifiedName == "android.os.UserManager" + ) { + context.report( + ISSUE_SLOW_USER_INFO_QUERY, + method, + context.getNameLocation(node), + "UserManager.getUserInfo() is slow. " + "Use UserTracker.getUserInfo() instead." + ) + } + } + + companion object { + @JvmField + val ISSUE_SLOW_USER_ID_QUERY: Issue = + Issue.create( + id = "SlowUserIdQuery", + briefDescription = "User ID queried using ActivityManager instead of UserTracker.", + explanation = + "ActivityManager.getCurrentUser() makes a binder call and is slow. " + + "Instead, inject a UserTracker and call UserTracker.getUserId(). For " + + "more info, see: http://go/multi-user-in-systemui-slides", + category = Category.PERFORMANCE, + priority = 8, + severity = Severity.WARNING, + implementation = + Implementation(SlowUserQueryDetector::class.java, Scope.JAVA_FILE_SCOPE) + ) + + @JvmField + val ISSUE_SLOW_USER_INFO_QUERY: Issue = + Issue.create( + id = "SlowUserInfoQuery", + briefDescription = "User info queried using UserManager instead of UserTracker.", + explanation = + "UserManager.getUserInfo() makes a binder call and is slow. " + + "Instead, inject a UserTracker and call UserTracker.getUserInfo(). For " + + "more info, see: http://go/multi-user-in-systemui-slides", + category = Category.PERFORMANCE, + priority = 8, + severity = Severity.WARNING, + implementation = + Implementation(SlowUserQueryDetector::class.java, Scope.JAVA_FILE_SCOPE) + ) + } +} diff --git a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt index c7c73d3c86a1..4879883e7c2e 100644 --- a/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt +++ b/packages/SystemUI/checks/src/com/android/internal/systemui/lint/SystemUIIssueRegistry.kt @@ -30,6 +30,8 @@ class SystemUIIssueRegistry : IssueRegistry() { get() = listOf( BindServiceViaContextDetector.ISSUE, BroadcastSentViaContextDetector.ISSUE, + SlowUserQueryDetector.ISSUE_SLOW_USER_ID_QUERY, + SlowUserQueryDetector.ISSUE_SLOW_USER_INFO_QUERY, GetMainLooperViaContextDetector.ISSUE, RegisterReceiverViaContextDetector.ISSUE, SoftwareBitmapDetector.ISSUE, diff --git a/packages/SystemUI/checks/tests/com/android/systemui/lint/SlowUserQueryDetectorTest.kt b/packages/SystemUI/checks/tests/com/android/systemui/lint/SlowUserQueryDetectorTest.kt new file mode 100644 index 000000000000..2738f0409fd0 --- /dev/null +++ b/packages/SystemUI/checks/tests/com/android/systemui/lint/SlowUserQueryDetectorTest.kt @@ -0,0 +1,194 @@ +package com.android.internal.systemui.lint + +import com.android.tools.lint.checks.infrastructure.LintDetectorTest +import com.android.tools.lint.checks.infrastructure.TestFile +import com.android.tools.lint.checks.infrastructure.TestFiles +import com.android.tools.lint.checks.infrastructure.TestLintTask +import com.android.tools.lint.detector.api.Detector +import com.android.tools.lint.detector.api.Issue +import org.junit.Test + +class SlowUserQueryDetectorTest : LintDetectorTest() { + + override fun getDetector(): Detector = SlowUserQueryDetector() + override fun lint(): TestLintTask = super.lint().allowMissingSdk(true) + + override fun getIssues(): List<Issue> = + listOf( + SlowUserQueryDetector.ISSUE_SLOW_USER_ID_QUERY, + SlowUserQueryDetector.ISSUE_SLOW_USER_INFO_QUERY + ) + + @Test + fun testGetCurrentUser() { + lint() + .files( + TestFiles.java( + """ + package test.pkg; + import android.app.ActivityManager; + + public class TestClass1 { + public void slewlyGetCurrentUser() { + ActivityManager.getCurrentUser(); + } + } + """ + ) + .indented(), + *stubs + ) + .issues( + SlowUserQueryDetector.ISSUE_SLOW_USER_ID_QUERY, + SlowUserQueryDetector.ISSUE_SLOW_USER_INFO_QUERY + ) + .run() + .expectWarningCount(1) + .expectContains( + "ActivityManager.getCurrentUser() is slow. " + + "Use UserTracker.getUserId() instead." + ) + } + + @Test + fun testGetUserInfo() { + lint() + .files( + TestFiles.java( + """ + package test.pkg; + import android.os.UserManager; + + public class TestClass2 { + public void slewlyGetUserInfo(UserManager userManager) { + userManager.getUserInfo(); + } + } + """ + ) + .indented(), + *stubs + ) + .issues( + SlowUserQueryDetector.ISSUE_SLOW_USER_ID_QUERY, + SlowUserQueryDetector.ISSUE_SLOW_USER_INFO_QUERY + ) + .run() + .expectWarningCount(1) + .expectContains( + "UserManager.getUserInfo() is slow. " + "Use UserTracker.getUserInfo() instead." + ) + } + + @Test + fun testUserTrackerGetUserId() { + lint() + .files( + TestFiles.java( + """ + package test.pkg; + import com.android.systemui.settings.UserTracker; + + public class TestClass3 { + public void quicklyGetUserId(UserTracker userTracker) { + userTracker.getUserId(); + } + } + """ + ) + .indented(), + *stubs + ) + .issues( + SlowUserQueryDetector.ISSUE_SLOW_USER_ID_QUERY, + SlowUserQueryDetector.ISSUE_SLOW_USER_INFO_QUERY + ) + .run() + .expectClean() + } + + @Test + fun testUserTrackerGetUserInfo() { + lint() + .files( + TestFiles.java( + """ + package test.pkg; + import com.android.systemui.settings.UserTracker; + + public class TestClass4 { + public void quicklyGetUserId(UserTracker userTracker) { + userTracker.getUserInfo(); + } + } + """ + ) + .indented(), + *stubs + ) + .issues( + SlowUserQueryDetector.ISSUE_SLOW_USER_ID_QUERY, + SlowUserQueryDetector.ISSUE_SLOW_USER_INFO_QUERY + ) + .run() + .expectClean() + } + + private val activityManagerStub: TestFile = + java( + """ + package android.app; + + public class ActivityManager { + public static int getCurrentUser() {}; + } + """ + ) + + private val userManagerStub: TestFile = + java( + """ + package android.os; + import android.content.pm.UserInfo; + import android.annotation.UserIdInt; + + public class UserManager { + public UserInfo getUserInfo(@UserIdInt int userId) {}; + } + """ + ) + + private val userIdIntStub: TestFile = + java( + """ + package android.annotation; + + public @interface UserIdInt {} + """ + ) + + private val userInfoStub: TestFile = + java( + """ + package android.content.pm; + + public class UserInfo {} + """ + ) + + private val userTrackerStub: TestFile = + java( + """ + package com.android.systemui.settings; + import android.content.pm.UserInfo; + + public interface UserTracker { + public int getUserId(); + public UserInfo getUserInfo(); + } + """ + ) + + private val stubs = + arrayOf(activityManagerStub, userManagerStub, userIdIntStub, userInfoStub, userTrackerStub) +} diff --git a/packages/SystemUI/compose/core/src/com/android/systemui/compose/SystemUiButtons.kt b/packages/SystemUI/compose/core/src/com/android/systemui/compose/SystemUiButtons.kt new file mode 100644 index 000000000000..496f4b3460f7 --- /dev/null +++ b/packages/SystemUI/compose/core/src/com/android/systemui/compose/SystemUiButtons.kt @@ -0,0 +1,110 @@ +/* + * 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.compose + +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.RowScope +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.ButtonColors +import androidx.compose.material3.ButtonDefaults +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import com.android.systemui.compose.theme.LocalAndroidColorScheme + +@Composable +fun SysUiButton( + onClick: () -> Unit, + modifier: Modifier = Modifier, + enabled: Boolean = true, + content: @Composable RowScope.() -> Unit, +) { + androidx.compose.material3.Button( + modifier = modifier.padding(vertical = 6.dp).height(36.dp), + colors = filledButtonColors(), + contentPadding = ButtonPaddings, + onClick = onClick, + enabled = enabled, + ) { + content() + } +} + +@Composable +fun SysUiOutlinedButton( + onClick: () -> Unit, + modifier: Modifier = Modifier, + enabled: Boolean = true, + content: @Composable RowScope.() -> Unit, +) { + androidx.compose.material3.OutlinedButton( + modifier = modifier.padding(vertical = 6.dp).height(36.dp), + enabled = enabled, + colors = outlineButtonColors(), + border = outlineButtonBorder(), + contentPadding = ButtonPaddings, + onClick = onClick, + ) { + content() + } +} + +@Composable +fun SysUiTextButton( + onClick: () -> Unit, + modifier: Modifier = Modifier, + enabled: Boolean = true, + content: @Composable RowScope.() -> Unit, +) { + androidx.compose.material3.TextButton( + onClick = onClick, + modifier = modifier, + enabled = enabled, + content = content, + ) +} + +private val ButtonPaddings = PaddingValues(horizontal = 16.dp, vertical = 8.dp) + +@Composable +private fun filledButtonColors(): ButtonColors { + val colors = LocalAndroidColorScheme.current + return ButtonDefaults.buttonColors( + containerColor = colors.colorAccentPrimary, + contentColor = colors.textColorOnAccent, + ) +} + +@Composable +private fun outlineButtonColors(): ButtonColors { + val colors = LocalAndroidColorScheme.current + return ButtonDefaults.outlinedButtonColors( + contentColor = colors.textColorPrimary, + ) +} + +@Composable +private fun outlineButtonBorder(): BorderStroke { + val colors = LocalAndroidColorScheme.current + return BorderStroke( + width = 1.dp, + color = colors.colorAccentPrimaryVariant, + ) +} diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/common/ui/compose/TextExt.kt b/packages/SystemUI/compose/features/src/com/android/systemui/common/ui/compose/TextExt.kt new file mode 100644 index 000000000000..e1f73e304b9e --- /dev/null +++ b/packages/SystemUI/compose/features/src/com/android/systemui/common/ui/compose/TextExt.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.common.ui.compose + +import androidx.compose.runtime.Composable +import androidx.compose.ui.res.stringResource +import com.android.systemui.common.shared.model.Text + +/** Returns the loaded [String] or `null` if there isn't one. */ +@Composable +fun Text.load(): String? { + return when (this) { + is Text.Loaded -> text + is Text.Resource -> stringResource(res) + } +} diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/user/ui/compose/UserSwitcherScreen.kt b/packages/SystemUI/compose/features/src/com/android/systemui/user/ui/compose/UserSwitcherScreen.kt new file mode 100644 index 000000000000..3175dcfa092b --- /dev/null +++ b/packages/SystemUI/compose/features/src/com/android/systemui/user/ui/compose/UserSwitcherScreen.kt @@ -0,0 +1,423 @@ +/* + * 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.user.ui.compose + +import android.graphics.Bitmap +import android.graphics.Canvas +import android.graphics.drawable.Drawable +import androidx.appcompat.content.res.AppCompatResources +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.heightIn +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.sizeIn +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material3.DropdownMenu +import androidx.compose.material3.DropdownMenuItem +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.alpha +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.asImageBitmap +import androidx.compose.ui.graphics.painter.ColorPainter +import androidx.compose.ui.graphics.toArgb +import androidx.compose.ui.platform.LocalConfiguration +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.res.colorResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp +import com.android.systemui.common.ui.compose.load +import com.android.systemui.compose.SysUiOutlinedButton +import com.android.systemui.compose.SysUiTextButton +import com.android.systemui.compose.features.R +import com.android.systemui.compose.theme.LocalAndroidColorScheme +import com.android.systemui.user.ui.viewmodel.UserActionViewModel +import com.android.systemui.user.ui.viewmodel.UserSwitcherViewModel +import com.android.systemui.user.ui.viewmodel.UserViewModel +import java.lang.Integer.min +import kotlin.math.ceil + +@Composable +fun UserSwitcherScreen( + viewModel: UserSwitcherViewModel, + onFinished: () -> Unit, + modifier: Modifier = Modifier, +) { + val isFinishRequested: Boolean by viewModel.isFinishRequested.collectAsState(false) + val users: List<UserViewModel> by viewModel.users.collectAsState(emptyList()) + val maxUserColumns: Int by viewModel.maximumUserColumns.collectAsState(1) + val menuActions: List<UserActionViewModel> by viewModel.menu.collectAsState(emptyList()) + val isOpenMenuButtonVisible: Boolean by viewModel.isOpenMenuButtonVisible.collectAsState(false) + val isMenuVisible: Boolean by viewModel.isMenuVisible.collectAsState(false) + + UserSwitcherScreenStateless( + isFinishRequested = isFinishRequested, + users = users, + maxUserColumns = maxUserColumns, + menuActions = menuActions, + isOpenMenuButtonVisible = isOpenMenuButtonVisible, + isMenuVisible = isMenuVisible, + onMenuClosed = viewModel::onMenuClosed, + onOpenMenuButtonClicked = viewModel::onOpenMenuButtonClicked, + onCancelButtonClicked = viewModel::onCancelButtonClicked, + onFinished = { + onFinished() + viewModel.onFinished() + }, + modifier = modifier, + ) +} + +@Composable +private fun UserSwitcherScreenStateless( + isFinishRequested: Boolean, + users: List<UserViewModel>, + maxUserColumns: Int, + menuActions: List<UserActionViewModel>, + isOpenMenuButtonVisible: Boolean, + isMenuVisible: Boolean, + onMenuClosed: () -> Unit, + onOpenMenuButtonClicked: () -> Unit, + onCancelButtonClicked: () -> Unit, + onFinished: () -> Unit, + modifier: Modifier = Modifier, +) { + LaunchedEffect(isFinishRequested) { + if (isFinishRequested) { + onFinished() + } + } + + Box( + modifier = + modifier + .fillMaxSize() + .padding( + horizontal = 60.dp, + vertical = 40.dp, + ), + ) { + UserGrid( + users = users, + maxUserColumns = maxUserColumns, + modifier = Modifier.align(Alignment.Center), + ) + + Buttons( + menuActions = menuActions, + isOpenMenuButtonVisible = isOpenMenuButtonVisible, + isMenuVisible = isMenuVisible, + onMenuClosed = onMenuClosed, + onOpenMenuButtonClicked = onOpenMenuButtonClicked, + onCancelButtonClicked = onCancelButtonClicked, + modifier = Modifier.align(Alignment.BottomEnd), + ) + } +} + +@Composable +private fun UserGrid( + users: List<UserViewModel>, + maxUserColumns: Int, + modifier: Modifier = Modifier, +) { + Column( + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(44.dp), + modifier = modifier, + ) { + val rowCount = ceil(users.size / maxUserColumns.toFloat()).toInt() + (0 until rowCount).forEach { rowIndex -> + Row( + horizontalArrangement = Arrangement.spacedBy(64.dp), + modifier = modifier, + ) { + val fromIndex = rowIndex * maxUserColumns + val toIndex = min(users.size, (rowIndex + 1) * maxUserColumns) + users.subList(fromIndex, toIndex).forEach { user -> + UserItem( + viewModel = user, + ) + } + } + } + } +} + +@Composable +private fun UserItem( + viewModel: UserViewModel, +) { + val onClicked = viewModel.onClicked + Column( + horizontalAlignment = Alignment.CenterHorizontally, + modifier = + if (onClicked != null) { + Modifier.clickable { onClicked() } + } else { + Modifier + } + .alpha(viewModel.alpha), + ) { + Box { + UserItemBackground(modifier = Modifier.align(Alignment.Center).size(222.dp)) + + UserItemIcon( + image = viewModel.image, + isSelectionMarkerVisible = viewModel.isSelectionMarkerVisible, + modifier = Modifier.align(Alignment.Center).size(222.dp) + ) + } + + // User name + val text = viewModel.name.load() + if (text != null) { + // We use the box to center-align the text vertically as that is not possible with Text + // alone. + Box( + modifier = Modifier.size(width = 222.dp, height = 48.dp), + ) { + Text( + text = text, + style = MaterialTheme.typography.titleLarge, + color = colorResource(com.android.internal.R.color.system_neutral1_50), + maxLines = 1, + overflow = TextOverflow.Ellipsis, + modifier = Modifier.align(Alignment.Center), + ) + } + } + } +} + +@Composable +private fun UserItemBackground( + modifier: Modifier = Modifier, +) { + Image( + painter = ColorPainter(LocalAndroidColorScheme.current.colorBackground), + contentDescription = null, + modifier = modifier.clip(CircleShape), + ) +} + +@Composable +private fun UserItemIcon( + image: Drawable, + isSelectionMarkerVisible: Boolean, + modifier: Modifier = Modifier, +) { + Image( + bitmap = image.toBitmap().asImageBitmap(), + contentDescription = null, + modifier = + if (isSelectionMarkerVisible) { + // Draws a ring + modifier.border( + width = 8.dp, + color = LocalAndroidColorScheme.current.colorAccentPrimary, + shape = CircleShape, + ) + } else { + modifier + } + .padding(16.dp) + .clip(CircleShape) + ) +} + +@Composable +private fun Buttons( + menuActions: List<UserActionViewModel>, + isOpenMenuButtonVisible: Boolean, + isMenuVisible: Boolean, + onMenuClosed: () -> Unit, + onOpenMenuButtonClicked: () -> Unit, + onCancelButtonClicked: () -> Unit, + modifier: Modifier = Modifier, +) { + Row( + modifier = modifier, + ) { + // Cancel button. + SysUiTextButton( + onClick = onCancelButtonClicked, + ) { + Text(stringResource(R.string.cancel)) + } + + // "Open menu" button. + if (isOpenMenuButtonVisible) { + Spacer(modifier = Modifier.width(8.dp)) + // To properly use a DropdownMenu in Compose, we need to wrap the button that opens it + // and the menu itself in a Box. + Box { + SysUiOutlinedButton( + onClick = onOpenMenuButtonClicked, + ) { + Text(stringResource(R.string.add)) + } + Menu( + viewModel = menuActions, + isMenuVisible = isMenuVisible, + onMenuClosed = onMenuClosed, + ) + } + } + } +} + +@Composable +private fun Menu( + viewModel: List<UserActionViewModel>, + isMenuVisible: Boolean, + onMenuClosed: () -> Unit, + modifier: Modifier = Modifier, +) { + val maxItemWidth = LocalConfiguration.current.screenWidthDp.dp / 4 + DropdownMenu( + expanded = isMenuVisible, + onDismissRequest = onMenuClosed, + modifier = + modifier.background( + color = MaterialTheme.colorScheme.inverseOnSurface, + ), + ) { + viewModel.forEachIndexed { index, action -> + MenuItem( + viewModel = action, + onClicked = { action.onClicked() }, + topPadding = + if (index == 0) { + 16.dp + } else { + 0.dp + }, + bottomPadding = + if (index == viewModel.size - 1) { + 16.dp + } else { + 0.dp + }, + modifier = Modifier.sizeIn(maxWidth = maxItemWidth), + ) + } + } +} + +@Composable +private fun MenuItem( + viewModel: UserActionViewModel, + onClicked: () -> Unit, + topPadding: Dp, + bottomPadding: Dp, + modifier: Modifier = Modifier, +) { + val context = LocalContext.current + val density = LocalDensity.current + + val icon = + remember(viewModel.iconResourceId) { + val drawable = + checkNotNull(AppCompatResources.getDrawable(context, viewModel.iconResourceId)) + drawable + .toBitmap( + size = with(density) { 20.dp.toPx() }.toInt(), + tintColor = Color.White, + ) + .asImageBitmap() + } + + DropdownMenuItem( + text = { + Text( + text = stringResource(viewModel.textResourceId), + style = MaterialTheme.typography.bodyMedium, + ) + }, + onClick = onClicked, + leadingIcon = { + Spacer(modifier = Modifier.width(10.dp)) + Image( + bitmap = icon, + contentDescription = null, + ) + }, + modifier = + modifier + .heightIn( + min = 56.dp, + ) + .padding( + start = 18.dp, + end = 65.dp, + top = topPadding, + bottom = bottomPadding, + ), + ) +} + +/** + * Converts the [Drawable] to a [Bitmap]. + * + * Note that this is a relatively memory-heavy operation as it allocates a whole bitmap and draws + * the `Drawable` onto it. Use sparingly and with care. + */ +private fun Drawable.toBitmap( + size: Int? = null, + tintColor: Color? = null, +): Bitmap { + val bitmap = + if (intrinsicWidth <= 0 || intrinsicHeight <= 0) { + Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888) + } else { + Bitmap.createBitmap( + size ?: intrinsicWidth, + size ?: intrinsicHeight, + Bitmap.Config.ARGB_8888 + ) + } + val canvas = Canvas(bitmap) + setBounds(0, 0, canvas.width, canvas.height) + if (tintColor != null) { + setTint(tintColor.toArgb()) + } + draw(canvas) + return bitmap +} diff --git a/packages/SystemUI/compose/gallery/res/drawable/kitten1.jpeg b/packages/SystemUI/compose/gallery/res/drawable/kitten1.jpeg Binary files differnew file mode 100644 index 000000000000..6241b0b44bb6 --- /dev/null +++ b/packages/SystemUI/compose/gallery/res/drawable/kitten1.jpeg diff --git a/packages/SystemUI/compose/gallery/res/drawable/kitten2.jpeg b/packages/SystemUI/compose/gallery/res/drawable/kitten2.jpeg Binary files differnew file mode 100644 index 000000000000..870ef13ee2d9 --- /dev/null +++ b/packages/SystemUI/compose/gallery/res/drawable/kitten2.jpeg diff --git a/packages/SystemUI/compose/gallery/res/drawable/kitten3.jpeg b/packages/SystemUI/compose/gallery/res/drawable/kitten3.jpeg Binary files differnew file mode 100644 index 000000000000..bb7261c10033 --- /dev/null +++ b/packages/SystemUI/compose/gallery/res/drawable/kitten3.jpeg diff --git a/packages/SystemUI/compose/gallery/res/drawable/kitten4.jpeg b/packages/SystemUI/compose/gallery/res/drawable/kitten4.jpeg Binary files differnew file mode 100644 index 000000000000..e34b7ddf58ce --- /dev/null +++ b/packages/SystemUI/compose/gallery/res/drawable/kitten4.jpeg diff --git a/packages/SystemUI/compose/gallery/res/drawable/kitten5.jpeg b/packages/SystemUI/compose/gallery/res/drawable/kitten5.jpeg Binary files differnew file mode 100644 index 000000000000..9cde24be59ef --- /dev/null +++ b/packages/SystemUI/compose/gallery/res/drawable/kitten5.jpeg diff --git a/packages/SystemUI/compose/gallery/res/drawable/kitten6.jpeg b/packages/SystemUI/compose/gallery/res/drawable/kitten6.jpeg Binary files differnew file mode 100644 index 000000000000..17825b639a26 --- /dev/null +++ b/packages/SystemUI/compose/gallery/res/drawable/kitten6.jpeg diff --git a/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/ButtonsScreen.kt b/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/ButtonsScreen.kt new file mode 100644 index 000000000000..881a1def113a --- /dev/null +++ b/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/ButtonsScreen.kt @@ -0,0 +1,77 @@ +/* + * 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(ExperimentalMaterial3Api::class) + +package com.android.systemui.compose.gallery + +import androidx.compose.foundation.layout.Column +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.android.systemui.compose.SysUiButton +import com.android.systemui.compose.SysUiOutlinedButton +import com.android.systemui.compose.SysUiTextButton + +@Composable +fun ButtonsScreen( + modifier: Modifier = Modifier, +) { + Column( + modifier = modifier, + ) { + SysUiButton( + onClick = {}, + ) { + Text("SysUiButton") + } + + SysUiButton( + onClick = {}, + enabled = false, + ) { + Text("SysUiButton - disabled") + } + + SysUiOutlinedButton( + onClick = {}, + ) { + Text("SysUiOutlinedButton") + } + + SysUiOutlinedButton( + onClick = {}, + enabled = false, + ) { + Text("SysUiOutlinedButton - disabled") + } + + SysUiTextButton( + onClick = {}, + ) { + Text("SysUiTextButton") + } + + SysUiTextButton( + onClick = {}, + enabled = false, + ) { + Text("SysUiTextButton - disabled") + } + } +} diff --git a/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/GalleryApp.kt b/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/GalleryApp.kt index bb98fb350a2e..6805bf83dff4 100644 --- a/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/GalleryApp.kt +++ b/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/GalleryApp.kt @@ -28,24 +28,25 @@ import com.android.systemui.compose.theme.SystemUITheme /** The gallery app screens. */ object GalleryAppScreens { - val Typography = ChildScreen("typography") { TypographyScreen() } - val MaterialColors = ChildScreen("material_colors") { MaterialColorsScreen() } - val AndroidColors = ChildScreen("android_colors") { AndroidColorsScreen() } - val ExampleFeature = ChildScreen("example_feature") { ExampleFeatureScreen() } + private val Typography = ChildScreen("typography") { TypographyScreen() } + private val MaterialColors = ChildScreen("material_colors") { MaterialColorsScreen() } + private val AndroidColors = ChildScreen("android_colors") { AndroidColorsScreen() } + private val Buttons = ChildScreen("buttons") { ButtonsScreen() } + private val ExampleFeature = ChildScreen("example_feature") { ExampleFeatureScreen() } - val PeopleEmpty = + private val PeopleEmpty = ChildScreen("people_empty") { navController -> EmptyPeopleScreen(onResult = { navController.popBackStack() }) } - val PeopleFew = + private val PeopleFew = ChildScreen("people_few") { navController -> FewPeopleScreen(onResult = { navController.popBackStack() }) } - val PeopleFull = + private val PeopleFull = ChildScreen("people_full") { navController -> FullPeopleScreen(onResult = { navController.popBackStack() }) } - val People = + private val People = ParentScreen( "people", mapOf( @@ -54,6 +55,52 @@ object GalleryAppScreens { "Full" to PeopleFull, ) ) + private val UserSwitcherSingleUser = + ChildScreen("user_switcher_single") { navController -> + UserSwitcherScreen( + userCount = 1, + onFinished = navController::popBackStack, + ) + } + private val UserSwitcherThreeUsers = + ChildScreen("user_switcher_three") { navController -> + UserSwitcherScreen( + userCount = 3, + onFinished = navController::popBackStack, + ) + } + private val UserSwitcherFourUsers = + ChildScreen("user_switcher_four") { navController -> + UserSwitcherScreen( + userCount = 4, + onFinished = navController::popBackStack, + ) + } + private val UserSwitcherFiveUsers = + ChildScreen("user_switcher_five") { navController -> + UserSwitcherScreen( + userCount = 5, + onFinished = navController::popBackStack, + ) + } + private val UserSwitcherSixUsers = + ChildScreen("user_switcher_six") { navController -> + UserSwitcherScreen( + userCount = 6, + onFinished = navController::popBackStack, + ) + } + private val UserSwitcher = + ParentScreen( + "user_switcher", + mapOf( + "Single" to UserSwitcherSingleUser, + "Three" to UserSwitcherThreeUsers, + "Four" to UserSwitcherFourUsers, + "Five" to UserSwitcherFiveUsers, + "Six" to UserSwitcherSixUsers, + ) + ) val Home = ParentScreen( @@ -63,7 +110,9 @@ object GalleryAppScreens { "Material colors" to MaterialColors, "Android colors" to AndroidColors, "Example feature" to ExampleFeature, + "Buttons" to Buttons, "People" to People, + "User Switcher" to UserSwitcher, ) ) } diff --git a/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/UserSwitcherScreen.kt b/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/UserSwitcherScreen.kt new file mode 100644 index 000000000000..fe9707d22684 --- /dev/null +++ b/packages/SystemUI/compose/gallery/src/com/android/systemui/compose/gallery/UserSwitcherScreen.kt @@ -0,0 +1,35 @@ +/* + * 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.compose.gallery + +import androidx.compose.runtime.Composable +import androidx.compose.ui.platform.LocalContext +import com.android.systemui.user.Fakes.fakeUserSwitcherViewModel +import com.android.systemui.user.ui.compose.UserSwitcherScreen + +@Composable +fun UserSwitcherScreen( + userCount: Int, + onFinished: () -> Unit, +) { + val context = LocalContext.current.applicationContext + UserSwitcherScreen( + viewModel = fakeUserSwitcherViewModel(context, userCount = userCount), + onFinished = onFinished, + ) +} diff --git a/packages/SystemUI/compose/gallery/src/com/android/systemui/qs/footer/Fakes.kt b/packages/SystemUI/compose/gallery/src/com/android/systemui/qs/footer/Fakes.kt index 11477f9d833b..6588e22721fb 100644 --- a/packages/SystemUI/compose/gallery/src/com/android/systemui/qs/footer/Fakes.kt +++ b/packages/SystemUI/compose/gallery/src/com/android/systemui/qs/footer/Fakes.kt @@ -83,7 +83,11 @@ private fun fakeFooterActionsViewModel( flowOf( securityText?.let { text -> SecurityButtonConfig( - icon = Icon.Resource(R.drawable.ic_info_outline), + icon = + Icon.Resource( + R.drawable.ic_info_outline, + contentDescription = null, + ), text = text, isClickable = securityClickable, ) diff --git a/packages/SystemUI/compose/gallery/src/com/android/systemui/user/Fakes.kt b/packages/SystemUI/compose/gallery/src/com/android/systemui/user/Fakes.kt new file mode 100644 index 000000000000..91a73ea16dc4 --- /dev/null +++ b/packages/SystemUI/compose/gallery/src/com/android/systemui/user/Fakes.kt @@ -0,0 +1,116 @@ +/* + * 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.user + +import android.content.Context +import androidx.appcompat.content.res.AppCompatResources +import com.android.systemui.common.shared.model.Text +import com.android.systemui.compose.gallery.R +import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository +import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor +import com.android.systemui.power.data.repository.FakePowerRepository +import com.android.systemui.power.domain.interactor.PowerInteractor +import com.android.systemui.user.data.repository.FakeUserRepository +import com.android.systemui.user.domain.interactor.UserInteractor +import com.android.systemui.user.shared.model.UserActionModel +import com.android.systemui.user.shared.model.UserModel +import com.android.systemui.user.ui.viewmodel.UserSwitcherViewModel +import com.android.systemui.util.mockito.mock + +object Fakes { + private val USER_TINT_COLORS = + arrayOf( + 0x000000, + 0x0000ff, + 0x00ff00, + 0x00ffff, + 0xff0000, + 0xff00ff, + 0xffff00, + 0xffffff, + ) + + fun fakeUserSwitcherViewModel( + context: Context, + userCount: Int, + ): UserSwitcherViewModel { + return UserSwitcherViewModel.Factory( + userInteractor = + UserInteractor( + repository = + FakeUserRepository().apply { + setUsers( + (0 until userCount).map { index -> + UserModel( + id = index, + name = + Text.Loaded( + when (index % 6) { + 0 -> "Ross Geller" + 1 -> "Phoebe Buffay" + 2 -> "Monica Geller" + 3 -> "Rachel Greene" + 4 -> "Chandler Bing" + else -> "Joey Tribbiani" + } + ), + image = + checkNotNull( + AppCompatResources.getDrawable( + context, + when (index % 6) { + 0 -> R.drawable.kitten1 + 1 -> R.drawable.kitten2 + 2 -> R.drawable.kitten3 + 3 -> R.drawable.kitten4 + 4 -> R.drawable.kitten5 + else -> R.drawable.kitten6 + }, + ) + ), + isSelected = index == 0, + isSelectable = true, + ) + } + ) + setActions( + UserActionModel.values().mapNotNull { + if (it == UserActionModel.NAVIGATE_TO_USER_MANAGEMENT) { + null + } else { + it + } + } + ) + }, + controller = mock(), + activityStarter = mock(), + keyguardInteractor = + KeyguardInteractor( + repository = + FakeKeyguardRepository().apply { setKeyguardShowing(false) }, + ), + ), + powerInteractor = + PowerInteractor( + repository = FakePowerRepository(), + ) + ) + .create(UserSwitcherViewModel::class.java) + } +} diff --git a/packages/SystemUI/ktfmt_includes.txt b/packages/SystemUI/ktfmt_includes.txt index 51cc1954299f..818248439d0a 100644 --- a/packages/SystemUI/ktfmt_includes.txt +++ b/packages/SystemUI/ktfmt_includes.txt @@ -240,8 +240,6 @@ -packages/SystemUI/src/com/android/systemui/media/nearby/NearbyMediaDevicesManager.kt -packages/SystemUI/src/com/android/systemui/media/taptotransfer/MediaTttCommandLineHelper.kt -packages/SystemUI/src/com/android/systemui/media/taptotransfer/MediaTttFlags.kt --packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/ChipInfoCommon.kt --packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommon.kt -packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttLogger.kt -packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/ChipStateReceiver.kt -packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt @@ -500,7 +498,6 @@ -packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherContainer.kt -packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherController.kt -packages/SystemUI/src/com/android/systemui/statusbar/phone/userswitcher/StatusBarUserSwitcherFeatureController.kt --packages/SystemUI/src/com/android/systemui/statusbar/pipeline/ConnectivityInfoProcessor.kt -packages/SystemUI/src/com/android/systemui/statusbar/pipeline/dagger/StatusBarPipelineModule.kt -packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityPipelineLogger.kt -packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/data/model/WifiActivityModel.kt @@ -529,6 +526,8 @@ -packages/SystemUI/src/com/android/systemui/statusbar/tv/VpnStatusObserver.kt -packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowModule.kt -packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowStateController.kt +-packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewInfo.kt +-packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayController.kt -packages/SystemUI/src/com/android/systemui/toast/ToastDefaultAnimation.kt -packages/SystemUI/src/com/android/systemui/toast/ToastLogger.kt -packages/SystemUI/src/com/android/systemui/tv/TVSystemUICoreStartableModule.kt @@ -677,7 +676,6 @@ -packages/SystemUI/tests/src/com/android/systemui/media/muteawait/MediaMuteAwaitConnectionManagerTest.kt -packages/SystemUI/tests/src/com/android/systemui/media/nearby/NearbyMediaDevicesManagerTest.kt -packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/MediaTttCommandLineHelperTest.kt --packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommonTest.kt -packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttLoggerTest.kt -packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt -packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSenderTest.kt @@ -834,6 +832,7 @@ -packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/VariableDateViewControllerTest.kt -packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/WalletControllerImplTest.kt -packages/SystemUI/tests/src/com/android/systemui/statusbar/window/StatusBarWindowStateControllerTest.kt +-packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayControllerTest.kt -packages/SystemUI/tests/src/com/android/systemui/unfold/FoldStateLoggingProviderTest.kt -packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldLatencyTrackerTest.kt -packages/SystemUI/tests/src/com/android/systemui/unfold/UnfoldTransitionWallpaperControllerTest.kt diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java index 1aaf19e8793f..c50340cfd247 100644 --- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/FalsingManager.java @@ -147,10 +147,10 @@ public interface FalsingManager { } /** - * Listener that is alerted when a double tap is required to confirm a single tap. + * Listener that is alerted when an additional tap is required to confirm a single tap. **/ interface FalsingTapListener { - void onDoubleTapRequired(); + void onAdditionalTapRequired(); } /** Passed to {@link FalsingManager#onProximityEvent}. */ diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QS.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QS.java index 57193e7060f9..436145ec0692 100644 --- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QS.java +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QS.java @@ -16,6 +16,8 @@ package com.android.systemui.plugins.qs; import android.view.View; +import androidx.annotation.FloatRange; + import com.android.systemui.plugins.FragmentBase; import com.android.systemui.plugins.annotations.DependsOn; import com.android.systemui.plugins.annotations.ProvidesInterface; @@ -107,10 +109,24 @@ public interface QS extends FragmentBase { void setInSplitShade(boolean shouldTranslate); /** - * Set the amount of pixels we have currently dragged down if we're transitioning to the full - * shade. 0.0f means we're not transitioning yet. + * Sets the progress of the transition to full shade on the lockscreen. + * + * @param isTransitioningToFullShade + * whether the transition to full shade is in progress. This might be {@code true}, even + * though {@code qsTransitionFraction} is still 0. + * The reason for that is that on some device configurations, the QS transition has a + * start delay compared to the overall transition. + * + * @param qsTransitionFraction + * the fraction of the QS transition progress, from 0 to 1. + * + * @param qsSquishinessFraction + * the fraction of the QS "squish" transition progress, from 0 to 1. */ - default void setTransitionToFullShadeAmount(float pxAmount, float progress) {} + default void setTransitionToFullShadeProgress( + boolean isTransitioningToFullShade, + @FloatRange(from = 0.0, to = 1.0) float qsTransitionFraction, + @FloatRange(from = 0.0, to = 1.0) float qsSquishinessFraction) {} /** * A rounded corner clipping that makes QS feel as if it were behind everything. @@ -140,6 +156,12 @@ public interface QS extends FragmentBase { default void setOverScrollAmount(int overScrollAmount) {} /** + * Sets whether the notification panel is using the full width of the screen. Typically true on + * small screens and false on large screens. + */ + void setIsNotificationPanelFullWidth(boolean isFullWidth); + + /** * Callback for when QSPanel container is scrolled */ @ProvidesInterface(version = ScrollListener.VERSION) diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSContainerController.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSContainerController.kt index 8bf982d360a1..9c7fbe8842bc 100644 --- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSContainerController.kt +++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QSContainerController.kt @@ -3,7 +3,9 @@ package com.android.systemui.plugins.qs interface QSContainerController { fun setCustomizerAnimating(animating: Boolean) - fun setCustomizerShowing(showing: Boolean) + fun setCustomizerShowing(showing: Boolean) = setCustomizerShowing(showing, 0L) + + fun setCustomizerShowing(showing: Boolean, animationDuration: Long) fun setDetailShowing(showing: Boolean) -}
\ No newline at end of file +} diff --git a/packages/SystemUI/res-keyguard/drawable/kg_bouncer_secondary_button.xml b/packages/SystemUI/res-keyguard/drawable/kg_bouncer_secondary_button.xml new file mode 100644 index 000000000000..732fc57dbded --- /dev/null +++ b/packages/SystemUI/res-keyguard/drawable/kg_bouncer_secondary_button.xml @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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. + --> + +<inset xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:androidprv="http://schemas.android.com/apk/prv/res/android" + android:insetTop="6dp" + android:insetBottom="6dp"> + <ripple android:color="?android:attr/colorControlHighlight"> + <item android:id="@android:id/mask"> + <shape android:shape="rectangle"> + <solid android:color="?android:attr/textColorSecondary"/> + <corners android:radius="24dp"/> + </shape> + </item> + <item> + <shape android:shape="rectangle"> + <corners android:radius="24dp"/> + <solid android:color="@android:color/transparent"/> + <stroke android:color="?androidprv:attr/colorAccentTertiary" + android:width="1dp" + /> + <padding android:left="16dp" + android:top="12dp" + android:right="16dp" + android:bottom="12dp"/> + </shape> + </item> + </ripple> +</inset> diff --git a/packages/SystemUI/res-keyguard/drawable/qs_invert_colors_icon_off.xml b/packages/SystemUI/res-keyguard/drawable/qs_invert_colors_icon_off.xml new file mode 100644 index 000000000000..a34712386d52 --- /dev/null +++ b/packages/SystemUI/res-keyguard/drawable/qs_invert_colors_icon_off.xml @@ -0,0 +1,109 @@ +<?xml version="1.0" encoding="utf-8"?><!-- + ~ 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 + --> +<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:aapt="http://schemas.android.com/aapt"> + <target android:name="_R_G_L_0_G_D_0_P_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:duration="17" + android:propertyName="pathData" + android:startOffset="0" + android:valueFrom="M7.38 -0.28 C5.69,-2.81 1.5,-8.5 0.01,-7.32 C0.03,-6.22 -0.06,6.16 -0.06,7.78 C1.56,7.81 5.44,7.19 7.37,2.06 C7.37,1.21 7.35,1.69 7.35,1 C7.35,0.09 7.38,0.59 7.38,-0.28c " + android:valueTo="M6 -2.38 C1.81,-6.69 -0.5,-10 -1.72,-7.1 C-1.73,-6.22 -1.73,5.88 -1.7,7.16 C0.25,8.45 3,7.75 5.47,4.91 C6.33,3.91 7.21,2.42 7.24,1.13 C7.26,-0.05 6.87,-1.49 6,-2.38c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="33" + android:propertyName="pathData" + android:startOffset="17" + android:valueFrom="M6 -2.38 C1.81,-6.69 -0.5,-10 -1.72,-7.1 C-1.73,-6.22 -1.73,5.88 -1.7,7.16 C0.25,8.45 3,7.75 5.47,4.91 C6.33,3.91 7.21,2.42 7.24,1.13 C7.26,-0.05 6.87,-1.49 6,-2.38c " + android:valueTo="M4.94 -3.95 C-0.31,-9.06 0.52,-9.42 -5.75,-3.22 C-8.31,-0.69 -7.05,3 -6.94,3.22 C-3.63,9.31 2.63,9.5 5.94,4.59 C6.61,3.6 7.43,1.16 7.12,0 C6.72,-1.45 6.01,-2.9 4.94,-3.95c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="67" + android:propertyName="pathData" + android:startOffset="50" + android:valueFrom="M4.94 -3.95 C-0.31,-9.06 0.52,-9.42 -5.75,-3.22 C-8.31,-0.69 -7.05,3 -6.94,3.22 C-3.63,9.31 2.63,9.5 5.94,4.59 C6.61,3.6 7.43,1.16 7.12,0 C6.72,-1.45 6.01,-2.9 4.94,-3.95c " + android:valueTo="M3.07 -5.83 C-0.44,-10.25 -2.56,-6.87 -6.11,-2.6 C-7.03,-1.49 -7.23,1.85 -7.18,2.06 C-5.84,7.25 -0.33,9.23 3.14,6.75 C3.17,5.1 3.17,3.58 3.22,0 C3.25,-3.04 3.1,-4.1 3.07,-5.83c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="83" + android:propertyName="pathData" + android:startOffset="117" + android:valueFrom="M3.07 -5.83 C-0.44,-10.25 -2.56,-6.87 -6.11,-2.6 C-7.03,-1.49 -7.23,1.85 -7.18,2.06 C-5.84,7.25 -0.33,9.23 3.14,6.75 C3.17,5.1 3.17,3.58 3.22,0 C3.25,-3.04 3.1,-4.1 3.07,-5.83c " + android:valueTo="M0 -8.18 C-1.81,-7.06 -3.89,-5.21 -5.95,-2.81 C-7.56,-0.94 -7.37,0.88 -7.37,1.09 C-7.37,6.31 -2.19,7.99 0,7.99 C0,6.34 -0.01,3.91 -0.01,0 C-0.01,-3.91 0,-6 0,-8.18c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.2,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="time_group"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:duration="433" + android:propertyName="translateX" + android:startOffset="0" + android:valueFrom="0" + android:valueTo="1" + android:valueType="floatType" /> + </set> + </aapt:attr> + </target> + <aapt:attr name="android:drawable"> + <vector + android:width="24dp" + android:height="24dp" + android:viewportHeight="24" + android:viewportWidth="24"> + <group android:name="_R_G"> + <group + android:name="_R_G_L_0_G" + android:translateX="12" + android:translateY="12"> + <path + android:name="_R_G_L_0_G_D_0_P_0" + android:fillAlpha="1" + android:fillColor="#edf2eb" + android:fillType="nonZero" + android:pathData=" M7.38 -0.28 C5.69,-2.81 1.5,-8.5 0.01,-7.32 C0.03,-6.22 -0.06,6.16 -0.06,7.78 C1.56,7.81 5.44,7.19 7.37,2.06 C7.37,1.21 7.35,1.69 7.35,1 C7.35,0.09 7.38,0.59 7.38,-0.28c " /> + <path + android:name="_R_G_L_0_G_D_1_P_0" + android:fillAlpha="1" + android:fillColor="#ffffff" + android:fillType="nonZero" + android:pathData=" M0 -7.19 C0,-7.19 2.93,-4.32 4.38,-2.87 C5.25,-2 5.88,-0.62 5.88,1.19 C5.88,4.5 2.8,6.97 0,7 C-2.8,7.03 -6,4.37 -6,1.13 C-6,-0.43 -5.38,-1.9 -4.25,-3.01 C-4.25,-3.01 0,-7.19 0,-7.19 M-5.65 -4.44 C-5.65,-4.44 -5.65,-4.44 -5.65,-4.44 C-7.1,-3.01 -8,-1.04 -8,1.13 C-8,5.48 -4.42,9 0,9 C4.42,9 8,5.48 8,1.13 C8,-1.04 7.1,-3.01 5.65,-4.44 C5.65,-4.44 5.65,-4.44 5.65,-4.44 C5.65,-4.44 0,-10 0,-10 C0,-10 -5.65,-4.44 -5.65,-4.44c " /> + </group> + </group> + <group android:name="time_group" /> + </vector> + </aapt:attr> +</animated-vector> diff --git a/packages/SystemUI/res-keyguard/drawable/qs_invert_colors_icon_on.xml b/packages/SystemUI/res-keyguard/drawable/qs_invert_colors_icon_on.xml new file mode 100644 index 000000000000..c5609d8e465b --- /dev/null +++ b/packages/SystemUI/res-keyguard/drawable/qs_invert_colors_icon_on.xml @@ -0,0 +1,109 @@ +<?xml version="1.0" encoding="utf-8"?><!-- + ~ 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 + --> +<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:aapt="http://schemas.android.com/aapt"> + <target android:name="_R_G_L_0_G_D_0_P_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:duration="100" + android:propertyName="pathData" + android:startOffset="0" + android:valueFrom="M0 -7.49 C-2.58,-7.49 -7.47,-2.59 -7.47,0.57 C-7.47,0.77 -7.37,0.88 -7.37,1.09 C-7.37,6.31 -2.19,7.55 0,7.55 C0,5.91 -0.01,3.91 -0.01,0 C-0.01,-3.91 0,-5.31 0,-7.49c " + android:valueTo="M3.11 -6.83 C-1.37,-10.12 -6.04,-3.87 -7.22,0.09 C-7.26,0.29 -7.23,1.85 -7.18,2.06 C-5.84,7.25 -0.33,9.23 3.14,6.75 C3.17,5.1 3.17,3.58 3.22,0 C3.25,-3.04 3.14,-5.1 3.11,-6.83c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="67" + android:propertyName="pathData" + android:startOffset="100" + android:valueFrom="M3.11 -6.83 C-1.37,-10.12 -6.04,-3.87 -7.22,0.09 C-7.26,0.29 -7.23,1.85 -7.18,2.06 C-5.84,7.25 -0.33,9.23 3.14,6.75 C3.17,5.1 3.17,3.58 3.22,0 C3.25,-3.04 3.14,-5.1 3.11,-6.83c " + android:valueTo="M5 -3.95 C-0.25,-9.87 -0.47,-8.74 -5,-3.63 C-7.94,-0.31 -7.05,3 -6.94,3.22 C-3.63,9.31 2.94,9.19 7,3.59 C7.06,1.94 7,3.19 7.12,0 C7.19,-2 5.06,-2.75 5,-3.95c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="67" + android:propertyName="pathData" + android:startOffset="167" + android:valueFrom="M5 -3.95 C-0.25,-9.87 -0.47,-8.74 -5,-3.63 C-7.94,-0.31 -7.05,3 -6.94,3.22 C-3.63,9.31 2.94,9.19 7,3.59 C7.06,1.94 7,3.19 7.12,0 C7.19,-2 5.06,-2.75 5,-3.95c " + android:valueTo="M4.82 -3.81 C1,-7.87 0.75,-9.37 -1.72,-7.1 C-1.73,-6.22 -1.73,5.88 -1.7,7.16 C0.25,8.45 4.38,7.38 6.4,3.22 C6.77,2.46 7,1.69 6.74,0 C6.56,-1.16 5.85,-2.71 4.82,-3.81c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="100" + android:propertyName="pathData" + android:startOffset="233" + android:valueFrom="M4.82 -3.81 C1,-7.87 0.75,-9.37 -1.72,-7.1 C-1.73,-6.22 -1.73,5.88 -1.7,7.16 C0.25,8.45 4.38,7.38 6.4,3.22 C6.77,2.46 7,1.69 6.74,0 C6.56,-1.16 5.85,-2.71 4.82,-3.81c " + android:valueTo="M5.63 -2.97 C3.65,-4.93 0.75,-8.37 0.01,-7.32 C0.03,-6.22 -0.03,5.66 -0.03,7.28 C1.59,7.31 4.13,7.94 6.31,3.44 C6.68,2.66 7,1.37 6.87,0.06 C6.77,-0.84 6.13,-2.47 5.63,-2.97c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.2,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="time_group"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:duration="433" + android:propertyName="translateX" + android:startOffset="0" + android:valueFrom="0" + android:valueTo="1" + android:valueType="floatType" /> + </set> + </aapt:attr> + </target> + <aapt:attr name="android:drawable"> + <vector + android:width="24dp" + android:height="24dp" + android:viewportHeight="24" + android:viewportWidth="24"> + <group android:name="_R_G"> + <group + android:name="_R_G_L_0_G" + android:translateX="12" + android:translateY="12"> + <path + android:name="_R_G_L_0_G_D_0_P_0" + android:fillAlpha="1" + android:fillColor="#edf2eb" + android:fillType="nonZero" + android:pathData=" M0 -7.49 C-2.58,-7.49 -7.47,-2.59 -7.47,0.57 C-7.47,0.77 -7.37,0.88 -7.37,1.09 C-7.37,6.31 -2.19,7.55 0,7.55 C0,5.91 -0.01,3.91 -0.01,0 C-0.01,-3.91 0,-5.31 0,-7.49c " /> + <path + android:name="_R_G_L_0_G_D_1_P_0" + android:fillAlpha="1" + android:fillColor="#ffffff" + android:fillType="nonZero" + android:pathData=" M0 -7.19 C0,-7.19 2.93,-4.32 4.38,-2.87 C5.25,-2 5.88,-0.62 5.88,1.19 C5.88,4.5 2.8,6.97 0,7 C-2.8,7.03 -6,4.37 -6,1.13 C-6,-0.43 -5.38,-1.9 -4.25,-3.01 C-4.25,-3.01 0,-7.19 0,-7.19 M-5.65 -4.44 C-5.65,-4.44 -5.65,-4.44 -5.65,-4.44 C-7.1,-3.01 -8,-1.04 -8,1.13 C-8,5.48 -4.42,9 0,9 C4.42,9 8,5.48 8,1.13 C8,-1.04 7.1,-3.01 5.65,-4.44 C5.65,-4.44 5.65,-4.44 5.65,-4.44 C5.65,-4.44 0,-10 0,-10 C0,-10 -5.65,-4.44 -5.65,-4.44c " /> + </group> + </group> + <group android:name="time_group" /> + </vector> + </aapt:attr> +</animated-vector> diff --git a/packages/SystemUI/res-keyguard/drawable/qs_light_dark_theme_icon_off.xml b/packages/SystemUI/res-keyguard/drawable/qs_light_dark_theme_icon_off.xml new file mode 100644 index 000000000000..5c0a7c820887 --- /dev/null +++ b/packages/SystemUI/res-keyguard/drawable/qs_light_dark_theme_icon_off.xml @@ -0,0 +1,109 @@ +<?xml version="1.0" encoding="utf-8"?><!-- + ~ 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 + --> +<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:aapt="http://schemas.android.com/aapt"> + <target android:name="_R_G_L_0_G_D_1_P_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:duration="20" + android:propertyName="pathData" + android:startOffset="0" + android:valueFrom="M7.38 -2.03 C6.38,-4.66 3.47,-7.32 0.01,-7.32 C0.03,-6.22 -0.03,5.66 -0.03,7.28 C1.59,7.31 5.22,6.17 7.37,2.06 C7.37,1.21 7.37,0.69 7.37,0 C7.37,-0.91 7.38,-1.16 7.38,-2.03c " + android:valueTo="M7.25 -2.44 C5.46,-5.86 1.53,-8.3 -1.72,-7.1 C-1.73,-6.22 -1.73,5.88 -1.7,7.16 C0.25,8.45 4.43,6.91 7.28,2.47 C7.29,1.42 7.27,1.3 7.3,0 C7.32,-1.17 7.27,-1.49 7.25,-2.44c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="40" + android:propertyName="pathData" + android:startOffset="20" + android:valueFrom="M7.25 -2.44 C5.46,-5.86 1.53,-8.3 -1.72,-7.1 C-1.73,-6.22 -1.73,5.88 -1.7,7.16 C0.25,8.45 4.43,6.91 7.28,2.47 C7.29,1.42 7.27,1.3 7.3,0 C7.32,-1.17 7.27,-1.49 7.25,-2.44c " + android:valueTo="M7.06 -3.94 C3.5,-8.81 -3.31,-9.44 -7,-3.66 C-7.12,-3.47 -7.05,3 -6.94,3.22 C-3.63,9.31 2.94,9.19 7,3.59 C7.06,1.94 7,3.19 7.12,0 C7.19,-2 7.12,-2.75 7.06,-3.94c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="40" + android:propertyName="pathData" + android:startOffset="60" + android:valueFrom="M7.06 -3.94 C3.5,-8.81 -3.31,-9.44 -7,-3.66 C-7.12,-3.47 -7.05,3 -6.94,3.22 C-3.63,9.31 2.94,9.19 7,3.59 C7.06,1.94 7,3.19 7.12,0 C7.19,-2 7.12,-2.75 7.06,-3.94c " + android:valueTo="M3.11 -6.83 C-0.23,-9.49 -6.06,-6.24 -7.23,-2.29 C-7.28,-2.09 -7.23,1.85 -7.18,2.06 C-5.84,7.25 -0.33,9.23 3.14,6.75 C3.17,5.1 3.17,3.58 3.22,0 C3.25,-3.04 3.14,-5.1 3.11,-6.83c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="100" + android:propertyName="pathData" + android:startOffset="100" + android:valueFrom="M3.11 -6.83 C-0.23,-9.49 -6.06,-6.24 -7.23,-2.29 C-7.28,-2.09 -7.23,1.85 -7.18,2.06 C-5.84,7.25 -0.33,9.23 3.14,6.75 C3.17,5.1 3.17,3.58 3.22,0 C3.25,-3.04 3.14,-5.1 3.11,-6.83c " + android:valueTo="M0 -7.49 C-2.58,-7.49 -7.45,-4.78 -7.45,-1.62 C-7.45,-1.42 -7.37,0.88 -7.37,1.09 C-7.37,6.31 -2.19,7.55 0,7.55 C0,5.91 -0.01,3.91 -0.01,0 C-0.01,-3.91 0,-5.31 0,-7.49c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.2,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="time_group"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:duration="217" + android:propertyName="translateX" + android:startOffset="0" + android:valueFrom="0" + android:valueTo="1" + android:valueType="floatType" /> + </set> + </aapt:attr> + </target> + <aapt:attr name="android:drawable"> + <vector + android:width="24dp" + android:height="24dp" + android:viewportHeight="24" + android:viewportWidth="24"> + <group android:name="_R_G"> + <group + android:name="_R_G_L_0_G" + android:translateX="12" + android:translateY="12"> + <path + android:name="_R_G_L_0_G_D_0_P_0" + android:fillAlpha="1" + android:fillColor="#ffffff" + android:fillType="nonZero" + android:pathData=" M0 -7.08 C-2.69,-7.08 -7.03,-5.19 -7.03,0.03 C-7.03,5.25 -2.19,7.08 0,7.08 C3.03,7.08 7.08,3.91 7.08,0 C7.08,-3.91 3.69,-7.08 0,-7.08c M-8.33 0 C-8.33,-4.6 -4.6,-8.33 0,-8.33 C4.6,-8.33 8.33,-4.6 8.33,0 C8.33,4.6 4.6,8.33 0,8.33 C-4.6,8.33 -8.33,4.6 -8.33,0c " /> + <path + android:name="_R_G_L_0_G_D_1_P_0" + android:fillAlpha="1" + android:fillColor="#ffffff" + android:fillType="nonZero" + android:pathData=" M7.38 -2.03 C6.38,-4.66 3.47,-7.32 0.01,-7.32 C0.03,-6.22 -0.03,5.66 -0.03,7.28 C1.59,7.31 5.22,6.17 7.37,2.06 C7.37,1.21 7.37,0.69 7.37,0 C7.37,-0.91 7.38,-1.16 7.38,-2.03c " /> + </group> + </group> + <group android:name="time_group" /> + </vector> + </aapt:attr> +</animated-vector> diff --git a/packages/SystemUI/res-keyguard/drawable/qs_light_dark_theme_icon_on.xml b/packages/SystemUI/res-keyguard/drawable/qs_light_dark_theme_icon_on.xml new file mode 100644 index 000000000000..a96b7480ec94 --- /dev/null +++ b/packages/SystemUI/res-keyguard/drawable/qs_light_dark_theme_icon_on.xml @@ -0,0 +1,109 @@ +<?xml version="1.0" encoding="utf-8"?><!-- + ~ 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 + --> +<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:aapt="http://schemas.android.com/aapt"> + <target android:name="_R_G_L_0_G_D_1_P_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:duration="100" + android:propertyName="pathData" + android:startOffset="0" + android:valueFrom="M0 -7.49 C-2.58,-7.49 -7.45,-4.78 -7.45,-1.62 C-7.45,-1.42 -7.37,0.88 -7.37,1.09 C-7.37,6.31 -2.19,7.55 0,7.55 C0,5.91 -0.01,3.91 -0.01,0 C-0.01,-3.91 0,-5.31 0,-7.49c " + android:valueTo="M3.11 -6.83 C-0.23,-9.49 -6.06,-6.24 -7.23,-2.29 C-7.28,-2.09 -7.23,1.85 -7.18,2.06 C-5.84,7.25 -0.33,9.23 3.14,6.75 C3.17,5.1 3.17,3.58 3.22,0 C3.25,-3.04 3.14,-5.1 3.11,-6.83c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="67" + android:propertyName="pathData" + android:startOffset="100" + android:valueFrom="M3.11 -6.83 C-0.23,-9.49 -6.06,-6.24 -7.23,-2.29 C-7.28,-2.09 -7.23,1.85 -7.18,2.06 C-5.84,7.25 -0.33,9.23 3.14,6.75 C3.17,5.1 3.17,3.58 3.22,0 C3.25,-3.04 3.14,-5.1 3.11,-6.83c " + android:valueTo="M7.06 -3.94 C3.5,-8.81 -3.31,-9.44 -7,-3.66 C-7.12,-3.47 -7.05,3 -6.94,3.22 C-3.63,9.31 2.94,9.19 7,3.59 C7.06,1.94 7,3.19 7.12,0 C7.19,-2 7.12,-2.75 7.06,-3.94c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="67" + android:propertyName="pathData" + android:startOffset="167" + android:valueFrom="M7.06 -3.94 C3.5,-8.81 -3.31,-9.44 -7,-3.66 C-7.12,-3.47 -7.05,3 -6.94,3.22 C-3.63,9.31 2.94,9.19 7,3.59 C7.06,1.94 7,3.19 7.12,0 C7.19,-2 7.12,-2.75 7.06,-3.94c " + android:valueTo="M7.25 -2.44 C5.46,-5.86 1.53,-8.3 -1.72,-7.1 C-1.73,-6.22 -1.73,5.88 -1.7,7.16 C0.25,8.45 4.43,6.91 7.28,2.47 C7.29,1.42 7.27,1.3 7.3,0 C7.32,-1.17 7.27,-1.49 7.25,-2.44c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="100" + android:propertyName="pathData" + android:startOffset="233" + android:valueFrom="M7.25 -2.44 C5.46,-5.86 1.53,-8.3 -1.72,-7.1 C-1.73,-6.22 -1.73,5.88 -1.7,7.16 C0.25,8.45 4.43,6.91 7.28,2.47 C7.29,1.42 7.27,1.3 7.3,0 C7.32,-1.17 7.27,-1.49 7.25,-2.44c " + android:valueTo="M7.38 -2.03 C6.38,-4.66 3.47,-7.32 0.01,-7.32 C0.03,-6.22 -0.03,5.66 -0.03,7.28 C1.59,7.31 5.22,6.17 7.37,2.06 C7.37,1.21 7.37,0.69 7.37,0 C7.37,-0.91 7.38,-1.16 7.38,-2.03c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.2,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="time_group"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:duration="350" + android:propertyName="translateX" + android:startOffset="0" + android:valueFrom="0" + android:valueTo="1" + android:valueType="floatType" /> + </set> + </aapt:attr> + </target> + <aapt:attr name="android:drawable"> + <vector + android:width="24dp" + android:height="24dp" + android:viewportHeight="24" + android:viewportWidth="24"> + <group android:name="_R_G"> + <group + android:name="_R_G_L_0_G" + android:translateX="12" + android:translateY="12"> + <path + android:name="_R_G_L_0_G_D_0_P_0" + android:fillAlpha="1" + android:fillColor="#edf2eb" + android:fillType="nonZero" + android:pathData=" M0 -7.08 C-2.69,-7.08 -7.03,-5.19 -7.03,0.03 C-7.03,5.25 -2.19,7.08 0,7.08 C3.03,7.08 7.08,3.91 7.08,0 C7.08,-3.91 3.69,-7.08 0,-7.08c M-8.33 0 C-8.33,-4.6 -4.6,-8.33 0,-8.33 C4.6,-8.33 8.33,-4.6 8.33,0 C8.33,4.6 4.6,8.33 0,8.33 C-4.6,8.33 -8.33,4.6 -8.33,0c " /> + <path + android:name="_R_G_L_0_G_D_1_P_0" + android:fillAlpha="1" + android:fillColor="#edf2eb" + android:fillType="nonZero" + android:pathData=" M0 -7.49 C-2.58,-7.49 -7.45,-4.78 -7.45,-1.62 C-7.45,-1.42 -7.37,0.88 -7.37,1.09 C-7.37,6.31 -2.19,7.55 0,7.55 C0,5.91 -0.01,3.91 -0.01,0 C-0.01,-3.91 0,-5.31 0,-7.49c " /> + </group> + </group> + <group android:name="time_group" /> + </vector> + </aapt:attr> +</animated-vector> diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_bouncer_message_area.xml b/packages/SystemUI/res-keyguard/layout/keyguard_bouncer_message_area.xml new file mode 100644 index 000000000000..57b3acd6557a --- /dev/null +++ b/packages/SystemUI/res-keyguard/layout/keyguard_bouncer_message_area.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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 + --> +<merge xmlns:android="http://schemas.android.com/apk/res/android"> + <com.android.keyguard.BouncerKeyguardMessageArea + android:id="@+id/bouncer_message_area" + style="@style/Keyguard.TextView" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="@dimen/keyguard_lock_padding" + android:ellipsize="marquee" + android:focusable="true" + android:gravity="center" + android:singleLine="true" /> +</merge> diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_esim_area.xml b/packages/SystemUI/res-keyguard/layout/keyguard_esim_area.xml index db508c91e0de..67fd5b9a78bd 100644 --- a/packages/SystemUI/res-keyguard/layout/keyguard_esim_area.xml +++ b/packages/SystemUI/res-keyguard/layout/keyguard_esim_area.xml @@ -17,15 +17,17 @@ */ --> -<!-- This contains disable esim buttonas shared by sim_pin/sim_puk screens --> -<com.android.keyguard.KeyguardEsimArea - xmlns:android="http://schemas.android.com/apk/res/android" +<!-- This contains disable eSim buttons shared by sim_pin/sim_puk screens --> +<com.android.keyguard.KeyguardEsimArea xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/keyguard_disable_esim" + style="@style/Keyguard.TextView" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:id="@+id/keyguard_disable_esim" - android:visibility="gone" + android:background="@drawable/kg_bouncer_secondary_button" + android:drawablePadding="10dp" + android:drawableStart="@drawable/ic_no_sim" + android:drawableTint="?android:attr/textColorPrimary" android:text="@string/disable_carrier_button_text" - style="@style/Keyguard.TextView" - android:textAppearance="?android:attr/textAppearanceMedium" + android:textColor="?android:attr/textColorPrimary" android:textSize="@dimen/kg_status_line_font_size" - android:textAllCaps="@bool/kg_use_all_caps" /> + android:visibility="gone" /> diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_password_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_password_view.xml index e77e084c48e8..5486adbd2b8e 100644 --- a/packages/SystemUI/res-keyguard/layout/keyguard_password_view.xml +++ b/packages/SystemUI/res-keyguard/layout/keyguard_password_view.xml @@ -28,6 +28,7 @@ android:layout_gravity="center_horizontal|bottom" android:gravity="bottom" > + <include layout="@layout/keyguard_bouncer_message_area"/> <Space android:layout_width="match_parent" diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_pattern_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_pattern_view.xml index 231ead8dc273..2b7bdc2dc4cb 100644 --- a/packages/SystemUI/res-keyguard/layout/keyguard_pattern_view.xml +++ b/packages/SystemUI/res-keyguard/layout/keyguard_pattern_view.xml @@ -31,6 +31,7 @@ android:layout_gravity="center_horizontal|bottom" android:clipChildren="false" android:clipToPadding="false"> + <include layout="@layout/keyguard_bouncer_message_area"/> <androidx.constraintlayout.widget.ConstraintLayout android:id="@+id/pattern_container" diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml index 712f657a20ae..64ece472243d 100644 --- a/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml +++ b/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml @@ -17,23 +17,25 @@ */ --> -<com.android.keyguard.KeyguardPINView - xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:androidprv="http://schemas.android.com/apk/res-auto" - xmlns:tools="http://schemas.android.com/tools" - android:id="@+id/keyguard_pin_view" - android:layout_width="match_parent" - android:layout_height="match_parent" - androidprv:layout_maxWidth="@dimen/keyguard_security_width" - android:layout_gravity="center_horizontal|bottom" - android:orientation="vertical" - > - - <androidx.constraintlayout.widget.ConstraintLayout +<com.android.keyguard.KeyguardPINView xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:androidprv="http://schemas.android.com/apk/res-auto" + android:id="@+id/keyguard_pin_view" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_gravity="center_horizontal|bottom" + android:clipChildren="false" + android:clipToPadding="false" + android:orientation="vertical" + androidprv:layout_maxWidth="@dimen/keyguard_security_width"> +<include layout="@layout/keyguard_bouncer_message_area"/> + +<androidx.constraintlayout.widget.ConstraintLayout android:id="@+id/pin_container" android:layout_width="match_parent" android:layout_height="0dp" android:layout_marginBottom="8dp" + android:clipChildren="false" + android:clipToPadding="false" android:layout_weight="1" android:layoutDirection="ltr" android:orientation="vertical"> @@ -79,6 +81,8 @@ android:layout_width="0dp" android:layout_height="0dp" android:orientation="horizontal" + android:clipChildren="false" + android:clipToPadding="false" androidprv:constraint_referenced_ids="key1,key2,key3,key4,key5,key6,key7,key8,key9,delete_button,key0,key_enter" @@ -186,8 +190,6 @@ </androidx.constraintlayout.widget.ConstraintLayout> - - <include layout="@layout/keyguard_eca" android:id="@+id/keyguard_selector_fade_container" android:layout_width="match_parent" diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml index dae2e564dd32..7db0fe908ec0 100644 --- a/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml +++ b/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml @@ -26,20 +26,17 @@ android:layout_height="match_parent" androidprv:layout_maxWidth="@dimen/keyguard_security_width" android:layout_gravity="center_horizontal|bottom"> - - <Space - android:layout_width="match_parent" - android:layout_height="0dp" - android:layout_weight="1" - /> - + <include layout="@layout/keyguard_bouncer_message_area" /> + <Space + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_weight="1" /> <ImageView android:id="@+id/keyguard_sim" android:layout_width="match_parent" android:layout_height="wrap_content" android:tint="@color/background_protected" android:src="@drawable/ic_lockscreen_sim"/> - <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" @@ -50,16 +47,13 @@ <include layout="@layout/keyguard_esim_area" android:id="@+id/keyguard_esim_area" android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginTop="@dimen/eca_overlap" /> - + android:layout_height="wrap_content" /> <RelativeLayout android:id="@+id/row0" android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingBottom="4dp" > - <com.android.keyguard.PasswordTextView android:id="@+id/simPinEntry" style="@style/Widget.TextView.Password" @@ -195,7 +189,6 @@ /> </LinearLayout> </LinearLayout> - <include layout="@layout/keyguard_eca" android:id="@+id/keyguard_selector_fade_container" android:layout_width="match_parent" @@ -205,5 +198,4 @@ android:layout_marginTop="@dimen/keyguard_eca_top_margin" android:layout_marginBottom="2dp" android:gravity="center_horizontal"/> - </com.android.keyguard.KeyguardSimPinView> diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml index 74f78201e677..422bd4c12e8e 100644 --- a/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml +++ b/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml @@ -27,12 +27,12 @@ android:layout_height="match_parent" androidprv:layout_maxWidth="@dimen/keyguard_security_width" android:layout_gravity="center_horizontal|bottom"> + <include layout="@layout/keyguard_bouncer_message_area"/> - <Space - android:layout_width="match_parent" - android:layout_height="0dp" - android:layout_weight="1" - /> + <Space + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_weight="1" /> <ImageView android:id="@+id/keyguard_sim" @@ -51,8 +51,7 @@ <include layout="@layout/keyguard_esim_area" android:id="@+id/keyguard_esim_area" android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginTop="@dimen/eca_overlap" /> + android:layout_height="wrap_content" /> <RelativeLayout android:id="@+id/row0" diff --git a/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml b/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml index fc9c4026bdfa..9dc054a53393 100644 --- a/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml +++ b/packages/SystemUI/res-keyguard/values-es-rUS/strings.xml @@ -53,7 +53,7 @@ <string name="kg_wrong_pattern" msgid="5907301342430102842">"Patrón incorrecto"</string> <string name="kg_wrong_password" msgid="4143127991071670512">"Contraseña incorrecta"</string> <string name="kg_wrong_pin" msgid="4160978845968732624">"PIN incorrecto"</string> - <string name="kg_too_many_failed_attempts_countdown" msgid="2038195171919795529">"{count,plural, =1{Vuelve a intentarlo en # segundo.}other{Vuelve a intentarlo en # segundos.}}"</string> + <string name="kg_too_many_failed_attempts_countdown" msgid="2038195171919795529">"{count,plural, =1{Vuelve a intentarlo en # segundo.}many{Vuelve a intentarlo en # segundos.}other{Vuelve a intentarlo en # segundos.}}"</string> <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Ingresa el PIN de la tarjeta SIM."</string> <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Ingresa el PIN de la tarjeta SIM de \"<xliff:g id="CARRIER">%1$s</xliff:g>\"."</string> <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Inhabilita la tarjeta eSIM para usar el dispositivo sin servicio móvil."</string> @@ -68,9 +68,9 @@ <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Escribiste tu contraseña <xliff:g id="NUMBER_0">%1$d</xliff:g> veces de manera incorrecta. \n\nVuelve a intentarlo en <xliff:g id="NUMBER_1">%2$d</xliff:g> segundos."</string> <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Dibujaste tu patrón de desbloqueo <xliff:g id="NUMBER_0">%1$d</xliff:g> veces de manera incorrecta. \n\nVuelve a intentarlo en <xliff:g id="NUMBER_1">%2$d</xliff:g> segundos."</string> <string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"El código PIN de la tarjeta SIM es incorrecto. Debes comunicarte con tu proveedor para desbloquear el dispositivo."</string> - <string name="kg_password_wrong_pin_code" msgid="5629415765976820357">"{count,plural, =1{El código PIN de la tarjeta SIM es incorrecto. Tienes # intento restante antes de que debas comunicarte con tu operador para desbloquear el dispositivo.}other{El código PIN de la tarjeta SIM es incorrecto. Tienes # intentos restantes. }}"</string> + <string name="kg_password_wrong_pin_code" msgid="5629415765976820357">"{count,plural, =1{El código PIN de la tarjeta SIM es incorrecto. Tienes # intento restante antes de que debas comunicarte con tu operador para desbloquear el dispositivo.}many{El código PIN de la tarjeta SIM es incorrecto. Tienes # intentos restantes. }other{El código PIN de la tarjeta SIM es incorrecto. Tienes # intentos restantes. }}"</string> <string name="kg_password_wrong_puk_code_dead" msgid="3698285357028468617">"La tarjeta SIM no se puede usar. Comunícate con tu proveedor."</string> - <string name="kg_password_wrong_puk_code" msgid="6820515467645087827">"{count,plural, =1{El código PUK de la tarjeta SIM es incorrecto. Tienes # intento restante antes de que la tarjeta SIM quede inutilizable permanentemente.}other{El código PUK de la tarjeta SIM es incorrecto. Tienes # intentos restantes antes de que la tarjeta SIM quede inutilizable permanentemente.}}"</string> + <string name="kg_password_wrong_puk_code" msgid="6820515467645087827">"{count,plural, =1{El código PUK de la tarjeta SIM es incorrecto. Tienes # intento restante antes de que la tarjeta SIM quede inutilizable permanentemente.}many{El código PUK de la tarjeta SIM es incorrecto. Tienes # intentos restantes antes de que la tarjeta SIM quede inutilizable permanentemente.}other{El código PUK de la tarjeta SIM es incorrecto. Tienes # intentos restantes antes de que la tarjeta SIM quede inutilizable permanentemente.}}"</string> <string name="kg_password_pin_failed" msgid="5136259126330604009">"Se produjo un error al desbloquear la tarjeta SIM con el PIN."</string> <string name="kg_password_puk_failed" msgid="6778867411556937118">"Se produjo un error al desbloquear la tarjeta SIM con el PUK."</string> <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Cambiar método de entrada"</string> @@ -85,8 +85,8 @@ <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"El dispositivo se bloqueó de forma manual"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"No se reconoció"</string> <string name="kg_face_sensor_privacy_enabled" msgid="939511161763558512">"Activa acceso a cámara en Config. y usa Desb. facial"</string> - <string name="kg_password_default_pin_message" msgid="1434544655827987873">"{count,plural, =1{Ingresa el PIN de la tarjeta SIM. Tienes # intento restante antes de que debas comunicarte con tu operador para desbloquear el dispositivo.}other{Ingresa el PIN de la tarjeta SIM. Tienes # intentos restantes.}}"</string> - <string name="kg_password_default_puk_message" msgid="1025139786449741950">"{count,plural, =1{Se inhabilitó la tarjeta SIM. Para continuar, ingresa el código PUK. Tienes # intento restante antes de que la SIM quede inutilizable permanentemente. Comunícate con tu operador para conocer más detalles.}other{Se inhabilitó la tarjeta SIM. Para continuar, ingresa el código PUK. Tienes # intentos restantes antes de que la SIM quede inutilizable permanentemente. Comunícate con tu operador para conocer más detalles.}}"</string> + <string name="kg_password_default_pin_message" msgid="1434544655827987873">"{count,plural, =1{Ingresa el PIN de la tarjeta SIM. Tienes # intento restante antes de que debas comunicarte con tu operador para desbloquear el dispositivo.}many{Ingresa el PIN de la tarjeta SIM. Tienes # intentos restantes.}other{Ingresa el PIN de la tarjeta SIM. Tienes # intentos restantes.}}"</string> + <string name="kg_password_default_puk_message" msgid="1025139786449741950">"{count,plural, =1{Se inhabilitó la tarjeta SIM. Para continuar, ingresa el código PUK. Tienes # intento restante antes de que la SIM quede inutilizable permanentemente. Comunícate con tu operador para conocer más detalles.}many{Se inhabilitó la tarjeta SIM. Para continuar, ingresa el código PUK. Tienes # intentos restantes antes de que la SIM quede inutilizable permanentemente. Comunícate con tu operador para conocer más detalles.}other{Se inhabilitó la tarjeta SIM. Para continuar, ingresa el código PUK. Tienes # intentos restantes antes de que la SIM quede inutilizable permanentemente. Comunícate con tu operador para conocer más detalles.}}"</string> <string name="clock_title_default" msgid="6342735240617459864">"Predeterminado"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Burbuja"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Analógico"</string> diff --git a/packages/SystemUI/res-keyguard/values-es/strings.xml b/packages/SystemUI/res-keyguard/values-es/strings.xml index 405316165c57..f9f0452771af 100644 --- a/packages/SystemUI/res-keyguard/values-es/strings.xml +++ b/packages/SystemUI/res-keyguard/values-es/strings.xml @@ -53,7 +53,7 @@ <string name="kg_wrong_pattern" msgid="5907301342430102842">"Patrón incorrecto"</string> <string name="kg_wrong_password" msgid="4143127991071670512">"Contraseña incorrecta"</string> <string name="kg_wrong_pin" msgid="4160978845968732624">"PIN incorrecto"</string> - <string name="kg_too_many_failed_attempts_countdown" msgid="2038195171919795529">"{count,plural, =1{Vuelve a intentarlo en # segundo.}other{Vuelve a intentarlo en # segundos.}}"</string> + <string name="kg_too_many_failed_attempts_countdown" msgid="2038195171919795529">"{count,plural, =1{Vuelve a intentarlo en # segundo.}many{Vuelve a intentarlo en # segundos.}other{Vuelve a intentarlo en # segundos.}}"</string> <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Introduce el PIN de la tarjeta SIM."</string> <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Introduce el PIN de la tarjeta SIM de <xliff:g id="CARRIER">%1$s</xliff:g>."</string> <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Inhabilita la tarjeta eSIM para usar el dispositivo sin servicio móvil."</string> @@ -68,9 +68,9 @@ <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Has fallado <xliff:g id="NUMBER_0">%1$d</xliff:g> veces al introducir la contraseña. \n\nVuelve a intentarlo dentro de <xliff:g id="NUMBER_1">%2$d</xliff:g> segundos."</string> <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Has fallado <xliff:g id="NUMBER_0">%1$d</xliff:g> veces al dibujar el patrón de desbloqueo. \n\nVuelve a intentarlo dentro de <xliff:g id="NUMBER_1">%2$d</xliff:g> segundos."</string> <string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"El código PIN de la tarjeta SIM es incorrecto. Debes ponerte en contacto con tu operador para desbloquear el dispositivo."</string> - <string name="kg_password_wrong_pin_code" msgid="5629415765976820357">"{count,plural, =1{Código PIN de la SIM incorrecto. Te queda # intento antes de tener que ponerte en contacto con tu operador para desbloquear el dispositivo.}other{Código PIN de la SIM incorrecto. Te quedan # intentos. }}"</string> + <string name="kg_password_wrong_pin_code" msgid="5629415765976820357">"{count,plural, =1{Código PIN de la SIM incorrecto. Te queda # intento antes de tener que ponerte en contacto con tu operador para desbloquear el dispositivo.}many{Código PIN de la SIM incorrecto. Te quedan # intentos. }other{Código PIN de la SIM incorrecto. Te quedan # intentos. }}"</string> <string name="kg_password_wrong_puk_code_dead" msgid="3698285357028468617">"La tarjeta SIM no se puede utilizar. Ponte en contacto con tu operador."</string> - <string name="kg_password_wrong_puk_code" msgid="6820515467645087827">"{count,plural, =1{Código PUK de la SIM incorrecto. Te queda # intento antes de que la SIM quede inservible permanentemente.}other{Código PUK de la SIM incorrecto. Te quedan # intentos antes de que la SIM quede inservible permanentemente.}}"</string> + <string name="kg_password_wrong_puk_code" msgid="6820515467645087827">"{count,plural, =1{Código PUK de la SIM incorrecto. Te queda # intento antes de que la SIM quede inservible permanentemente.}many{Código PUK de la SIM incorrecto. Te quedan # intentos antes de que la SIM quede inservible permanentemente.}other{Código PUK de la SIM incorrecto. Te quedan # intentos antes de que la SIM quede inservible permanentemente.}}"</string> <string name="kg_password_pin_failed" msgid="5136259126330604009">"No se ha podido desbloquear la tarjeta SIM con el código PIN."</string> <string name="kg_password_puk_failed" msgid="6778867411556937118">"No se ha podido desbloquear la tarjeta SIM con el código PUK."</string> <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Cambiar método de introducción"</string> @@ -85,8 +85,8 @@ <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"El dispositivo se ha bloqueado manualmente"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"No se reconoce"</string> <string name="kg_face_sensor_privacy_enabled" msgid="939511161763558512">"Desbloqueo facial: activa el acceso a la cámara"</string> - <string name="kg_password_default_pin_message" msgid="1434544655827987873">"{count,plural, =1{Introduce el PIN de la SIM. Te queda # intento antes de tener que ponerte en contacto con tu operador para desbloquear el dispositivo.}other{Introduce el PIN de la SIM. Te quedan # intentos.}}"</string> - <string name="kg_password_default_puk_message" msgid="1025139786449741950">"{count,plural, =1{La SIM se ha inhabilitado. Introduce el código PUK para continuar. Te queda # intento antes de que la SIM quede inservible permanentemente. Ponte en contacto con tu operador para obtener más información.}other{La SIM se ha inhabilitado. Introduce el código PUK para continuar. Te quedan # intentos antes de que la SIM quede inservible permanentemente. Ponte en contacto con tu operador para obtener más información.}}"</string> + <string name="kg_password_default_pin_message" msgid="1434544655827987873">"{count,plural, =1{Introduce el PIN de la SIM. Te queda # intento antes de tener que ponerte en contacto con tu operador para desbloquear el dispositivo.}many{Introduce el PIN de la SIM. Te quedan # intentos.}other{Introduce el PIN de la SIM. Te quedan # intentos.}}"</string> + <string name="kg_password_default_puk_message" msgid="1025139786449741950">"{count,plural, =1{La SIM se ha inhabilitado. Introduce el código PUK para continuar. Te queda # intento antes de que la SIM quede inservible permanentemente. Ponte en contacto con tu operador para obtener más información.}many{La SIM se ha inhabilitado. Introduce el código PUK para continuar. Te quedan # intentos antes de que la SIM quede inservible permanentemente. Ponte en contacto con tu operador para obtener más información.}other{La SIM se ha inhabilitado. Introduce el código PUK para continuar. Te quedan # intentos antes de que la SIM quede inservible permanentemente. Ponte en contacto con tu operador para obtener más información.}}"</string> <string name="clock_title_default" msgid="6342735240617459864">"Predeterminado"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Burbuja"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Analógico"</string> diff --git a/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml b/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml index 92ab77e301db..077fe11be4f2 100644 --- a/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml +++ b/packages/SystemUI/res-keyguard/values-fr-rCA/strings.xml @@ -53,7 +53,7 @@ <string name="kg_wrong_pattern" msgid="5907301342430102842">"Schéma incorrect"</string> <string name="kg_wrong_password" msgid="4143127991071670512">"Mot de passe incorrect"</string> <string name="kg_wrong_pin" msgid="4160978845968732624">"NIP incorrect"</string> - <string name="kg_too_many_failed_attempts_countdown" msgid="2038195171919795529">"{count,plural, =1{Réessayez dans # seconde.}one{Réessayez dans # seconde.}other{Réessayez dans # secondes.}}"</string> + <string name="kg_too_many_failed_attempts_countdown" msgid="2038195171919795529">"{count,plural, =1{Réessayez dans # seconde.}one{Réessayez dans # seconde.}many{Réessayez dans # secondes.}other{Réessayez dans # secondes.}}"</string> <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Entrez le NIP de la carte SIM."</string> <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Entrez le NIP de la carte SIM pour « <xliff:g id="CARRIER">%1$s</xliff:g> »."</string> <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Désactivez la carte eSIM pour utiliser l\'appareil sans service cellulaire."</string> @@ -68,9 +68,9 @@ <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Vous avez entré un mot de passe incorrect à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises.\n\nVeuillez réessayer dans <xliff:g id="NUMBER_1">%2$d</xliff:g> secondes."</string> <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Vous avez dessiné un schéma de déverrouillage incorrect à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises.\n\nVeuillez réessayer dans <xliff:g id="NUMBER_1">%2$d</xliff:g> secondes."</string> <string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"NIP de carte SIM incorrect. Vous devez maintenant communiquer avec votre fournisseur de services pour déverrouiller votre appareil."</string> - <string name="kg_password_wrong_pin_code" msgid="5629415765976820357">"{count,plural, =1{NIP de la carte SIM incorrect. Il vous reste # tentative. Après cela, vous devrez communiquer avec votre fournisseur de services pour déverrouiller votre appareil.}one{NIP de la carte SIM incorrect. Il vous reste # tentative. }other{NIP de la carte SIM incorrect. Il vous reste # tentatives. }}"</string> + <string name="kg_password_wrong_pin_code" msgid="5629415765976820357">"{count,plural, =1{NIP de la carte SIM incorrect. Il vous reste # tentative. Après cela, vous devrez communiquer avec votre fournisseur de services pour déverrouiller votre appareil.}one{NIP de la carte SIM incorrect. Il vous reste # tentative. }many{NIP de la carte SIM incorrect. Il vous reste # de tentatives. }other{NIP de la carte SIM incorrect. Il vous reste # tentatives. }}"</string> <string name="kg_password_wrong_puk_code_dead" msgid="3698285357028468617">"La carte SIM est inutilisable. Communiquez avec votre fournisseur de services."</string> - <string name="kg_password_wrong_puk_code" msgid="6820515467645087827">"{count,plural, =1{Code PUK de la carte SIM incorrect. Il vous reste # tentative avant que votre carte SIM devienne définitivement inutilisable.}one{Code PUK de la carte SIM incorrect. Il vous reste # tentative avant que votre carte SIM devienne définitivement inutilisable.}other{Code PUK de la carte SIM incorrect. Il vous reste # tentatives avant que votre carte SIM devienne définitivement inutilisable.}}"</string> + <string name="kg_password_wrong_puk_code" msgid="6820515467645087827">"{count,plural, =1{Code PUK de la carte SIM incorrect. Il vous reste # tentative avant que votre carte SIM devienne définitivement inutilisable.}one{Code PUK de la carte SIM incorrect. Il vous reste # tentative avant que votre carte SIM devienne définitivement inutilisable.}many{Code PUK de la carte SIM incorrect. Il vous reste # de tentatives avant que votre carte SIM devienne définitivement inutilisable.}other{Code PUK de la carte SIM incorrect. Il vous reste # tentatives avant que votre carte SIM devienne définitivement inutilisable.}}"</string> <string name="kg_password_pin_failed" msgid="5136259126330604009">"Le déverrouillage par NIP de la carte SIM a échoué."</string> <string name="kg_password_puk_failed" msgid="6778867411556937118">"Le déverrouillage de la carte SIM par code PUK a échoué."</string> <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Changer de méthode d\'entrée"</string> @@ -85,8 +85,8 @@ <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"L\'appareil a été verrouillé manuellement"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Doigt non reconnu"</string> <string name="kg_face_sensor_privacy_enabled" msgid="939511161763558512">"Déverr. rec. faciale : activez accès app. photo dans Param."</string> - <string name="kg_password_default_pin_message" msgid="1434544655827987873">"{count,plural, =1{Entrez le NIP de la carte SIM. Il vous reste # tentative. Après cela, vous devrez communiquer avec votre fournisseur de services pour déverrouiller votre appareil.}one{Entrez le NIP de la carte SIM. Il vous reste # tentative.}other{Entrez le NIP de la carte SIM. Il vous reste # tentatives.}}"</string> - <string name="kg_password_default_puk_message" msgid="1025139786449741950">"{count,plural, =1{La carte SIM est maintenant désactivée. Entrez le code PUK pour continuer. Il vous reste # tentative avant que votre carte SIM devienne définitivement inutilisable. Communiquez avec votre fournisseur de services pour en savoir plus.}one{La carte SIM est maintenant désactivée. Entrez le code PUK pour continuer. Il vous reste # tentative avant que votre carte SIM devienne définitivement inutilisable. Communiquez avec votre fournisseur de services pour en savoir plus.}other{La carte SIM est maintenant désactivée. Entrez le code PUK pour continuer. Il vous reste # tentatives avant que votre carte SIM devienne définitivement inutilisable. Communiquez avec votre fournisseur de services pour en savoir plus.}}"</string> + <string name="kg_password_default_pin_message" msgid="1434544655827987873">"{count,plural, =1{Entrez le NIP de la carte SIM. Il vous reste # tentative. Après cela, vous devrez communiquer avec votre fournisseur de services pour déverrouiller votre appareil.}one{Entrez le NIP de la carte SIM. Il vous reste # tentative.}many{Entrez le NIP de la carte SIM. Il vous reste # de tentatives.}other{Entrez le NIP de la carte SIM. Il vous reste # tentatives.}}"</string> + <string name="kg_password_default_puk_message" msgid="1025139786449741950">"{count,plural, =1{La carte SIM est maintenant désactivée. Entrez le code PUK pour continuer. Il vous reste # tentative avant que votre carte SIM devienne définitivement inutilisable. Communiquez avec votre fournisseur de services pour en savoir plus.}one{La carte SIM est maintenant désactivée. Entrez le code PUK pour continuer. Il vous reste # tentative avant que votre carte SIM devienne définitivement inutilisable. Communiquez avec votre fournisseur de services pour en savoir plus.}many{La carte SIM est maintenant désactivée. Entrez le code PUK pour continuer. Il vous reste # de tentatives avant que votre carte SIM devienne définitivement inutilisable. Communiquez avec votre fournisseur de services pour en savoir plus.}other{La carte SIM est maintenant désactivée. Entrez le code PUK pour continuer. Il vous reste # tentatives avant que votre carte SIM devienne définitivement inutilisable. Communiquez avec votre fournisseur de services pour en savoir plus.}}"</string> <string name="clock_title_default" msgid="6342735240617459864">"Par défaut"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Bulle"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Analogique"</string> diff --git a/packages/SystemUI/res-keyguard/values-fr/strings.xml b/packages/SystemUI/res-keyguard/values-fr/strings.xml index 01facd109717..62379f8e37dc 100644 --- a/packages/SystemUI/res-keyguard/values-fr/strings.xml +++ b/packages/SystemUI/res-keyguard/values-fr/strings.xml @@ -53,7 +53,7 @@ <string name="kg_wrong_pattern" msgid="5907301342430102842">"Schéma incorrect"</string> <string name="kg_wrong_password" msgid="4143127991071670512">"Mot de passe incorrect"</string> <string name="kg_wrong_pin" msgid="4160978845968732624">"Code incorrect"</string> - <string name="kg_too_many_failed_attempts_countdown" msgid="2038195171919795529">"{count,plural, =1{Réessayez dans # seconde.}one{Réessayez dans # seconde.}other{Réessayez dans # secondes.}}"</string> + <string name="kg_too_many_failed_attempts_countdown" msgid="2038195171919795529">"{count,plural, =1{Réessayez dans # seconde.}one{Réessayez dans # seconde.}many{Réessayez dans # secondes.}other{Réessayez dans # secondes.}}"</string> <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Saisissez le code PIN de la carte SIM."</string> <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Saisissez le code PIN de la carte SIM \"<xliff:g id="CARRIER">%1$s</xliff:g>\"."</string> <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Désactivez la carte eSIM pour utiliser l\'appareil sans service mobile."</string> @@ -68,9 +68,9 @@ <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Vous avez saisi un mot de passe incorrect à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises.\n\nRéessayez dans <xliff:g id="NUMBER_1">%2$d</xliff:g> secondes."</string> <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Vous avez dessiné un schéma de déverrouillage incorrect à <xliff:g id="NUMBER_0">%1$d</xliff:g> reprises.\n\nRéessayez dans <xliff:g id="NUMBER_1">%2$d</xliff:g> secondes."</string> <string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Code PIN de la carte SIM incorrect. Vous devez désormais contacter votre opérateur pour déverrouiller votre appareil."</string> - <string name="kg_password_wrong_pin_code" msgid="5629415765976820357">"{count,plural, =1{Code PIN SIM incorrect. Il vous reste # tentative avant de devoir contacter votre opérateur pour déverrouiller l\'appareil.}one{Code PIN SIM incorrect. Il vous reste # tentative. }other{Code PIN SIM incorrect. Il vous reste # tentatives. }}"</string> + <string name="kg_password_wrong_pin_code" msgid="5629415765976820357">"{count,plural, =1{Code PIN SIM incorrect. Il vous reste # tentative avant de devoir contacter votre opérateur pour déverrouiller l\'appareil.}one{Code PIN SIM incorrect. Il vous reste # tentative. }many{Code PIN SIM incorrect. Il vous reste # tentatives. }other{Code PIN SIM incorrect. Il vous reste # tentatives. }}"</string> <string name="kg_password_wrong_puk_code_dead" msgid="3698285357028468617">"La carte SIM est inutilisable. Contactez votre opérateur."</string> - <string name="kg_password_wrong_puk_code" msgid="6820515467645087827">"{count,plural, =1{Clé PUK de la SIM incorrecte. Il vous reste # tentative avant que la SIM ne devienne définitivement inutilisable.}one{Clé PUK de la SIM incorrecte. Il vous reste # tentative avant que la carte SIM ne devienne définitivement inutilisable.}other{Clé PUK de la SIM incorrecte. Il vous reste # tentatives avant que la carte SIM ne devienne définitivement inutilisable.}}"</string> + <string name="kg_password_wrong_puk_code" msgid="6820515467645087827">"{count,plural, =1{Clé PUK de la SIM incorrecte. Il vous reste # tentative avant que la SIM ne devienne définitivement inutilisable.}one{Clé PUK de la SIM incorrecte. Il vous reste # tentative avant que la carte SIM ne devienne définitivement inutilisable.}many{Clé PUK de la SIM incorrecte. Il vous reste # tentatives avant que la carte SIM ne devienne définitivement inutilisable.}other{Clé PUK de la SIM incorrecte. Il vous reste # tentatives avant que la carte SIM ne devienne définitivement inutilisable.}}"</string> <string name="kg_password_pin_failed" msgid="5136259126330604009">"Échec du déverrouillage à l\'aide du code PIN de la carte SIM."</string> <string name="kg_password_puk_failed" msgid="6778867411556937118">"Échec du déverrouillage à l\'aide de la clé PUK de la carte SIM."</string> <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Changer le mode de saisie"</string> @@ -85,8 +85,8 @@ <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Appareil verrouillé manuellement"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Non reconnu"</string> <string name="kg_face_sensor_privacy_enabled" msgid="939511161763558512">"Pour le déverrouillage par reconnaissance faciale, activez l\'accès à l\'app. photo dans Paramètres"</string> - <string name="kg_password_default_pin_message" msgid="1434544655827987873">"{count,plural, =1{Saisissez le code PIN SIM. Il vous reste # tentative avant de devoir contacter votre opérateur pour déverrouiller l\'appareil.}one{Saisissez le code PIN SIM. Il vous reste # tentative.}other{Saisissez le code PIN SIM. Il vous reste # tentatives.}}"</string> - <string name="kg_password_default_puk_message" msgid="1025139786449741950">"{count,plural, =1{La SIM est maintenant désactivée. Saisissez la clé PUK pour continuer. Il vous reste # tentative avant que la SIM ne devienne définitivement inutilisable. Pour plus d\'infos, contactez votre opérateur.}one{La SIM est maintenant désactivée. Saisissez la clé PUK pour continuer. Il vous reste # tentative avant que la SIM ne devienne définitivement inutilisable. Pour plus d\'infos, contactez votre opérateur.}other{La SIM est maintenant désactivée. Saisissez la clé PUK pour continuer. Il vous reste # tentatives avant que la SIM ne devienne définitivement inutilisable. Pour plus d\'infos, contactez votre opérateur.}}"</string> + <string name="kg_password_default_pin_message" msgid="1434544655827987873">"{count,plural, =1{Saisissez le code PIN SIM. Il vous reste # tentative avant de devoir contacter votre opérateur pour déverrouiller l\'appareil.}one{Saisissez le code PIN SIM. Il vous reste # tentative.}many{Saisissez le code PIN SIM. Il vous reste # tentatives.}other{Saisissez le code PIN SIM. Il vous reste # tentatives.}}"</string> + <string name="kg_password_default_puk_message" msgid="1025139786449741950">"{count,plural, =1{La SIM est maintenant désactivée. Saisissez la clé PUK pour continuer. Il vous reste # tentative avant que la SIM ne devienne définitivement inutilisable. Pour plus d\'infos, contactez votre opérateur.}one{La SIM est maintenant désactivée. Saisissez la clé PUK pour continuer. Il vous reste # tentative avant que la SIM ne devienne définitivement inutilisable. Pour plus d\'infos, contactez votre opérateur.}many{La SIM est maintenant désactivée. Saisissez la clé PUK pour continuer. Il vous reste # tentatives avant que la SIM ne devienne définitivement inutilisable. Pour plus d\'infos, contactez votre opérateur.}other{La SIM est maintenant désactivée. Saisissez la clé PUK pour continuer. Il vous reste # tentatives avant que la SIM ne devienne définitivement inutilisable. Pour plus d\'infos, contactez votre opérateur.}}"</string> <string name="clock_title_default" msgid="6342735240617459864">"Par défaut"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Bulle"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Analogique"</string> diff --git a/packages/SystemUI/res-keyguard/values-it/strings.xml b/packages/SystemUI/res-keyguard/values-it/strings.xml index d3a683bf3869..9fed5f72afa1 100644 --- a/packages/SystemUI/res-keyguard/values-it/strings.xml +++ b/packages/SystemUI/res-keyguard/values-it/strings.xml @@ -53,7 +53,7 @@ <string name="kg_wrong_pattern" msgid="5907301342430102842">"Sequenza errata"</string> <string name="kg_wrong_password" msgid="4143127991071670512">"Password errata"</string> <string name="kg_wrong_pin" msgid="4160978845968732624">"PIN errato"</string> - <string name="kg_too_many_failed_attempts_countdown" msgid="2038195171919795529">"{count,plural, =1{Riprova fra # secondo.}other{Riprova fra # secondi.}}"</string> + <string name="kg_too_many_failed_attempts_countdown" msgid="2038195171919795529">"{count,plural, =1{Riprova fra # secondo.}many{Riprova fra # secondi.}other{Riprova fra # secondi.}}"</string> <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Inserisci il PIN della SIM."</string> <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Inserisci il PIN della SIM \"<xliff:g id="CARRIER">%1$s</xliff:g>\"."</string> <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Disattiva la eSIM per usare il dispositivo senza servizio dati mobile."</string> @@ -68,9 +68,9 @@ <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Hai digitato la tua password <xliff:g id="NUMBER_0">%1$d</xliff:g> volte in modo errato. \n\nRiprova tra <xliff:g id="NUMBER_1">%2$d</xliff:g> secondi."</string> <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"<xliff:g id="NUMBER_0">%1$d</xliff:g> tentativi errati di inserimento della sequenza di sblocco. \n\nRiprova tra <xliff:g id="NUMBER_1">%2$d</xliff:g> secondi."</string> <string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Codice PIN della SIM errato. Devi contattare l\'operatore per sbloccare il dispositivo."</string> - <string name="kg_password_wrong_pin_code" msgid="5629415765976820357">"{count,plural, =1{Codice PIN della SIM errato. Hai ancora # tentativo a disposizione, dopodiché dovrai contattare l\'operatore per sbloccare il dispositivo.}other{Codice PIN della SIM errato. Hai ancora # tentativi a disposizione. }}"</string> + <string name="kg_password_wrong_pin_code" msgid="5629415765976820357">"{count,plural, =1{Codice PIN della SIM errato. Hai ancora # tentativo a disposizione, dopodiché dovrai contattare l\'operatore per sbloccare il dispositivo.}many{Codice PIN della SIM errato. Hai ancora # tentativi a disposizione. }other{Codice PIN della SIM errato. Hai ancora # tentativi a disposizione. }}"</string> <string name="kg_password_wrong_puk_code_dead" msgid="3698285357028468617">"SIM inutilizzabile. Contatta il tuo operatore."</string> - <string name="kg_password_wrong_puk_code" msgid="6820515467645087827">"{count,plural, =1{Codice PUK della SIM errato. Hai ancora # tentativo a disposizione prima che la SIM diventi definitivamente inutilizzabile.}other{Codice PUK della SIM errato. Hai ancora # tentativi a disposizione prima che la SIM diventi definitivamente inutilizzabile.}}"</string> + <string name="kg_password_wrong_puk_code" msgid="6820515467645087827">"{count,plural, =1{Codice PUK della SIM errato. Hai ancora # tentativo a disposizione prima che la SIM diventi definitivamente inutilizzabile.}many{Codice PUK della SIM errato. Hai ancora # tentativi a disposizione prima che la SIM diventi definitivamente inutilizzabile.}other{Codice PUK della SIM errato. Hai ancora # tentativi a disposizione prima che la SIM diventi definitivamente inutilizzabile.}}"</string> <string name="kg_password_pin_failed" msgid="5136259126330604009">"Operazione con PIN della SIM non riuscita."</string> <string name="kg_password_puk_failed" msgid="6778867411556937118">"Operazione con PUK della SIM non riuscita."</string> <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Cambia metodo di immissione"</string> @@ -85,8 +85,8 @@ <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"Il dispositivo è stato bloccato manualmente"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Non riconosciuto"</string> <string name="kg_face_sensor_privacy_enabled" msgid="939511161763558512">"Sblocco con volto richiede l\'accesso alla fotocamera"</string> - <string name="kg_password_default_pin_message" msgid="1434544655827987873">"{count,plural, =1{Inserisci il codice PIN della SIM. Hai ancora # tentativo a disposizione, dopodiché dovrai contattare l\'operatore per sbloccare il dispositivo.}other{Inserisci il PIN della SIM. Hai a disposizione ancora # tentativi.}}"</string> - <string name="kg_password_default_puk_message" msgid="1025139786449741950">"{count,plural, =1{La scheda SIM è ora disattivata. Inserisci il codice PUK per continuare. Hai ancora # tentativo a disposizione prima che la SIM diventi definitivamente inutilizzabile. Per informazioni dettagliate, contatta l\'operatore.}other{La scheda SIM è ora disattivata. Inserisci il codice PUK per continuare. Hai ancora # tentativi a disposizione prima che la SIM diventi definitivamente inutilizzabile. Per informazioni dettagliate, contatta l\'operatore.}}"</string> + <string name="kg_password_default_pin_message" msgid="1434544655827987873">"{count,plural, =1{Inserisci il codice PIN della SIM. Hai ancora # tentativo a disposizione, dopodiché dovrai contattare l\'operatore per sbloccare il dispositivo.}many{Inserisci il PIN della SIM. Hai a disposizione ancora # tentativi.}other{Inserisci il PIN della SIM. Hai a disposizione ancora # tentativi.}}"</string> + <string name="kg_password_default_puk_message" msgid="1025139786449741950">"{count,plural, =1{La scheda SIM è ora disattivata. Inserisci il codice PUK per continuare. Hai ancora # tentativo a disposizione prima che la SIM diventi definitivamente inutilizzabile. Per informazioni dettagliate, contatta l\'operatore.}many{La scheda SIM è ora disattivata. Inserisci il codice PUK per continuare. Hai ancora # tentativi a disposizione prima che la SIM diventi definitivamente inutilizzabile. Per informazioni dettagliate, contatta l\'operatore.}other{La scheda SIM è ora disattivata. Inserisci il codice PUK per continuare. Hai ancora # tentativi a disposizione prima che la SIM diventi definitivamente inutilizzabile. Per informazioni dettagliate, contatta l\'operatore.}}"</string> <string name="clock_title_default" msgid="6342735240617459864">"Predefinito"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Bolla"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Analogico"</string> diff --git a/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml b/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml index 76ced1251358..b9348260d40e 100644 --- a/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml +++ b/packages/SystemUI/res-keyguard/values-pt-rBR/strings.xml @@ -53,7 +53,7 @@ <string name="kg_wrong_pattern" msgid="5907301342430102842">"Padrão incorreto"</string> <string name="kg_wrong_password" msgid="4143127991071670512">"Senha incorreta"</string> <string name="kg_wrong_pin" msgid="4160978845968732624">"PIN incorreto"</string> - <string name="kg_too_many_failed_attempts_countdown" msgid="2038195171919795529">"{count,plural, =1{Tente novamente em # segundo.}one{Tente novamente em # segundo.}other{Tente novamente em # segundos.}}"</string> + <string name="kg_too_many_failed_attempts_countdown" msgid="2038195171919795529">"{count,plural, =1{Tente novamente em # segundo.}one{Tente novamente em # segundo.}many{Tente novamente em # segundos.}other{Tente novamente em # segundos.}}"</string> <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Informe o PIN do chip."</string> <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Informe o PIN do chip para \"<xliff:g id="CARRIER">%1$s</xliff:g>\"."</string> <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Desative o eSIM para usar o dispositivo sem serviço móvel."</string> @@ -68,9 +68,9 @@ <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Você digitou sua senha incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. \n\nTente novamente em <xliff:g id="NUMBER_1">%2$d</xliff:g> segundos."</string> <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Você desenhou sua sequência de desbloqueio incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. \n\nTente novamente em <xliff:g id="NUMBER_1">%2$d</xliff:g> segundos."</string> <string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Código PIN do chip incorreto. Entre em contato com a operadora para desbloquear o dispositivo."</string> - <string name="kg_password_wrong_pin_code" msgid="5629415765976820357">"{count,plural, =1{Código PIN do chip incorreto. Você tem # tentativa restante. Se o código correto não for digitado, será necessário entrar em contato com a operadora para desbloquear o dispositivo.}one{Código PIN do chip incorreto. Você tem # tentativa restante. }other{Código PIN do chip incorreto. Você tem # tentativas restantes. }}"</string> + <string name="kg_password_wrong_pin_code" msgid="5629415765976820357">"{count,plural, =1{Código PIN do chip incorreto. Você tem # tentativa restante. Se o código correto não for digitado, será necessário entrar em contato com a operadora para desbloquear o dispositivo.}one{Código PIN do chip incorreto. Você tem # tentativa restante. }many{Código PIN do chip incorreto. Você tem # de tentativas restantes. }other{Código PIN do chip incorreto. Você tem # tentativas restantes. }}"</string> <string name="kg_password_wrong_puk_code_dead" msgid="3698285357028468617">"O chip não pode ser utilizado. Entre em contato com a operadora."</string> - <string name="kg_password_wrong_puk_code" msgid="6820515467645087827">"{count,plural, =1{Código PUK do chip incorreto. Você tem # tentativa restante. Se o código correto não for digitado, o chip vai ficar permanentemente inutilizável.}one{Código PUK do chip incorreto. Você tem # tentativa restante. Se o código correto não for digitado, o chip vai ficar permanentemente inutilizável.}other{Código PUK do chip incorreto. Você tem # tentativas restantes. Se o código correto não for digitado, o chip vai ficar permanentemente inutilizável.}}"</string> + <string name="kg_password_wrong_puk_code" msgid="6820515467645087827">"{count,plural, =1{Código PUK do chip incorreto. Você tem # tentativa restante. Se o código correto não for digitado, o chip vai ficar permanentemente inutilizável.}one{Código PUK do chip incorreto. Você tem # tentativa restante. Se o código correto não for digitado, o chip vai ficar permanentemente inutilizável.}many{Código PUK do chip incorreto. Você tem # de tentativas restantes. Se o código correto não for digitado, o chip vai ficar permanentemente inutilizável.}other{Código PUK do chip incorreto. Você tem # tentativas restantes. Se o código correto não for digitado, o chip vai ficar permanentemente inutilizável.}}"</string> <string name="kg_password_pin_failed" msgid="5136259126330604009">"Falha na operação de PIN do chip."</string> <string name="kg_password_puk_failed" msgid="6778867411556937118">"Falha na operação de PUK do chip."</string> <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Alterar o método de entrada"</string> @@ -85,8 +85,8 @@ <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"O dispositivo foi bloqueado manualmente"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Não reconhecido"</string> <string name="kg_face_sensor_privacy_enabled" msgid="939511161763558512">"Para usar o Desbloqueio facial, ative o acesso à câmera nas Configurações"</string> - <string name="kg_password_default_pin_message" msgid="1434544655827987873">"{count,plural, =1{Informe o PIN do chip. Você tem # tentativa restante antes de precisar entrar em contato com a operadora para desbloquear seu dispositivo.}one{Informe o PIN do chip. Você tem # tentativa restante.}other{Informe o PIN do chip. Você tem # tentativas restantes.}}"</string> - <string name="kg_password_default_puk_message" msgid="1025139786449741950">"{count,plural, =1{O chip está desativado. Informe o código PUK para continuar. Você tem # tentativa restante antes que o chip fique permanentemente inutilizável. Consulte sua operadora para saber mais.}one{O chip está desativado. Informe o código PUK para continuar. Você tem # tentativa restante antes que o chip fique permanentemente inutilizável. Consulte sua operadora para saber mais.}other{O chip está desativado. Informe o código PUK para continuar. Você tem # tentativas restantes antes que o chip fique permanentemente inutilizável. Consulte sua operadora para saber mais.}}"</string> + <string name="kg_password_default_pin_message" msgid="1434544655827987873">"{count,plural, =1{Informe o PIN do chip. Você tem # tentativa restante antes de precisar entrar em contato com a operadora para desbloquear seu dispositivo.}one{Informe o PIN do chip. Você tem # tentativa restante.}many{Informe o PIN do chip. Você tem # de tentativas restantes.}other{Informe o PIN do chip. Você tem # tentativas restantes.}}"</string> + <string name="kg_password_default_puk_message" msgid="1025139786449741950">"{count,plural, =1{O chip está desativado. Informe o código PUK para continuar. Você tem # tentativa restante antes que o chip fique permanentemente inutilizável. Consulte sua operadora para saber mais.}one{O chip está desativado. Informe o código PUK para continuar. Você tem # tentativa restante antes que o chip fique permanentemente inutilizável. Consulte sua operadora para saber mais.}many{O chip está desativado. Informe o código PUK para continuar. Você tem # de tentativas restantes antes que o chip fique permanentemente inutilizável. Consulte sua operadora para saber mais.}other{O chip está desativado. Informe o código PUK para continuar. Você tem # tentativas restantes antes que o chip fique permanentemente inutilizável. Consulte sua operadora para saber mais.}}"</string> <string name="clock_title_default" msgid="6342735240617459864">"Padrão"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Bolha"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Analógico"</string> diff --git a/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml b/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml index 94afc5f3678b..a67bfb020a3c 100644 --- a/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml +++ b/packages/SystemUI/res-keyguard/values-pt-rPT/strings.xml @@ -53,7 +53,7 @@ <string name="kg_wrong_pattern" msgid="5907301342430102842">"Padrão incorreto."</string> <string name="kg_wrong_password" msgid="4143127991071670512">"Palavra-passe incorreta."</string> <string name="kg_wrong_pin" msgid="4160978845968732624">"PIN incorreto"</string> - <string name="kg_too_many_failed_attempts_countdown" msgid="2038195171919795529">"{count,plural, =1{Tente novamente dentro de # segundo.}other{Tente novamente dentro de # segundos.}}"</string> + <string name="kg_too_many_failed_attempts_countdown" msgid="2038195171919795529">"{count,plural, =1{Tente novamente dentro de # segundo.}many{Tente novamente dentro de # segundos.}other{Tente novamente dentro de # segundos.}}"</string> <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Introduza o PIN do cartão SIM."</string> <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Introduza o PIN do cartão SIM \"<xliff:g id="CARRIER">%1$s</xliff:g>\"."</string> <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Desative o eSIM para utilizar o dispositivo sem serviço móvel."</string> @@ -68,9 +68,9 @@ <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Introduziu a palavra-passe incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. \n\nTente novamente dentro de <xliff:g id="NUMBER_1">%2$d</xliff:g> segundos."</string> <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Desenhou a sua padrão de desbloqueio incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. \n\nTente novamente dentro de <xliff:g id="NUMBER_1">%2$d</xliff:g> segundos."</string> <string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Código PIN do cartão SIM incorreto. Tem de contactar o seu operador para desbloquear o dispositivo."</string> - <string name="kg_password_wrong_pin_code" msgid="5629415765976820357">"{count,plural, =1{Código PIN do SIM incorreto. Tem mais # tentativa antes de ser necessário contactar o operador para desbloquear o dispositivo.}other{Código PIN do SIM incorreto. Tem mais # tentativas. }}"</string> + <string name="kg_password_wrong_pin_code" msgid="5629415765976820357">"{count,plural, =1{Código PIN do SIM incorreto. Tem mais # tentativa antes de ser necessário contactar o operador para desbloquear o dispositivo.}many{Código PIN do SIM incorreto. Tem mais # tentativas. }other{Código PIN do SIM incorreto. Tem mais # tentativas. }}"</string> <string name="kg_password_wrong_puk_code_dead" msgid="3698285357028468617">"Cartão SIM inutilizável. Contacte o seu operador."</string> - <string name="kg_password_wrong_puk_code" msgid="6820515467645087827">"{count,plural, =1{Código PUK do SIM incorreto. Tem mais # tentativa antes de o SIM ficar permanentemente inutilizável.}other{Código PUK do SIM incorreto. Tem mais # tentativas antes de o SIM ficar permanentemente inutilizável.}}"</string> + <string name="kg_password_wrong_puk_code" msgid="6820515467645087827">"{count,plural, =1{Código PUK do SIM incorreto. Tem mais # tentativa antes de o SIM ficar permanentemente inutilizável.}many{Código PUK do SIM incorreto. Tem mais # tentativas antes de o SIM ficar permanentemente inutilizável.}other{Código PUK do SIM incorreto. Tem mais # tentativas antes de o SIM ficar permanentemente inutilizável.}}"</string> <string name="kg_password_pin_failed" msgid="5136259126330604009">"Falha ao introduzir o PIN do cartão SIM!"</string> <string name="kg_password_puk_failed" msgid="6778867411556937118">"Falha ao introduzir o PUK do cartão SIM!"</string> <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Alternar o método de introdução"</string> @@ -85,8 +85,8 @@ <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"O dispositivo foi bloqueado manualmente"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Não reconhecido."</string> <string name="kg_face_sensor_privacy_enabled" msgid="939511161763558512">"Ative acesso à câmara nas Def. p/ usar Desbl. facial"</string> - <string name="kg_password_default_pin_message" msgid="1434544655827987873">"{count,plural, =1{Introduza o PIN do SIM. Tem mais # tentativa antes de ser necessário contactar o operador para desbloquear o dispositivo.}other{Introduza o PIN do SIM. Tem mais # tentativas.}}"</string> - <string name="kg_password_default_puk_message" msgid="1025139786449741950">"{count,plural, =1{O SIM está desativado. Introduza o código PUK para continuar. Tem mais # tentativa antes de o SIM ficar permanentemente inutilizável. Contacte o operador para obter mais detalhes.}other{O SIM está desativado. Introduza o código PUK para continuar. Tem mais # tentativas antes de o SIM ficar permanentemente inutilizável. Contacte o operador para obter mais detalhes.}}"</string> + <string name="kg_password_default_pin_message" msgid="1434544655827987873">"{count,plural, =1{Introduza o PIN do SIM. Tem mais # tentativa antes de ser necessário contactar o operador para desbloquear o dispositivo.}many{Introduza o PIN do SIM. Tem mais # tentativas.}other{Introduza o PIN do SIM. Tem mais # tentativas.}}"</string> + <string name="kg_password_default_puk_message" msgid="1025139786449741950">"{count,plural, =1{O SIM está desativado. Introduza o código PUK para continuar. Tem mais # tentativa antes de o SIM ficar permanentemente inutilizável. Contacte o operador para obter mais detalhes.}many{O SIM está desativado. Introduza o código PUK para continuar. Tem mais # tentativas antes de o SIM ficar permanentemente inutilizável. Contacte o operador para obter mais detalhes.}other{O SIM está desativado. Introduza o código PUK para continuar. Tem mais # tentativas antes de o SIM ficar permanentemente inutilizável. Contacte o operador para obter mais detalhes.}}"</string> <string name="clock_title_default" msgid="6342735240617459864">"Predefinido"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Balão"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Analógico"</string> diff --git a/packages/SystemUI/res-keyguard/values-pt/strings.xml b/packages/SystemUI/res-keyguard/values-pt/strings.xml index 76ced1251358..b9348260d40e 100644 --- a/packages/SystemUI/res-keyguard/values-pt/strings.xml +++ b/packages/SystemUI/res-keyguard/values-pt/strings.xml @@ -53,7 +53,7 @@ <string name="kg_wrong_pattern" msgid="5907301342430102842">"Padrão incorreto"</string> <string name="kg_wrong_password" msgid="4143127991071670512">"Senha incorreta"</string> <string name="kg_wrong_pin" msgid="4160978845968732624">"PIN incorreto"</string> - <string name="kg_too_many_failed_attempts_countdown" msgid="2038195171919795529">"{count,plural, =1{Tente novamente em # segundo.}one{Tente novamente em # segundo.}other{Tente novamente em # segundos.}}"</string> + <string name="kg_too_many_failed_attempts_countdown" msgid="2038195171919795529">"{count,plural, =1{Tente novamente em # segundo.}one{Tente novamente em # segundo.}many{Tente novamente em # segundos.}other{Tente novamente em # segundos.}}"</string> <string name="kg_sim_pin_instructions" msgid="1942424305184242951">"Informe o PIN do chip."</string> <string name="kg_sim_pin_instructions_multi" msgid="3639863309953109649">"Informe o PIN do chip para \"<xliff:g id="CARRIER">%1$s</xliff:g>\"."</string> <string name="kg_sim_lock_esim_instructions" msgid="5577169988158738030">"<xliff:g id="PREVIOUS_MSG">%1$s</xliff:g> Desative o eSIM para usar o dispositivo sem serviço móvel."</string> @@ -68,9 +68,9 @@ <string name="kg_too_many_failed_password_attempts_dialog_message" msgid="190984061975729494">"Você digitou sua senha incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. \n\nTente novamente em <xliff:g id="NUMBER_1">%2$d</xliff:g> segundos."</string> <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="4252405904570284368">"Você desenhou sua sequência de desbloqueio incorretamente <xliff:g id="NUMBER_0">%1$d</xliff:g> vezes. \n\nTente novamente em <xliff:g id="NUMBER_1">%2$d</xliff:g> segundos."</string> <string name="kg_password_wrong_pin_code_pukked" msgid="8047350661459040581">"Código PIN do chip incorreto. Entre em contato com a operadora para desbloquear o dispositivo."</string> - <string name="kg_password_wrong_pin_code" msgid="5629415765976820357">"{count,plural, =1{Código PIN do chip incorreto. Você tem # tentativa restante. Se o código correto não for digitado, será necessário entrar em contato com a operadora para desbloquear o dispositivo.}one{Código PIN do chip incorreto. Você tem # tentativa restante. }other{Código PIN do chip incorreto. Você tem # tentativas restantes. }}"</string> + <string name="kg_password_wrong_pin_code" msgid="5629415765976820357">"{count,plural, =1{Código PIN do chip incorreto. Você tem # tentativa restante. Se o código correto não for digitado, será necessário entrar em contato com a operadora para desbloquear o dispositivo.}one{Código PIN do chip incorreto. Você tem # tentativa restante. }many{Código PIN do chip incorreto. Você tem # de tentativas restantes. }other{Código PIN do chip incorreto. Você tem # tentativas restantes. }}"</string> <string name="kg_password_wrong_puk_code_dead" msgid="3698285357028468617">"O chip não pode ser utilizado. Entre em contato com a operadora."</string> - <string name="kg_password_wrong_puk_code" msgid="6820515467645087827">"{count,plural, =1{Código PUK do chip incorreto. Você tem # tentativa restante. Se o código correto não for digitado, o chip vai ficar permanentemente inutilizável.}one{Código PUK do chip incorreto. Você tem # tentativa restante. Se o código correto não for digitado, o chip vai ficar permanentemente inutilizável.}other{Código PUK do chip incorreto. Você tem # tentativas restantes. Se o código correto não for digitado, o chip vai ficar permanentemente inutilizável.}}"</string> + <string name="kg_password_wrong_puk_code" msgid="6820515467645087827">"{count,plural, =1{Código PUK do chip incorreto. Você tem # tentativa restante. Se o código correto não for digitado, o chip vai ficar permanentemente inutilizável.}one{Código PUK do chip incorreto. Você tem # tentativa restante. Se o código correto não for digitado, o chip vai ficar permanentemente inutilizável.}many{Código PUK do chip incorreto. Você tem # de tentativas restantes. Se o código correto não for digitado, o chip vai ficar permanentemente inutilizável.}other{Código PUK do chip incorreto. Você tem # tentativas restantes. Se o código correto não for digitado, o chip vai ficar permanentemente inutilizável.}}"</string> <string name="kg_password_pin_failed" msgid="5136259126330604009">"Falha na operação de PIN do chip."</string> <string name="kg_password_puk_failed" msgid="6778867411556937118">"Falha na operação de PUK do chip."</string> <string name="accessibility_ime_switch_button" msgid="9082358310194861329">"Alterar o método de entrada"</string> @@ -85,8 +85,8 @@ <string name="kg_prompt_reason_user_request" msgid="6015774877733717904">"O dispositivo foi bloqueado manualmente"</string> <string name="kg_face_not_recognized" msgid="7903950626744419160">"Não reconhecido"</string> <string name="kg_face_sensor_privacy_enabled" msgid="939511161763558512">"Para usar o Desbloqueio facial, ative o acesso à câmera nas Configurações"</string> - <string name="kg_password_default_pin_message" msgid="1434544655827987873">"{count,plural, =1{Informe o PIN do chip. Você tem # tentativa restante antes de precisar entrar em contato com a operadora para desbloquear seu dispositivo.}one{Informe o PIN do chip. Você tem # tentativa restante.}other{Informe o PIN do chip. Você tem # tentativas restantes.}}"</string> - <string name="kg_password_default_puk_message" msgid="1025139786449741950">"{count,plural, =1{O chip está desativado. Informe o código PUK para continuar. Você tem # tentativa restante antes que o chip fique permanentemente inutilizável. Consulte sua operadora para saber mais.}one{O chip está desativado. Informe o código PUK para continuar. Você tem # tentativa restante antes que o chip fique permanentemente inutilizável. Consulte sua operadora para saber mais.}other{O chip está desativado. Informe o código PUK para continuar. Você tem # tentativas restantes antes que o chip fique permanentemente inutilizável. Consulte sua operadora para saber mais.}}"</string> + <string name="kg_password_default_pin_message" msgid="1434544655827987873">"{count,plural, =1{Informe o PIN do chip. Você tem # tentativa restante antes de precisar entrar em contato com a operadora para desbloquear seu dispositivo.}one{Informe o PIN do chip. Você tem # tentativa restante.}many{Informe o PIN do chip. Você tem # de tentativas restantes.}other{Informe o PIN do chip. Você tem # tentativas restantes.}}"</string> + <string name="kg_password_default_puk_message" msgid="1025139786449741950">"{count,plural, =1{O chip está desativado. Informe o código PUK para continuar. Você tem # tentativa restante antes que o chip fique permanentemente inutilizável. Consulte sua operadora para saber mais.}one{O chip está desativado. Informe o código PUK para continuar. Você tem # tentativa restante antes que o chip fique permanentemente inutilizável. Consulte sua operadora para saber mais.}many{O chip está desativado. Informe o código PUK para continuar. Você tem # de tentativas restantes antes que o chip fique permanentemente inutilizável. Consulte sua operadora para saber mais.}other{O chip está desativado. Informe o código PUK para continuar. Você tem # tentativas restantes antes que o chip fique permanentemente inutilizável. Consulte sua operadora para saber mais.}}"</string> <string name="clock_title_default" msgid="6342735240617459864">"Padrão"</string> <string name="clock_title_bubble" msgid="2204559396790593213">"Bolha"</string> <string name="clock_title_analog" msgid="8409262532900918273">"Analógico"</string> diff --git a/packages/SystemUI/res-keyguard/values-sw600dp/dimens.xml b/packages/SystemUI/res-keyguard/values-sw600dp/dimens.xml index e80cfafdd71a..a1068c65bae2 100644 --- a/packages/SystemUI/res-keyguard/values-sw600dp/dimens.xml +++ b/packages/SystemUI/res-keyguard/values-sw600dp/dimens.xml @@ -31,8 +31,4 @@ <!-- Overload default clock widget parameters --> <dimen name="widget_big_font_size">100dp</dimen> <dimen name="widget_label_font_size">18sp</dimen> - - <!-- EmergencyCarrierArea overlap - amount to overlap the emergency button and carrier text. - Should be 0 on devices with plenty of room (e.g. tablets) --> - <dimen name="eca_overlap">0dip</dimen> </resources> diff --git a/packages/SystemUI/res-keyguard/values/dimens.xml b/packages/SystemUI/res-keyguard/values/dimens.xml index 32871f0abb4f..46f6ab2399d1 100644 --- a/packages/SystemUI/res-keyguard/values/dimens.xml +++ b/packages/SystemUI/res-keyguard/values/dimens.xml @@ -44,10 +44,6 @@ <dimen name="keyguard_eca_top_margin">18dp</dimen> <dimen name="keyguard_eca_bottom_margin">12dp</dimen> - <!-- EmergencyCarrierArea overlap - amount to overlap the emergency button and carrier text. - Should be 0 on devices with plenty of room (e.g. tablets) --> - <dimen name="eca_overlap">-10dip</dimen> - <!-- Slice header --> <dimen name="widget_title_font_size">20dp</dimen> <dimen name="widget_title_line_height">24dp</dimen> @@ -84,6 +80,10 @@ <!-- The translation for disappearing security views after having solved them. --> <dimen name="disappear_y_translation">-32dp</dimen> + <!-- Dimens for animation for the Bouncer PIN view --> + <dimen name="pin_view_trans_y_entry">120dp</dimen> + <dimen name="pin_view_trans_y_entry_offset">10dp</dimen> + <!-- Spacing around each button used for PIN view --> <dimen name="num_pad_key_width">72dp</dimen> <dimen name="num_pad_entry_row_margin_bottom">12dp</dimen> diff --git a/packages/SystemUI/res-keyguard/values/styles.xml b/packages/SystemUI/res-keyguard/values/styles.xml index 625ffd3aa3ec..a1d12668d27a 100644 --- a/packages/SystemUI/res-keyguard/values/styles.xml +++ b/packages/SystemUI/res-keyguard/values/styles.xml @@ -50,7 +50,7 @@ <item name="android:background">@null</item> <item name="android:textSize">32sp</item> <item name="android:textColor">?android:attr/textColorPrimary</item> - <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item> + <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item> <item name="android:paddingBottom">-16dp</item> </style> <style name="Widget.TextView.Password" parent="@android:style/Widget.TextView"> diff --git a/packages/SystemUI/res/drawable/ic_no_sim.xml b/packages/SystemUI/res/drawable/ic_no_sim.xml new file mode 100644 index 000000000000..ccfb6ea642cc --- /dev/null +++ b/packages/SystemUI/res/drawable/ic_no_sim.xml @@ -0,0 +1,10 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24" + android:tint="?attr/colorControlNormal"> + <path + android:fillColor="@android:color/white" + android:pathData="M20,17.175 L18,15.175V4Q18,4 18,4Q18,4 18,4H10.85L8.85,6L7.4,4.6L10,2H18Q18.825,2 19.413,2.587Q20,3.175 20,4ZM20.5,23.3 L6,8.8V20Q6,20 6,20Q6,20 6,20H18Q18,20 18,20Q18,20 18,20V17.975L20,19.975V20Q20,20.825 19.413,21.413Q18.825,22 18,22H6Q5.175,22 4.588,21.413Q4,20.825 4,20V8L4.6,7.4L0.7,3.5L2.125,2.1L21.9,21.875ZM13.525,10.675Q13.525,10.675 13.525,10.675Q13.525,10.675 13.525,10.675ZM11.65,14.475Q11.65,14.475 11.65,14.475Q11.65,14.475 11.65,14.475Q11.65,14.475 11.65,14.475Q11.65,14.475 11.65,14.475Z"/> +</vector> diff --git a/packages/SystemUI/res/drawable/media_output_dialog_background.xml b/packages/SystemUI/res/drawable/media_output_dialog_background.xml new file mode 100644 index 000000000000..40bfd83038af --- /dev/null +++ b/packages/SystemUI/res/drawable/media_output_dialog_background.xml @@ -0,0 +1,22 @@ +<!-- + ~ Copyright (C) 2021 The Android Open Source Project + ~ + ~ Licensed under the Apache License, Version 2.0 (the "License"); + ~ you may not use this file except in compliance with the License. + ~ You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<shape xmlns:android="http://schemas.android.com/apk/res/android" + android:shape="rectangle"> + <corners + android:radius="28dp"/> + <solid android:color="@color/media_dialog_background" /> +</shape>
\ No newline at end of file diff --git a/packages/SystemUI/res/drawable/media_seekbar_thumb.xml b/packages/SystemUI/res/drawable/media_seekbar_thumb.xml new file mode 100644 index 000000000000..5eb2bfdbee39 --- /dev/null +++ b/packages/SystemUI/res/drawable/media_seekbar_thumb.xml @@ -0,0 +1,50 @@ +<!-- + ~ 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. + --> + +<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:aapt="http://schemas.android.com/aapt"> + <aapt:attr name="android:drawable"> + <vector android:height="16dp" + android:width="4dp" + android:viewportHeight="16" + android:viewportWidth="4"> + <group android:name="_R_G"> + <group android:name="_R_G_L_0_G" + android:translateX="2" + android:translateY="8"> + <path android:name="_R_G_L_0_G_D_0_P_0" + android:fillColor="#ffffff" + android:fillAlpha="1" + android:fillType="nonZero" + android:pathData=" M2 -6 C2,-6 2,6 2,6 C2,7.1 1.1,8 0,8 C0,8 0,8 0,8 C-1.1,8 -2,7.1 -2,6 C-2,6 -2,-6 -2,-6 C-2,-7.1 -1.1,-8 0,-8 C0,-8 0,-8 0,-8 C1.1,-8 2,-7.1 2,-6c "/> + </group> + </group> + <group android:name="time_group"/> + </vector> + </aapt:attr> + <target android:name="time_group"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator android:propertyName="translateX" + android:duration="1017" + android:startOffset="0" + android:valueFrom="0" + android:valueTo="1" + android:valueType="floatType"/> + </set> + </aapt:attr> + </target> +</animated-vector> diff --git a/packages/SystemUI/res/drawable/qs_data_saver_icon_off.xml b/packages/SystemUI/res/drawable/qs_data_saver_icon_off.xml new file mode 100644 index 000000000000..57777a670d33 --- /dev/null +++ b/packages/SystemUI/res/drawable/qs_data_saver_icon_off.xml @@ -0,0 +1,84 @@ +<?xml version="1.0" encoding="utf-8"?><!-- + ~ 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. + --> +<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:aapt="http://schemas.android.com/aapt"> + <target android:name="_R_G_L_1_G_D_0_P_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:duration="133" + android:propertyName="fillAlpha" + android:startOffset="0" + android:valueFrom="1" + android:valueTo="0" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="time_group"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:duration="150" + android:propertyName="translateX" + android:startOffset="0" + android:valueFrom="0" + android:valueTo="1" + android:valueType="floatType" /> + </set> + </aapt:attr> + </target> + <aapt:attr name="android:drawable"> + <vector + android:width="24dp" + android:height="24dp" + android:viewportHeight="24" + android:viewportWidth="24"> + <group android:name="_R_G"> + <group + android:name="_R_G_L_1_G" + android:pivotY="1" + android:rotation="180" + android:translateX="12" + android:translateY="10.984"> + <path + android:name="_R_G_L_1_G_D_0_P_0" + android:fillAlpha="1" + android:fillColor="#ffffff" + android:fillType="nonZero" + android:pathData=" M3 2 C3,2 1,2 1,2 C1,2 1,4 1,4 C1,4 -1,4 -1,4 C-1,4 -1,2 -1,2 C-1,2 -3,2 -3,2 C-3,2 -3,0 -3,0 C-3,0 -1,0 -1,0 C-1,0 -1,-2 -1,-2 C-1,-2 1,-2 1,-2 C1,-2 1,0 1,0 C1,0 3,0 3,0 C3,0 3,2 3,2c " /> + </group> + <group + android:name="_R_G_L_0_G" + android:rotation="1440" + android:translateX="12" + android:translateY="12"> + <path + android:name="_R_G_L_0_G_D_0_P_0" + android:fillAlpha="1" + android:fillColor="#ffffff" + android:fillType="nonZero" + android:pathData=" M9.15 4.05 C9.15,4.05 6.55,2.55 6.55,2.55 C6.7,2.13 6.81,1.71 6.89,1.29 C6.96,0.86 7,0.43 7,0 C7,-1.77 6.43,-3.31 5.3,-4.62 C4.17,-5.94 2.73,-6.72 1,-6.95 C1,-6.95 1,-9.95 1,-9.95 C3.57,-9.7 5.71,-8.62 7.43,-6.72 C9.14,-4.82 10,-2.58 10,0 C10,0.7 9.94,1.39 9.81,2.08 C9.69,2.76 9.47,3.42 9.15,4.05c M0 10 C-1.38,10 -2.68,9.74 -3.9,9.21 C-5.12,8.69 -6.17,7.98 -7.07,7.08 C-7.97,6.18 -8.69,5.12 -9.21,3.9 C-9.74,2.68 -10,1.38 -10,0 C-10,-2.58 -9.14,-4.82 -7.42,-6.72 C-5.71,-8.62 -3.57,-9.7 -1,-9.95 C-1,-9.95 -1,-6.95 -1,-6.95 C-2.73,-6.72 -4.17,-5.94 -5.3,-4.62 C-6.43,-3.31 -7,-1.77 -7,0 C-7,1.95 -6.32,3.6 -4.96,4.96 C-3.6,6.32 -1.95,7 0,7 C1.07,7 2.08,6.78 3.04,6.33 C4,5.88 4.82,5.23 5.5,4.4 C5.5,4.4 8.1,5.9 8.1,5.9 C7.15,7.2 5.97,8.21 4.55,8.93 C3.13,9.64 1.62,10 0,10c " /> + </group> + </group> + <group android:name="time_group" /> + </vector> + </aapt:attr> +</animated-vector> diff --git a/packages/SystemUI/res/drawable/qs_data_saver_icon_on.xml b/packages/SystemUI/res/drawable/qs_data_saver_icon_on.xml new file mode 100644 index 000000000000..b3764137793a --- /dev/null +++ b/packages/SystemUI/res/drawable/qs_data_saver_icon_on.xml @@ -0,0 +1,110 @@ +<?xml version="1.0" encoding="utf-8"?><!-- + ~ 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. + --> +<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:aapt="http://schemas.android.com/aapt"> + <target android:name="_R_G_L_1_G_D_0_P_0"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:duration="333" + android:propertyName="pathData" + android:startOffset="0" + android:valueFrom="M1.02 2 C1.02,2 1,2 1,2 C1,2 1,1.98 1,1.98 C1,1.98 -1,1.98 -1,1.98 C-1,1.98 -1,2 -1,2 C-1,2 -1,2 -1,2 C-1,2 -1,0 -1,0 C-1,0 -1,0 -1,0 C-1,0 -1,0 -1,0 C-1,0 1,0 1,0 C1,0 1,0 1,0 C1,0 1.02,0 1.02,0 C1.02,0 1.02,2 1.02,2c " + android:valueTo="M3 2 C3,2 1,2 1,2 C1,2 1,4 1,4 C1,4 -1,4 -1,4 C-1,4 -1,2 -1,2 C-1,2 -3,2 -3,2 C-3,2 -3,0 -3,0 C-3,0 -1,0 -1,0 C-1,0 -1,-2 -1,-2 C-1,-2 1,-2 1,-2 C1,-2 1,0 1,0 C1,0 3,0 3,0 C3,0 3,2 3,2c " + android:valueType="pathType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.2,0.2 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_0_G"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:duration="500" + android:propertyName="rotation" + android:startOffset="0" + android:valueFrom="0" + android:valueTo="613.191" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.086,0.422 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + <objectAnimator + android:duration="417" + android:propertyName="rotation" + android:startOffset="500" + android:valueFrom="613.191" + android:valueTo="720" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.334,1.012 0.833,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="time_group"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:duration="933" + android:propertyName="translateX" + android:startOffset="0" + android:valueFrom="0" + android:valueTo="1" + android:valueType="floatType" /> + </set> + </aapt:attr> + </target> + <aapt:attr name="android:drawable"> + <vector + android:width="24dp" + android:height="24dp" + android:viewportHeight="24" + android:viewportWidth="24"> + <group android:name="_R_G"> + <group + android:name="_R_G_L_1_G" + android:translateX="12" + android:translateY="10.75"> + <path + android:name="_R_G_L_1_G_D_0_P_0" + android:fillAlpha="1" + android:fillColor="#ffffff" + android:fillType="nonZero" + android:pathData=" M1.02 2 C1.02,2 1,2 1,2 C1,2 1,1.98 1,1.98 C1,1.98 -1,1.98 -1,1.98 C-1,1.98 -1,2 -1,2 C-1,2 -1,2 -1,2 C-1,2 -1,0 -1,0 C-1,0 -1,0 -1,0 C-1,0 -1,0 -1,0 C-1,0 1,0 1,0 C1,0 1,0 1,0 C1,0 1.02,0 1.02,0 C1.02,0 1.02,2 1.02,2c " /> + </group> + <group + android:name="_R_G_L_0_G" + android:rotation="0" + android:translateX="12" + android:translateY="12"> + <path + android:name="_R_G_L_0_G_D_0_P_0" + android:fillAlpha="1" + android:fillColor="#ffffff" + android:fillType="nonZero" + android:pathData=" M9.15 4.05 C9.15,4.05 6.55,2.55 6.55,2.55 C6.7,2.13 6.81,1.71 6.89,1.29 C6.96,0.86 7,0.43 7,0 C7,-1.77 6.43,-3.31 5.3,-4.62 C4.17,-5.94 2.73,-6.72 1,-6.95 C1,-6.95 1,-9.95 1,-9.95 C3.57,-9.7 5.71,-8.62 7.43,-6.72 C9.14,-4.82 10,-2.58 10,0 C10,0.7 9.94,1.39 9.81,2.08 C9.69,2.76 9.47,3.42 9.15,4.05c M0 10 C-1.38,10 -2.68,9.74 -3.9,9.21 C-5.12,8.69 -6.17,7.98 -7.07,7.08 C-7.97,6.18 -8.69,5.12 -9.21,3.9 C-9.74,2.68 -10,1.38 -10,0 C-10,-2.58 -9.14,-4.82 -7.42,-6.72 C-5.71,-8.62 -3.57,-9.7 -1,-9.95 C-1,-9.95 -1,-6.95 -1,-6.95 C-2.73,-6.72 -4.17,-5.94 -5.3,-4.62 C-6.43,-3.31 -7,-1.77 -7,0 C-7,1.95 -6.32,3.6 -4.96,4.96 C-3.6,6.32 -1.95,7 0,7 C1.07,7 2.08,6.78 3.04,6.33 C4,5.88 4.82,5.23 5.5,4.4 C5.5,4.4 8.1,5.9 8.1,5.9 C7.15,7.2 5.97,8.21 4.55,8.93 C3.13,9.64 1.62,10 0,10c " /> + </group> + </group> + <group android:name="time_group" /> + </vector> + </aapt:attr> +</animated-vector> diff --git a/packages/SystemUI/res/drawable/qs_nightlight_icon_off.xml b/packages/SystemUI/res/drawable/qs_nightlight_icon_off.xml new file mode 100644 index 000000000000..0769a85dae49 --- /dev/null +++ b/packages/SystemUI/res/drawable/qs_nightlight_icon_off.xml @@ -0,0 +1,94 @@ +<?xml version="1.0" encoding="utf-8"?><!-- + 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. +--> +<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:aapt="http://schemas.android.com/aapt"> + <target android:name="_R_G_L_0_G_T_1"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:duration="283" + android:propertyName="translateY" + android:startOffset="0" + android:valueFrom="12.125" + android:valueTo="12.312" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.3,0 0.1,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_0_G_T_1"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:duration="283" + android:propertyName="rotation" + android:startOffset="0" + android:valueFrom="-45" + android:valueTo="0" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.3,0 0.1,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="time_group"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:duration="300" + android:propertyName="translateX" + android:startOffset="0" + android:valueFrom="0" + android:valueTo="1" + android:valueType="floatType" /> + </set> + </aapt:attr> + </target> + <aapt:attr name="android:drawable"> + <vector + android:width="24dp" + android:height="24dp" + android:viewportHeight="24" + android:viewportWidth="24"> + <group android:name="_R_G"> + <group + android:name="_R_G_L_0_G_T_1" + android:rotation="-45" + android:translateX="12.875" + android:translateY="12.125"> + <group + android:name="_R_G_L_0_G" + android:translateX="-2.375"> + <path + android:name="_R_G_L_0_G_D_0_P_0" + android:pathData=" M3.33 8.62 C2.09,8.68 0.59,8.47 -0.64,7.95 C-1.65,7.53 -2.75,6.9 -3.59,6.09 C-4.38,5.32 -5.19,4.17 -5.61,3.08 C-6.04,1.99 -6.25,0.83 -6.25,-0.39 C-6.25,-1.72 -5.98,-2.85 -5.55,-3.94 C-5.13,-5.02 -4.37,-6 -3.59,-6.78 C-2.63,-7.75 -1.63,-8.28 -0.52,-8.77 C0.48,-9.2 2.04,-9.41 3.15,-9.38 C4.22,-9.35 4.94,-9.16 5.81,-8.79 C5.95,-8.73 6.28,-8.6 6.18,-8.55 C3.44,-6.63 1.83,-3.66 1.83,-0.39 C1.83,2.53 3.47,5.72 6.15,7.86 C6.16,7.9 6.03,7.97 5.91,8.04 C5.12,8.44 4.31,8.56 3.33,8.62c " + android:strokeAlpha="1" + android:strokeColor="#ffffff" + android:strokeLineCap="round" + android:strokeLineJoin="round" + android:strokeWidth="2" /> + </group> + </group> + </group> + <group android:name="time_group" /> + </vector> + </aapt:attr> +</animated-vector> diff --git a/packages/SystemUI/res/drawable/qs_nightlight_icon_on.xml b/packages/SystemUI/res/drawable/qs_nightlight_icon_on.xml new file mode 100644 index 000000000000..5ffe262d8077 --- /dev/null +++ b/packages/SystemUI/res/drawable/qs_nightlight_icon_on.xml @@ -0,0 +1,94 @@ +<?xml version="1.0" encoding="utf-8"?><!-- + 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. +--> +<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:aapt="http://schemas.android.com/aapt"> + <target android:name="_R_G_L_0_G_T_1"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:duration="400" + android:propertyName="translateY" + android:startOffset="0" + android:valueFrom="12.312" + android:valueTo="12.125" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.3,0 0.1,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="_R_G_L_0_G_T_1"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:duration="400" + android:propertyName="rotation" + android:startOffset="0" + android:valueFrom="0" + android:valueTo="-45" + android:valueType="floatType"> + <aapt:attr name="android:interpolator"> + <pathInterpolator android:pathData="M 0.0,0.0 c0.3,0 0.1,1 1.0,1.0" /> + </aapt:attr> + </objectAnimator> + </set> + </aapt:attr> + </target> + <target android:name="time_group"> + <aapt:attr name="android:animation"> + <set android:ordering="together"> + <objectAnimator + android:duration="417" + android:propertyName="translateX" + android:startOffset="0" + android:valueFrom="0" + android:valueTo="1" + android:valueType="floatType" /> + </set> + </aapt:attr> + </target> + <aapt:attr name="android:drawable"> + <vector + android:width="24dp" + android:height="24dp" + android:viewportHeight="24" + android:viewportWidth="24"> + <group android:name="_R_G"> + <group + android:name="_R_G_L_0_G_T_1" + android:rotation="0" + android:translateX="12.875" + android:translateY="12.312"> + <group + android:name="_R_G_L_0_G" + android:translateX="-2.375"> + <path + android:name="_R_G_L_0_G_D_0_P_0" + android:pathData=" M3.33 8.62 C2.09,8.68 0.59,8.47 -0.64,7.95 C-1.65,7.53 -2.75,6.9 -3.59,6.09 C-4.38,5.32 -5.19,4.17 -5.61,3.08 C-6.04,1.99 -6.25,0.83 -6.25,-0.39 C-6.25,-1.72 -5.98,-2.85 -5.55,-3.94 C-5.13,-5.02 -4.37,-6 -3.6,-6.78 C-2.63,-7.75 -1.63,-8.28 -0.52,-8.77 C0.48,-9.2 2.04,-9.41 3.14,-9.38 C4.22,-9.35 4.94,-9.16 5.81,-8.79 C5.94,-8.73 6.28,-8.6 6.18,-8.55 C3.44,-6.63 1.83,-3.66 1.83,-0.39 C1.83,2.53 3.47,5.72 6.15,7.86 C6.16,7.9 6.03,7.97 5.91,8.04 C5.13,8.43 4.31,8.56 3.33,8.62c " + android:strokeAlpha="1" + android:strokeColor="#ffffff" + android:strokeLineCap="round" + android:strokeLineJoin="round" + android:strokeWidth="2" /> + </group> + </group> + </group> + <group android:name="time_group" /> + </vector> + </aapt:attr> +</animated-vector> diff --git a/packages/SystemUI/res/layout/auth_biometric_contents.xml b/packages/SystemUI/res/layout/auth_biometric_contents.xml index d633803c920b..be76405744db 100644 --- a/packages/SystemUI/res/layout/auth_biometric_contents.xml +++ b/packages/SystemUI/res/layout/auth_biometric_contents.xml @@ -51,7 +51,7 @@ android:id="@+id/biometric_icon_frame" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_gravity="center_horizontal"> + android:layout_gravity="center"> <com.airbnb.lottie.LottieAnimationView android:id="@+id/biometric_icon" @@ -61,6 +61,13 @@ android:contentDescription="@null" android:scaleType="fitXY" /> + <com.airbnb.lottie.LottieAnimationView + android:id="@+id/biometric_icon_overlay" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:contentDescription="@null" + android:scaleType="fitXY" /> </FrameLayout> <!-- For sensors such as UDFPS, this view is used during custom measurement/layout to add extra diff --git a/packages/SystemUI/res/layout/dream_overlay_status_bar_view.xml b/packages/SystemUI/res/layout/dream_overlay_status_bar_view.xml index c972624c04b1..006b260434bc 100644 --- a/packages/SystemUI/res/layout/dream_overlay_status_bar_view.xml +++ b/packages/SystemUI/res/layout/dream_overlay_status_bar_view.xml @@ -40,7 +40,6 @@ android:layout_height="match_parent" android:orientation="horizontal" android:gravity="center_vertical" - android:layout_marginEnd="@dimen/dream_overlay_status_bar_extra_margin" app:layout_constraintEnd_toStartOf="@+id/dream_overlay_system_status" /> <LinearLayout @@ -48,14 +47,15 @@ android:layout_width="wrap_content" android:layout_height="match_parent" android:orientation="horizontal" - android:layout_marginStart="@dimen/dream_overlay_status_bar_extra_margin" + android:paddingStart="@dimen/dream_overlay_status_bar_extra_margin" + android:visibility="gone" app:layout_constraintEnd_toEndOf="parent"> <com.android.systemui.statusbar.AlphaOptimizedImageView android:id="@+id/dream_overlay_alarm_set" android:layout_width="@dimen/dream_overlay_status_bar_icon_size" android:layout_height="match_parent" - android:layout_marginEnd="@dimen/dream_overlay_status_icon_margin" + android:layout_marginStart="@dimen/dream_overlay_status_icon_margin" android:src="@drawable/ic_alarm" android:tint="@android:color/white" android:visibility="gone" @@ -65,7 +65,7 @@ android:id="@+id/dream_overlay_priority_mode" android:layout_width="@dimen/dream_overlay_status_bar_icon_size" android:layout_height="match_parent" - android:layout_marginEnd="@dimen/dream_overlay_status_icon_margin" + android:layout_marginStart="@dimen/dream_overlay_status_icon_margin" android:src="@drawable/ic_qs_dnd_on" android:tint="@android:color/white" android:visibility="gone" @@ -75,7 +75,7 @@ android:id="@+id/dream_overlay_wifi_status" android:layout_width="@dimen/dream_overlay_status_bar_icon_size" android:layout_height="match_parent" - android:layout_marginEnd="@dimen/dream_overlay_status_icon_margin" + android:layout_marginStart="@dimen/dream_overlay_status_icon_margin" android:src="@drawable/ic_signal_wifi_off" android:visibility="gone" android:contentDescription="@string/dream_overlay_status_bar_wifi_off" /> @@ -84,7 +84,7 @@ android:id="@+id/dream_overlay_mic_off" android:layout_width="@dimen/dream_overlay_grey_chip_width" android:layout_height="match_parent" - android:layout_marginEnd="@dimen/dream_overlay_status_icon_margin" + android:layout_marginStart="@dimen/dream_overlay_status_icon_margin" android:src="@drawable/dream_overlay_mic_off" android:visibility="gone" android:contentDescription="@string/dream_overlay_status_bar_mic_off" /> @@ -93,7 +93,7 @@ android:id="@+id/dream_overlay_camera_off" android:layout_width="@dimen/dream_overlay_grey_chip_width" android:layout_height="match_parent" - android:layout_marginEnd="@dimen/dream_overlay_status_icon_margin" + android:layout_marginStart="@dimen/dream_overlay_status_icon_margin" android:src="@drawable/dream_overlay_camera_off" android:visibility="gone" android:contentDescription="@string/dream_overlay_status_bar_camera_off" /> @@ -102,7 +102,7 @@ android:id="@+id/dream_overlay_camera_mic_off" android:layout_width="@dimen/dream_overlay_grey_chip_width" android:layout_height="match_parent" - android:layout_marginEnd="@dimen/dream_overlay_status_icon_margin" + android:layout_marginStart="@dimen/dream_overlay_status_icon_margin" android:src="@drawable/dream_overlay_mic_and_camera_off" android:visibility="gone" android:contentDescription="@string/dream_overlay_status_bar_camera_mic_off" /> diff --git a/packages/SystemUI/res/layout/keyguard_bottom_area.xml b/packages/SystemUI/res/layout/keyguard_bottom_area.xml index 0ca19d98a097..8df8c49ee057 100644 --- a/packages/SystemUI/res/layout/keyguard_bottom_area.xml +++ b/packages/SystemUI/res/layout/keyguard_bottom_area.xml @@ -83,48 +83,6 @@ android:layout_marginBottom="@dimen/keyguard_affordance_vertical_offset" android:visibility="gone" /> - <ImageView - android:id="@+id/wallet_button" - android:layout_height="@dimen/keyguard_affordance_fixed_height" - android:layout_width="@dimen/keyguard_affordance_fixed_width" - android:layout_gravity="bottom|end" - android:scaleType="center" - android:tint="?android:attr/textColorPrimary" - android:src="@drawable/ic_wallet_lockscreen" - android:background="@drawable/keyguard_bottom_affordance_bg" - android:layout_marginEnd="@dimen/keyguard_affordance_horizontal_offset" - android:layout_marginBottom="@dimen/keyguard_affordance_vertical_offset" - android:contentDescription="@string/accessibility_wallet_button" - android:visibility="gone" /> - - <ImageView - android:id="@+id/qr_code_scanner_button" - android:layout_height="@dimen/keyguard_affordance_fixed_height" - android:layout_width="@dimen/keyguard_affordance_fixed_width" - android:layout_gravity="bottom|end" - android:scaleType="center" - android:tint="?android:attr/textColorPrimary" - android:src="@drawable/ic_qr_code_scanner" - android:background="@drawable/keyguard_bottom_affordance_bg" - android:layout_marginEnd="@dimen/keyguard_affordance_horizontal_offset" - android:layout_marginBottom="@dimen/keyguard_affordance_vertical_offset" - android:contentDescription="@string/accessibility_qr_code_scanner_button" - android:visibility="gone" /> - - <ImageView - android:id="@+id/controls_button" - android:layout_height="@dimen/keyguard_affordance_fixed_height" - android:layout_width="@dimen/keyguard_affordance_fixed_width" - android:layout_gravity="bottom|start" - android:scaleType="center" - android:tint="?android:attr/textColorPrimary" - android:src="@drawable/controls_icon" - android:background="@drawable/keyguard_bottom_affordance_bg" - android:layout_marginStart="@dimen/keyguard_affordance_horizontal_offset" - android:layout_marginBottom="@dimen/keyguard_affordance_vertical_offset" - android:contentDescription="@string/quick_controls_title" - android:visibility="gone" /> - <FrameLayout android:id="@+id/overlay_container" android:layout_width="match_parent" diff --git a/packages/SystemUI/res/layout/media_output_dialog.xml b/packages/SystemUI/res/layout/media_output_dialog.xml index 93c16e4e119d..b76de5afdb73 100644 --- a/packages/SystemUI/res/layout/media_output_dialog.xml +++ b/packages/SystemUI/res/layout/media_output_dialog.xml @@ -20,6 +20,7 @@ android:id="@+id/media_output_dialog" android:layout_width="@dimen/large_dialog_width" android:layout_height="wrap_content" + android:background="@drawable/media_output_dialog_background" android:orientation="vertical"> <LinearLayout diff --git a/packages/SystemUI/res/layout/super_notification_shade.xml b/packages/SystemUI/res/layout/super_notification_shade.xml index 86f8ce26ccab..0c57b934d27e 100644 --- a/packages/SystemUI/res/layout/super_notification_shade.xml +++ b/packages/SystemUI/res/layout/super_notification_shade.xml @@ -88,7 +88,7 @@ android:layout_marginTop="@dimen/status_bar_height" android:layout_gravity="top|center_horizontal" android:gravity="center_horizontal"> - <com.android.keyguard.KeyguardMessageArea + <com.android.keyguard.AuthKeyguardMessageArea android:id="@+id/keyguard_message_area" style="@style/Keyguard.TextView" android:layout_width="wrap_content" diff --git a/packages/SystemUI/res/raw/biometricprompt_fingerprint_to_error_landscape.json b/packages/SystemUI/res/raw/biometricprompt_fingerprint_to_error_landscape.json new file mode 100644 index 000000000000..3d33b2afeaf1 --- /dev/null +++ b/packages/SystemUI/res/raw/biometricprompt_fingerprint_to_error_landscape.json @@ -0,0 +1 @@ +{"v":"5.9.0","fr":60,"ip":0,"op":21,"w":340,"h":340,"nm":"BiometricPrompt_Symbol_Fingerprint_To_Error_Landscape","ddd":0,"assets":[{"id":"comp_0","nm":"Fingerprint_Animation_ForConfirm_Short","fr":60,"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"circle fill 5","td":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":239,"s":[0]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":249,"s":[100]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":388,"s":[100]},{"t":408,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,62.45],[-62.45,0],[0,-62.45],[62.45,0]],"o":[[0,-62.45],[62.45,0],[0,62.45],[-62.45,0]],"v":[[-113.08,0],[0,-113.08],[113.08,0],[0,113.08]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[206,150],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333393172,0.403921598547,0.360784313725,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":239,"op":1411,"st":239,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".white","cl":"white","tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-52.056,-2.445],[-17.306,32.25],[52.194,-37.194]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":14,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":239,"s":[0]},{"t":249,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":239,"op":1139,"st":239,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".green400","cl":"green400","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":239,"s":[0]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":249,"s":[100]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":388,"s":[100]},{"t":408,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,62.45],[-62.45,0],[0,-62.45],[62.45,0]],"o":[[0,-62.45],[62.45,0],[0,62.45],[-62.45,0]],"v":[[-113.08,0],[0,-113.08],[113.08,0],[0,113.08]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[206,150],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.450980392157,0.709803921569,0.470588235294,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":239,"op":1411,"st":239,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"circle fill 3","td":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":80,"s":[0]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":90,"s":[100]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":108,"s":[100]},{"t":118,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,62.45],[-62.45,0],[0,-62.45],[62.45,0]],"o":[[0,-62.45],[62.45,0],[0,62.45],[-62.45,0]],"v":[[-113.08,0],[0,-113.08],[113.08,0],[0,113.08]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[206,150],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333393172,0.403921598547,0.360784313725,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":80,"op":1252,"st":80,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".white","cl":"white","tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":80,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.111,14.055],[-0.056,14.056]],"c":false}]},{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":90,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.056,-49.945],[-0.056,14.056]],"c":false}]},{"i":{"x":0.2,"y":1},"o":{"x":0.8,"y":0},"t":108,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.056,-49.945],[-0.056,14.056]],"c":false}]},{"t":118,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.111,14.055],[-0.056,14.056]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":14,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":80,"s":[0,0]},{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":90,"s":[100,100]},{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.8,0.8],"y":[0,0]},"t":108,"s":[100,100]},{"t":118,"s":[0,0]}],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.056,35.389],[-0.111,50.111]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":14,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0.049,42.698],"ix":2},"a":{"a":0,"k":[0.049,42.698],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":80,"s":[0,0]},{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":90,"s":[100,100]},{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.8,0.8],"y":[0,0]},"t":108,"s":[100,100]},{"t":118,"s":[0,0]}],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 2","np":3,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":80,"op":980,"st":80,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":".red400","cl":"red400","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":80,"s":[0]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":90,"s":[100]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":108,"s":[100]},{"t":118,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,62.45],[-62.45,0],[0,-62.45],[62.45,0]],"o":[[0,-62.45],[62.45,0],[0,62.45],[-62.45,0]],"v":[[-113.08,0],[0,-113.08],[113.08,0],[0,113.08]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[206,150],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333393172,0.403921598547,0.360784313725,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":80,"op":1252,"st":80,"bm":0},{"ddd":0,"ind":7,"ty":3,"nm":"Null 1","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0.333},"t":85,"s":[209.333,136.333,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":440,"s":[209.333,136.333,0],"to":[1.944,2.278,0],"ti":[3.056,-2.278,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":450,"s":[221,150,0],"to":[-3.056,2.278,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":460,"s":[191,150,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":470,"s":[221,150,0],"to":[0,0,0],"ti":[2.5,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":480,"s":[191,150,0],"to":[-2.5,0,0],"ti":[-2.5,0,0]},{"t":490,"s":[206,150,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[132,132,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":0,"nm":"Fingerprint_Animation_ForConfirm_Short","refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[170,77.667,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[30,30,100],"ix":6,"l":2}},"ao":0,"w":412,"h":300,"ip":0,"op":830,"st":-70,"bm":0}],"markers":[{"tm":255,"cm":"","dr":0},{"tm":364,"cm":"","dr":0},{"tm":482,"cm":"","dr":0},{"tm":600,"cm":"","dr":0}]}
\ No newline at end of file diff --git a/packages/SystemUI/res/raw/biometricprompt_landscape_base.json b/packages/SystemUI/res/raw/biometricprompt_landscape_base.json new file mode 100644 index 000000000000..3781eeee231f --- /dev/null +++ b/packages/SystemUI/res/raw/biometricprompt_landscape_base.json @@ -0,0 +1 @@ +{"v":"5.9.0","fr":60,"ip":0,"op":21,"w":340,"h":340,"nm":"biometricprompt_landscape_base","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 16","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[170,170,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":3,"nm":"Null_Circle","parent":1,"sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":-108,"s":[70.333,-88.75,0],"to":[-11.722,17.639,0],"ti":[11.722,-17.639,0]},{"t":-48,"s":[0,17.083,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ip":-255,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".grey600","cl":"grey600","parent":2,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0.333,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":-108,"s":[0,0]},{"t":-48,"s":[202,202]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.501960784314,0.525490196078,0.545098039216,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,-17.333],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-255,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"circle mask 3","parent":2,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0.333,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":-108,"s":[0,0]},{"t":-48,"s":[202,202]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.250980392157,0.282352941176,0.294117647059,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.078246000701,0.610494037703,0.787910970052,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,-17.333],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-255,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"Finger","parent":2,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":-60,"s":[55]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":0,"s":[0]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":110,"s":[0]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":140,"s":[10]},{"t":170,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":-60,"s":[92.146,-65.896,0],"to":[1.361,6.667,0],"ti":[-1.361,-6.667,0]},{"i":{"x":0.2,"y":0.2},"o":{"x":0.167,"y":0.167},"t":0,"s":[100.313,-25.896,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.2,"y":0.2},"o":{"x":0.7,"y":0.7},"t":110,"s":[100.313,-25.896,0],"to":[0,0,0],"ti":[0,0,0]},{"t":170,"s":[100.313,-25.896,0]}],"ix":2,"l":2},"a":{"a":0,"k":[160.315,58.684,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-11.013,2.518],[5.251,5.023],[8.982,-2.829],[-0.264,-5.587]],"o":[[12.768,-2.854],[-14.961,2.071],[-6.004,1.89],[8.052,1.403]],"v":[[5.115,7.499],[19.814,-10.087],[-16.489,-3.588],[-24.801,8.684]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.760784373564,0.478431402468,0.400000029919,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[34.67,28.053],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[22.231,-7],[-27.395,-1.197],[-26.792,4.092],[14.179,15.736]],"o":[[-17.931,5.646],[56.062,2.45],[-1.765,-22.396],[-51.819,17.744]],"v":[[-62.102,-8.314],[-39.958,30.079],[80.033,25.905],[54.879,-32.529]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.678431372549,0.403921598547,0.305882352941,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[80.283,32.779],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":4,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":-255,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"circle mask 7","parent":2,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0.333,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":-108,"s":[0,0]},{"t":-48,"s":[202,202]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.250980392157,0.282352941176,0.294117647059,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.078246000701,0.610494037703,0.787910970052,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,-17.333],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-255,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":".grey600","cl":"grey600","parent":2,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-0.25,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[114.218,-17.096],[-112.938,-17.096]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.501960784314,0.525490196078,0.545098039216,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":10,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":0,"k":36.9,"ix":2},"o":{"a":0,"k":114.2,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":-255,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"circle mask","parent":2,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0.333,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":-108,"s":[0,0]},{"t":-48,"s":[202,202]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.250980392157,0.282352941176,0.294117647059,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.078246000701,0.610494037703,0.787910970052,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,-17.333],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-255,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":".grey800","cl":"grey800","parent":2,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-0.5,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[114.218,-17.096],[-112.938,-17.096]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.235294117647,0.250980392157,0.262745098039,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":10,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":0,"k":100,"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":-255,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"circle mask 6","parent":2,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0.333,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":-108,"s":[0,0]},{"t":-48,"s":[202,202]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.250980392157,0.282352941176,0.294117647059,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.078246000701,0.610494037703,0.787910970052,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,-17.333],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-255,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":".grey900","cl":"grey900","parent":2,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":377,"s":[-180]},{"t":417,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":377,"s":[-1.137,1.771,0],"to":[0.375,0,0],"ti":[-0.375,0,0]},{"t":417,"s":[1.113,1.771,0]}],"ix":2,"l":2},"a":{"a":0,"k":[6.238,5.063,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":77,"s":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[-8.788,-4.637],[-10.23,-3.195],[-2.196,4.813],[5.988,-3.371],[4.545,-4.813],[-2.196,1.918]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":107,"s":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[-8.788,0.393],[-10.23,1.835],[-2.196,9.843],[5.988,1.659],[4.545,0.217],[-2.196,6.948]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":137,"s":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[-8.788,-4.637],[-10.23,-3.195],[-2.196,4.813],[5.988,-3.371],[4.545,-4.813],[-2.196,1.918]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":167,"s":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[-8.788,0.393],[-10.23,1.835],[-2.196,9.843],[5.988,1.659],[4.545,0.217],[-2.196,6.948]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":197,"s":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[-8.788,-4.637],[-10.23,-3.195],[-2.196,4.813],[5.988,-3.371],[4.545,-4.813],[-2.196,1.918]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.7,"y":0},"t":232,"s":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[-8.788,0.393],[-10.23,1.835],[-2.196,9.843],[5.988,1.659],[4.545,0.217],[-2.196,6.948]],"c":false}]},{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":562,"s":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[-8.788,0.393],[-10.23,1.835],[-2.196,9.843],[5.988,1.659],[4.545,0.217],[-2.196,6.948]],"c":false}]},{"t":602,"s":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[-4.546,-0.421],[-5.988,1.021],[-2.196,4.813],[5.988,-3.371],[4.545,-4.813],[-2.196,1.918]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.125490196078,0.129411764706,0.141176470588,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[6.238,5.063],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-255,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"circle mask 2","parent":2,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0.333,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":-108,"s":[0,0]},{"t":-48,"s":[202,202]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.250980392157,0.282352941176,0.294117647059,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.078246000701,0.610494037703,0.787910970052,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,-17.333],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-255,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":".blue400","cl":"blue400","parent":2,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,8.308,0],"ix":2,"l":2},"a":{"a":0,"k":[41.706,20.979,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[18.645,0],[0,18.645]],"o":[[0,18.645],[-18.644,0],[0,0]],"v":[[33.76,-16.88],[-0.001,16.88],[-33.76,-16.88]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.400000029919,0.61568627451,0.964705942191,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[41.706,17.13],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[22.896,0],[0,22.896]],"o":[[0,22.896],[-22.896,0],[0,0]],"v":[[41.457,-20.729],[-0.001,20.729],[-41.457,-20.729]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.400000029919,0.61568627451,0.964705942191,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[41.706,20.979],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":4,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":-255,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":"circle mask 4","parent":2,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0.333,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":-108,"s":[0,0]},{"t":-48,"s":[202,202]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.250980392157,0.282352941176,0.294117647059,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.078246000701,0.610494037703,0.787910970052,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,-17.333],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-255,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":15,"ty":1,"nm":".grey900","cl":"grey900","parent":2,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,66,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[52,52,100],"ix":6,"l":2}},"ao":0,"sw":412,"sh":300,"sc":"#202124","ip":-255,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":16,"ty":4,"nm":"circle mask 5","parent":2,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0.333,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":-108,"s":[0,0]},{"t":-48,"s":[202,202]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.250980392157,0.282352941176,0.294117647059,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.078246000701,0.610494037703,0.787910970052,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,-17.333],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-255,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":17,"ty":1,"nm":".black","cl":"black","parent":2,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,-17.333,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[72,72,100],"ix":6,"l":2}},"ao":0,"sw":412,"sh":300,"sc":"#000000","ip":-255,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":18,"ty":4,"nm":".grey800","cl":"grey800","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":-108,"s":[-192.25,99.933,0],"to":[5,3.333,0],"ti":[-5,-3.333,0]},{"t":-48,"s":[-162.25,119.933,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-163,100.85,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.833],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.167],"y":[0,0,0]},"t":-108,"s":[100,100,100]},{"t":-48,"s":[59,59,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[326,201.699],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":8,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"st","c":{"a":0,"k":[0.235294117647,0.250980392157,0.262745098039,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-255,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":19,"ty":4,"nm":".grey900","cl":"grey900","parent":23,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":-239,"s":[0,18.167,0],"to":[0,-1.25,0],"ti":[0,1.25,0]},{"t":-199,"s":[0,10.667,0]}],"ix":2,"l":2},"a":{"a":0,"k":[5.5,4,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.7,"y":0},"t":-239,"s":[{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-0.07,1.5],[0,-1.5],[-0.047,1.5]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":-199,"s":[{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-3,1.5],[0,-1.5],[3,1.5]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":-171,"s":[{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-3,1.5],[0,-1.5],[3,1.5]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":-141,"s":[{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-3,3.512],[0,0.512],[3,3.512]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":-111,"s":[{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-3,1.5],[0,-1.5],[3,1.5]],"c":false}]},{"t":-81,"s":[{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-3,3.967],[0,0.967],[3,3.967]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.125490196078,0.129411764706,0.141176470588,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[5.5,4],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-199,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":20,"ty":4,"nm":"Shape Layer 4","parent":1,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":-239,"s":[71,-116.083,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.7,"y":0},"t":-199,"s":[71,-101.083,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":365,"s":[71,-101.083,0],"to":[0,0,0],"ti":[16.833,-14.361,0]},{"t":405,"s":[-30,-14.917,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":-239,"s":[29,29]},{"i":{"x":[0.833,0.833],"y":[1,0.833]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":-199,"s":[29,38]},{"i":{"x":[0.833,0.833],"y":[0.833,0.833]},"o":{"x":[0.167,0.167],"y":[0.167,0.167]},"t":365,"s":[29,36]},{"t":405,"s":[83,83]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":365,"s":[50]},{"t":405,"s":[50]}],"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.400000029919,0.61568627451,0.964705942191,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-255,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":21,"ty":4,"nm":".grey900","cl":"grey900","parent":1,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":-239,"s":[71,-82.917,0],"to":[0,-1.25,0],"ti":[0,1.25,0]},{"t":-199,"s":[71,-90.417,0]}],"ix":2,"l":2},"a":{"a":0,"k":[5.5,4,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":-239,"s":[{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-0.07,1.5],[0,-1.5],[-0.047,1.5]],"c":false}]},{"t":-199,"s":[{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-3,1.5],[0,-1.5],[3,1.5]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.125490196078,0.129411764706,0.141176470588,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[5.5,4],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-255,"op":-199,"st":-255,"bm":0},{"ddd":0,"ind":22,"ty":4,"nm":"device frame mask","parent":24,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,1.167,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[326,201.699],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":8,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"st","c":{"a":0,"k":[0.250980392157,0.282352941176,0.294117647059,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.078246000701,0.610494037703,0.787910970052,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-255,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":23,"ty":4,"nm":".blue400","cl":"blue400","parent":18,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":-239,"s":[100.25,-115.167,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":-199,"s":[100.25,-100.167,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.7,"y":0},"t":-159,"s":[100.25,-105.667,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":365,"s":[100.25,-100.167,0],"to":[0,0,0],"ti":[16.833,-14.361,0]},{"t":405,"s":[-0.75,-14,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":-239,"s":[29,29]},{"i":{"x":[0.833,0.833],"y":[1,0.833]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":-199,"s":[29,38]},{"i":{"x":[0.833,0.833],"y":[0.833,0.833]},"o":{"x":[0.167,0.167],"y":[0.167,0.167]},"t":365,"s":[29,36]},{"t":405,"s":[83,83]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":365,"s":[50]},{"t":405,"s":[50]}],"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.400000029919,0.61568627451,0.964705942191,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-255,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":24,"ty":3,"nm":"device frame mask 5","parent":18,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ip":-165,"op":6.00000000000001,"st":-271,"bm":0},{"ddd":0,"ind":28,"ty":4,"nm":"device frame mask 9","parent":1,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-29.25,-0.917,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[326,201.699],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":8,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"st","c":{"a":0,"k":[0.250980392157,0.282352941176,0.294117647059,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.078246000701,0.610494037703,0.787910970052,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-181,"op":-62,"st":-181,"bm":0},{"ddd":0,"ind":29,"ty":4,"nm":".blue400","cl":"blue400","parent":23,"tt":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":-145,"s":[50]},{"t":-75,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":-165,"s":[0,0]},{"t":-75,"s":[94,94]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":73,"s":[50]},{"t":113,"s":[50]}],"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.4,0.61568627451,0.964705882353,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-181,"op":-62,"st":-181,"bm":0},{"ddd":0,"ind":30,"ty":4,"nm":"device frame mask 8","parent":1,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-29.25,-0.917,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[326,201.699],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":8,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"st","c":{"a":0,"k":[0.250980392157,0.282352941176,0.294117647059,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.078246000701,0.610494037703,0.787910970052,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-211,"op":-92,"st":-211,"bm":0},{"ddd":0,"ind":31,"ty":4,"nm":".blue400","cl":"blue400","parent":23,"tt":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":-165,"s":[50]},{"t":-95,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":-195,"s":[0,0]},{"t":-105,"s":[94,94]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":43,"s":[50]},{"t":83,"s":[50]}],"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.4,0.61568627451,0.964705882353,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-211,"op":-92,"st":-211,"bm":0},{"ddd":0,"ind":32,"ty":4,"nm":"device frame mask 7","parent":1,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-29.25,-0.917,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[326,201.699],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":8,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"st","c":{"a":0,"k":[0.250980392157,0.282352941176,0.294117647059,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.078246000701,0.610494037703,0.787910970052,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-241,"op":-122,"st":-241,"bm":0},{"ddd":0,"ind":33,"ty":4,"nm":".blue400","cl":"blue400","parent":23,"tt":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":-195,"s":[50]},{"t":-125,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":-225,"s":[0,0]},{"t":-135,"s":[94,94]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":13,"s":[50]},{"t":53,"s":[50]}],"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.4,0.61568627451,0.964705882353,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-241,"op":-122,"st":-241,"bm":0},{"ddd":0,"ind":34,"ty":4,"nm":"device frame mask 6","parent":1,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-29.25,-0.917,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[326,201.699],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":8,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"st","c":{"a":0,"k":[0.250980392157,0.282352941176,0.294117647059,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.078246000701,0.610494037703,0.787910970052,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-271,"op":-152,"st":-271,"bm":0},{"ddd":0,"ind":35,"ty":4,"nm":".blue400","cl":"blue400","parent":23,"tt":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":-225,"s":[50]},{"t":-155,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":-255,"s":[0,0]},{"t":-165,"s":[94,94]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":-17,"s":[50]},{"t":23,"s":[50]}],"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.4,0.61568627451,0.964705882353,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-271,"op":-152,"st":-271,"bm":0}],"markers":[{"tm":255,"cm":"","dr":0},{"tm":364,"cm":"","dr":0},{"tm":482,"cm":"","dr":0},{"tm":600,"cm":"","dr":0}]}
\ No newline at end of file diff --git a/packages/SystemUI/res/raw/biometricprompt_portrait_base_bottomright.json b/packages/SystemUI/res/raw/biometricprompt_portrait_base_bottomright.json new file mode 100644 index 000000000000..495066638cf4 --- /dev/null +++ b/packages/SystemUI/res/raw/biometricprompt_portrait_base_bottomright.json @@ -0,0 +1 @@ +{"v":"5.9.0","fr":60,"ip":0,"op":21,"w":340,"h":340,"nm":"biometricprompt_portrait_base_bottomright","ddd":0,"assets":[{"id":"comp_0","nm":"biometricprompt_landscape_base","fr":60,"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 16","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[170,170,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":3,"nm":"Null_Circle","parent":1,"sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":-108,"s":[70.333,-88.75,0],"to":[-11.722,17.639,0],"ti":[11.722,-17.639,0]},{"t":-48,"s":[0,17.083,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ip":-255,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".grey600","cl":"grey600","parent":2,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0.333,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":-108,"s":[0,0]},{"t":-48,"s":[202,202]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.501960784314,0.525490196078,0.545098039216,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,-17.333],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-255,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"circle mask 3","parent":2,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0.333,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":-108,"s":[0,0]},{"t":-48,"s":[202,202]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.250980392157,0.282352941176,0.294117647059,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.078246000701,0.610494037703,0.787910970052,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,-17.333],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-255,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"Finger","parent":2,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":-60,"s":[55]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":0,"s":[0]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":110,"s":[0]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":140,"s":[10]},{"t":170,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":-60,"s":[92.146,-65.896,0],"to":[1.361,6.667,0],"ti":[-1.361,-6.667,0]},{"i":{"x":0.2,"y":0.2},"o":{"x":0.167,"y":0.167},"t":0,"s":[100.313,-25.896,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.2,"y":0.2},"o":{"x":0.7,"y":0.7},"t":110,"s":[100.313,-25.896,0],"to":[0,0,0],"ti":[0,0,0]},{"t":170,"s":[100.313,-25.896,0]}],"ix":2,"l":2},"a":{"a":0,"k":[160.315,58.684,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-11.013,2.518],[5.251,5.023],[8.982,-2.829],[-0.264,-5.587]],"o":[[12.768,-2.854],[-14.961,2.071],[-6.004,1.89],[8.052,1.403]],"v":[[5.115,7.499],[19.814,-10.087],[-16.489,-3.588],[-24.801,8.684]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.760784373564,0.478431402468,0.400000029919,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[34.67,28.053],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[22.231,-7],[-27.395,-1.197],[-26.792,4.092],[14.179,15.736]],"o":[[-17.931,5.646],[56.062,2.45],[-1.765,-22.396],[-51.819,17.744]],"v":[[-62.102,-8.314],[-39.958,30.079],[80.033,25.905],[54.879,-32.529]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.678431372549,0.403921598547,0.305882352941,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[80.283,32.779],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":4,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":-255,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"circle mask 7","parent":2,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0.333,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":-108,"s":[0,0]},{"t":-48,"s":[202,202]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.250980392157,0.282352941176,0.294117647059,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.078246000701,0.610494037703,0.787910970052,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,-17.333],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-255,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":".grey600","cl":"grey600","parent":2,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-0.25,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[114.218,-17.096],[-112.938,-17.096]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.501960784314,0.525490196078,0.545098039216,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":10,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":0,"k":36.9,"ix":2},"o":{"a":0,"k":114.2,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":-255,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"circle mask","parent":2,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0.333,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":-108,"s":[0,0]},{"t":-48,"s":[202,202]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.250980392157,0.282352941176,0.294117647059,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.078246000701,0.610494037703,0.787910970052,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,-17.333],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-255,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":".grey800","cl":"grey800","parent":2,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-0.5,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[114.218,-17.096],[-112.938,-17.096]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.235294117647,0.250980392157,0.262745098039,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":10,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":0,"k":100,"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":-255,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"circle mask 6","parent":2,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0.333,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":-108,"s":[0,0]},{"t":-48,"s":[202,202]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.250980392157,0.282352941176,0.294117647059,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.078246000701,0.610494037703,0.787910970052,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,-17.333],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-255,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":".grey900","cl":"grey900","parent":2,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":377,"s":[-180]},{"t":417,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":377,"s":[-1.137,1.771,0],"to":[0.375,0,0],"ti":[-0.375,0,0]},{"t":417,"s":[1.113,1.771,0]}],"ix":2,"l":2},"a":{"a":0,"k":[6.238,5.063,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":77,"s":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[-8.788,-4.637],[-10.23,-3.195],[-2.196,4.813],[5.988,-3.371],[4.545,-4.813],[-2.196,1.918]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":107,"s":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[-8.788,0.393],[-10.23,1.835],[-2.196,9.843],[5.988,1.659],[4.545,0.217],[-2.196,6.948]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":137,"s":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[-8.788,-4.637],[-10.23,-3.195],[-2.196,4.813],[5.988,-3.371],[4.545,-4.813],[-2.196,1.918]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":167,"s":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[-8.788,0.393],[-10.23,1.835],[-2.196,9.843],[5.988,1.659],[4.545,0.217],[-2.196,6.948]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":197,"s":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[-8.788,-4.637],[-10.23,-3.195],[-2.196,4.813],[5.988,-3.371],[4.545,-4.813],[-2.196,1.918]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.7,"y":0},"t":232,"s":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[-8.788,0.393],[-10.23,1.835],[-2.196,9.843],[5.988,1.659],[4.545,0.217],[-2.196,6.948]],"c":false}]},{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":562,"s":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[-8.788,0.393],[-10.23,1.835],[-2.196,9.843],[5.988,1.659],[4.545,0.217],[-2.196,6.948]],"c":false}]},{"t":602,"s":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[-4.546,-0.421],[-5.988,1.021],[-2.196,4.813],[5.988,-3.371],[4.545,-4.813],[-2.196,1.918]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.125490196078,0.129411764706,0.141176470588,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[6.238,5.063],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-255,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"circle mask 2","parent":2,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0.333,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":-108,"s":[0,0]},{"t":-48,"s":[202,202]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.250980392157,0.282352941176,0.294117647059,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.078246000701,0.610494037703,0.787910970052,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,-17.333],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-255,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":".blue400","cl":"blue400","parent":2,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,8.308,0],"ix":2,"l":2},"a":{"a":0,"k":[41.706,20.979,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[18.645,0],[0,18.645]],"o":[[0,18.645],[-18.644,0],[0,0]],"v":[[33.76,-16.88],[-0.001,16.88],[-33.76,-16.88]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.400000029919,0.61568627451,0.964705942191,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[41.706,17.13],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[22.896,0],[0,22.896]],"o":[[0,22.896],[-22.896,0],[0,0]],"v":[[41.457,-20.729],[-0.001,20.729],[-41.457,-20.729]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.400000029919,0.61568627451,0.964705942191,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[41.706,20.979],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":4,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":-255,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":"circle mask 4","parent":2,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0.333,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":-108,"s":[0,0]},{"t":-48,"s":[202,202]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.250980392157,0.282352941176,0.294117647059,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.078246000701,0.610494037703,0.787910970052,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,-17.333],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-255,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":15,"ty":1,"nm":".grey900","cl":"grey900","parent":2,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,66,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[52,52,100],"ix":6,"l":2}},"ao":0,"sw":412,"sh":300,"sc":"#202124","ip":-255,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":16,"ty":4,"nm":"circle mask 5","parent":2,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0.333,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":-108,"s":[0,0]},{"t":-48,"s":[202,202]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.250980392157,0.282352941176,0.294117647059,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.078246000701,0.610494037703,0.787910970052,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,-17.333],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-255,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":17,"ty":1,"nm":".black","cl":"black","parent":2,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,-17.333,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[72,72,100],"ix":6,"l":2}},"ao":0,"sw":412,"sh":300,"sc":"#000000","ip":-255,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":18,"ty":4,"nm":".grey800","cl":"grey800","parent":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":-108,"s":[-192.25,99.933,0],"to":[5,3.333,0],"ti":[-5,-3.333,0]},{"t":-48,"s":[-162.25,119.933,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-163,100.85,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.833],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.167],"y":[0,0,0]},"t":-108,"s":[100,100,100]},{"t":-48,"s":[59,59,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[326,201.699],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":8,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"st","c":{"a":0,"k":[0.235294117647,0.250980392157,0.262745098039,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-255,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":19,"ty":4,"nm":".grey900","cl":"grey900","parent":23,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":-239,"s":[0,18.167,0],"to":[0,-1.25,0],"ti":[0,1.25,0]},{"t":-199,"s":[0,10.667,0]}],"ix":2,"l":2},"a":{"a":0,"k":[5.5,4,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.7,"y":0},"t":-239,"s":[{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-0.07,1.5],[0,-1.5],[-0.047,1.5]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":-199,"s":[{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-3,1.5],[0,-1.5],[3,1.5]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":-171,"s":[{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-3,1.5],[0,-1.5],[3,1.5]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":-141,"s":[{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-3,3.512],[0,0.512],[3,3.512]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":-111,"s":[{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-3,1.5],[0,-1.5],[3,1.5]],"c":false}]},{"t":-81,"s":[{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-3,3.967],[0,0.967],[3,3.967]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.125490196078,0.129411764706,0.141176470588,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[5.5,4],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-199,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":20,"ty":4,"nm":"Shape Layer 4","parent":1,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":-239,"s":[71,-116.083,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.7,"y":0},"t":-199,"s":[71,-101.083,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":365,"s":[71,-101.083,0],"to":[0,0,0],"ti":[16.833,-14.361,0]},{"t":405,"s":[-30,-14.917,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":-239,"s":[29,29]},{"i":{"x":[0.833,0.833],"y":[1,0.833]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":-199,"s":[29,38]},{"i":{"x":[0.833,0.833],"y":[0.833,0.833]},"o":{"x":[0.167,0.167],"y":[0.167,0.167]},"t":365,"s":[29,36]},{"t":405,"s":[83,83]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":365,"s":[50]},{"t":405,"s":[50]}],"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.400000029919,0.61568627451,0.964705942191,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-255,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":21,"ty":4,"nm":".grey900","cl":"grey900","parent":1,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":-239,"s":[71,-82.917,0],"to":[0,-1.25,0],"ti":[0,1.25,0]},{"t":-199,"s":[71,-90.417,0]}],"ix":2,"l":2},"a":{"a":0,"k":[5.5,4,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":-239,"s":[{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-0.07,1.5],[0,-1.5],[-0.047,1.5]],"c":false}]},{"t":-199,"s":[{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-3,1.5],[0,-1.5],[3,1.5]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.125490196078,0.129411764706,0.141176470588,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[5.5,4],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-255,"op":-199,"st":-255,"bm":0},{"ddd":0,"ind":22,"ty":4,"nm":"device frame mask","parent":24,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,1.167,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[326,201.699],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":8,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"st","c":{"a":0,"k":[0.250980392157,0.282352941176,0.294117647059,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.078246000701,0.610494037703,0.787910970052,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-255,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":23,"ty":4,"nm":".blue400","cl":"blue400","parent":18,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":-239,"s":[100.25,-115.167,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":-199,"s":[100.25,-100.167,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.7,"y":0},"t":-159,"s":[100.25,-105.667,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":365,"s":[100.25,-100.167,0],"to":[0,0,0],"ti":[16.833,-14.361,0]},{"t":405,"s":[-0.75,-14,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":-239,"s":[29,29]},{"i":{"x":[0.833,0.833],"y":[1,0.833]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":-199,"s":[29,38]},{"i":{"x":[0.833,0.833],"y":[0.833,0.833]},"o":{"x":[0.167,0.167],"y":[0.167,0.167]},"t":365,"s":[29,36]},{"t":405,"s":[83,83]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":365,"s":[50]},{"t":405,"s":[50]}],"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.400000029919,0.61568627451,0.964705942191,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-255,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":24,"ty":3,"nm":"device frame mask 5","parent":18,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ip":-165,"op":6.00000000000001,"st":-271,"bm":0},{"ddd":0,"ind":28,"ty":4,"nm":"device frame mask 9","parent":1,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-29.25,-0.917,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[326,201.699],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":8,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"st","c":{"a":0,"k":[0.250980392157,0.282352941176,0.294117647059,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.078246000701,0.610494037703,0.787910970052,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-181,"op":-62,"st":-181,"bm":0},{"ddd":0,"ind":29,"ty":4,"nm":".blue400","cl":"blue400","parent":23,"tt":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":-145,"s":[50]},{"t":-75,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":-165,"s":[0,0]},{"t":-75,"s":[94,94]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":73,"s":[50]},{"t":113,"s":[50]}],"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.4,0.61568627451,0.964705882353,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-181,"op":-62,"st":-181,"bm":0},{"ddd":0,"ind":30,"ty":4,"nm":"device frame mask 8","parent":1,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-29.25,-0.917,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[326,201.699],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":8,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"st","c":{"a":0,"k":[0.250980392157,0.282352941176,0.294117647059,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.078246000701,0.610494037703,0.787910970052,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-211,"op":-92,"st":-211,"bm":0},{"ddd":0,"ind":31,"ty":4,"nm":".blue400","cl":"blue400","parent":23,"tt":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":-165,"s":[50]},{"t":-95,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":-195,"s":[0,0]},{"t":-105,"s":[94,94]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":43,"s":[50]},{"t":83,"s":[50]}],"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.4,0.61568627451,0.964705882353,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-211,"op":-92,"st":-211,"bm":0},{"ddd":0,"ind":32,"ty":4,"nm":"device frame mask 7","parent":1,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-29.25,-0.917,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[326,201.699],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":8,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"st","c":{"a":0,"k":[0.250980392157,0.282352941176,0.294117647059,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.078246000701,0.610494037703,0.787910970052,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-241,"op":-122,"st":-241,"bm":0},{"ddd":0,"ind":33,"ty":4,"nm":".blue400","cl":"blue400","parent":23,"tt":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":-195,"s":[50]},{"t":-125,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":-225,"s":[0,0]},{"t":-135,"s":[94,94]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":13,"s":[50]},{"t":53,"s":[50]}],"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.4,0.61568627451,0.964705882353,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-241,"op":-122,"st":-241,"bm":0},{"ddd":0,"ind":34,"ty":4,"nm":"device frame mask 6","parent":1,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-29.25,-0.917,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[326,201.699],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":8,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"st","c":{"a":0,"k":[0.250980392157,0.282352941176,0.294117647059,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.078246000701,0.610494037703,0.787910970052,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-271,"op":-152,"st":-271,"bm":0},{"ddd":0,"ind":35,"ty":4,"nm":".blue400","cl":"blue400","parent":23,"tt":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":-225,"s":[50]},{"t":-155,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":-255,"s":[0,0]},{"t":-165,"s":[94,94]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":-17,"s":[50]},{"t":23,"s":[50]}],"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.4,0.61568627451,0.964705882353,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-271,"op":-152,"st":-271,"bm":0}]}],"layers":[{"ddd":0,"ind":6,"ty":0,"nm":"biometricprompt_landscape_base","refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":90,"ix":10},"p":{"a":0,"k":[170,170,0],"ix":2,"l":2},"a":{"a":0,"k":[170,170,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"w":340,"h":340,"ip":0,"op":900,"st":0,"bm":0}],"markers":[{"tm":255,"cm":"","dr":0},{"tm":364,"cm":"","dr":0},{"tm":482,"cm":"","dr":0},{"tm":600,"cm":"","dr":0}]}
\ No newline at end of file diff --git a/packages/SystemUI/res/raw/biometricprompt_portrait_base_topleft.json b/packages/SystemUI/res/raw/biometricprompt_portrait_base_topleft.json new file mode 100644 index 000000000000..b1616094ade4 --- /dev/null +++ b/packages/SystemUI/res/raw/biometricprompt_portrait_base_topleft.json @@ -0,0 +1 @@ +{"v":"5.9.0","fr":60,"ip":0,"op":21,"w":340,"h":340,"nm":"biometricprompt_portrait_base_topleft","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":6,"ty":3,"nm":"Null 16","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":-90,"ix":10},"p":{"a":0,"k":[170,170,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":7,"ty":3,"nm":"Null_Circle","parent":6,"sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":-108,"s":[70.333,-88.75,0],"to":[-11.722,17.639,0],"ti":[11.722,-17.639,0]},{"t":-48,"s":[0,17.083,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ip":-255,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":".grey905","cl":"grey905","parent":7,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0.333,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":-108,"s":[0,0]},{"t":-48,"s":[202,202]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.501960784314,0.525490196078,0.545098039216,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,-17.333],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-255,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"circle mask 3","parent":7,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0.333,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":-108,"s":[0,0]},{"t":-48,"s":[202,202]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.250980392157,0.282352941176,0.294117647059,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.078246000701,0.610494037703,0.787910970052,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,-17.333],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-255,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"Finger_Flipped","parent":6,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":90,"ix":10},"p":{"a":0,"k":[-24.98,-35.709,0],"ix":2,"l":2},"a":{"a":0,"k":[31.791,75.23,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[5.03,5.25],[-2.83,8.98],[-5.59,-0.26],[2.52,-11.02]],"o":[[-2.85,12.77],[2.07,-14.96],[1.9,-6],[1.4,8.05],[0,0]],"v":[[7.5,4.99],[-10.09,19.69],[-3.59,-16.61],[8.69,-24.92],[7.5,5]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.760784373564,0.478431402468,0.400000029919,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[27.8,24.94],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-7.01,22.23],[-1.2,-27.39],[4.09,-26.79],[15.73,14.18]],"o":[[5.64,-17.93],[2.45,56.06],[-22.4,-1.77],[17.73,-51.82]],"v":[[-7.57,-66.9],[30.82,-44.76],[26.65,75.23],[-31.78,50.08]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.678431372549,0.403921598547,0.305882352941,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[31.79,75.23],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":4,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"circle mask 7","parent":7,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0.333,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":-108,"s":[0,0]},{"t":-48,"s":[202,202]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.250980392157,0.282352941176,0.294117647059,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.078246000701,0.610494037703,0.787910970052,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,-17.333],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-255,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":".grey600","cl":"grey600","parent":7,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-0.25,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[114.218,-17.096],[-112.938,-17.096]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.501960784314,0.525490196078,0.545098039216,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":10,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":0,"k":36.9,"ix":2},"o":{"a":0,"k":114.2,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":-255,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":"circle mask","parent":7,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0.333,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":-108,"s":[0,0]},{"t":-48,"s":[202,202]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.250980392157,0.282352941176,0.294117647059,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.078246000701,0.610494037703,0.787910970052,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,-17.333],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-255,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":".grey904","cl":"grey904","parent":7,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-0.5,0,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[114.218,-17.096],[-112.938,-17.096]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.235294117647,0.250980392157,0.262745098039,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":10,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":0,"k":100,"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":-255,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":"circle mask 6","parent":7,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0.333,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":-108,"s":[0,0]},{"t":-48,"s":[202,202]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.250980392157,0.282352941176,0.294117647059,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.078246000701,0.610494037703,0.787910970052,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,-17.333],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-255,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":16,"ty":4,"nm":".grey903","cl":"grey903","parent":7,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":377,"s":[-180]},{"t":417,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":377,"s":[-1.137,1.771,0],"to":[0.375,0,0],"ti":[-0.375,0,0]},{"t":417,"s":[1.113,1.771,0]}],"ix":2,"l":2},"a":{"a":0,"k":[6.238,5.063,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":77,"s":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[-8.788,-4.637],[-10.23,-3.195],[-2.196,4.813],[5.988,-3.371],[4.545,-4.813],[-2.196,1.918]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":107,"s":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[-8.788,0.393],[-10.23,1.835],[-2.196,9.843],[5.988,1.659],[4.545,0.217],[-2.196,6.948]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":137,"s":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[-8.788,-4.637],[-10.23,-3.195],[-2.196,4.813],[5.988,-3.371],[4.545,-4.813],[-2.196,1.918]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":167,"s":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[-8.788,0.393],[-10.23,1.835],[-2.196,9.843],[5.988,1.659],[4.545,0.217],[-2.196,6.948]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.333,"y":0},"t":197,"s":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[-8.788,-4.637],[-10.23,-3.195],[-2.196,4.813],[5.988,-3.371],[4.545,-4.813],[-2.196,1.918]],"c":false}]},{"i":{"x":0.833,"y":1},"o":{"x":0.7,"y":0},"t":232,"s":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[-8.788,0.393],[-10.23,1.835],[-2.196,9.843],[5.988,1.659],[4.545,0.217],[-2.196,6.948]],"c":false}]},{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":562,"s":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[-8.788,0.393],[-10.23,1.835],[-2.196,9.843],[5.988,1.659],[4.545,0.217],[-2.196,6.948]],"c":false}]},{"t":602,"s":[{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[-4.546,-0.421],[-5.988,1.021],[-2.196,4.813],[5.988,-3.371],[4.545,-4.813],[-2.196,1.918]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.125490196078,0.129411764706,0.141176470588,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[6.238,5.063],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-255,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":17,"ty":4,"nm":"circle mask 2","parent":7,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0.333,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":-108,"s":[0,0]},{"t":-48,"s":[202,202]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.250980392157,0.282352941176,0.294117647059,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.078246000701,0.610494037703,0.787910970052,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,-17.333],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-255,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":18,"ty":4,"nm":".blue400","cl":"blue400","parent":7,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,8.308,0],"ix":2,"l":2},"a":{"a":0,"k":[41.706,20.979,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[18.645,0],[0,18.645]],"o":[[0,18.645],[-18.644,0],[0,0]],"v":[[33.76,-16.88],[-0.001,16.88],[-33.76,-16.88]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.400000029919,0.61568627451,0.964705942191,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[41.706,17.13],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[22.896,0],[0,22.896]],"o":[[0,22.896],[-22.896,0],[0,0]],"v":[[41.457,-20.729],[-0.001,20.729],[-41.457,-20.729]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.400000029919,0.61568627451,0.964705942191,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[41.706,20.979],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":4,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":-255,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":19,"ty":4,"nm":"circle mask 4","parent":7,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0.333,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":-108,"s":[0,0]},{"t":-48,"s":[202,202]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.250980392157,0.282352941176,0.294117647059,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.078246000701,0.610494037703,0.787910970052,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,-17.333],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-255,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":20,"ty":1,"nm":".grey902","cl":"grey902","parent":7,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,66,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[52,52,100],"ix":6,"l":2}},"ao":0,"sw":412,"sh":300,"sc":"#202124","ip":-255,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":21,"ty":4,"nm":"circle mask 5","parent":7,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,0.333,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":-108,"s":[0,0]},{"t":-48,"s":[202,202]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.250980392157,0.282352941176,0.294117647059,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.078246000701,0.610494037703,0.787910970052,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,-17.333],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-255,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":22,"ty":1,"nm":".black","cl":"black","parent":7,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0,-17.333,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[72,72,100],"ix":6,"l":2}},"ao":0,"sw":412,"sh":300,"sc":"#000000","ip":-255,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":23,"ty":4,"nm":".grey800","cl":"grey800","parent":6,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":-108,"s":[-192.25,99.933,0],"to":[5,3.333,0],"ti":[-5,-3.333,0]},{"t":-48,"s":[-162.25,119.933,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-163,100.85,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2,0.833],"y":[1,1,1]},"o":{"x":[0.7,0.7,0.167],"y":[0,0,0]},"t":-108,"s":[100,100,100]},{"t":-48,"s":[59,59,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[326,201.699],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":8,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"st","c":{"a":0,"k":[0.235294117647,0.250980392157,0.262745098039,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-255,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":24,"ty":4,"nm":".grey901","cl":"grey901","parent":23,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":-239,"s":[100.25,-87.156,0],"to":[0,-1.25,0],"ti":[0,1.25,0]},{"t":-199,"s":[100.25,-94.656,0]}],"ix":2,"l":2},"a":{"a":0,"k":[5.5,4,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.7,"y":0},"t":-239,"s":[{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-0.07,1.5],[0,-1.5],[-0.047,1.5]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":-199,"s":[{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-3,1.5],[0,-1.5],[3,1.5]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":-171,"s":[{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-3,1.5],[0,-1.5],[3,1.5]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":-141,"s":[{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-3,3.512],[0,0.512],[3,3.512]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":-111,"s":[{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-3,1.5],[0,-1.5],[3,1.5]],"c":false}]},{"t":-81,"s":[{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-3,3.967],[0,0.967],[3,3.967]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.125490196078,0.129411764706,0.141176470588,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[5.5,4],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-199,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":25,"ty":4,"nm":"Shape Layer 4","parent":6,"td":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":-239,"s":[71,-116.083,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.7,"y":0},"t":-199,"s":[71,-101.083,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":365,"s":[71,-101.083,0],"to":[0,0,0],"ti":[16.833,-14.361,0]},{"t":405,"s":[-30,-14.917,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":-239,"s":[29,29]},{"i":{"x":[0.833,0.833],"y":[1,0.833]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":-199,"s":[29,38]},{"i":{"x":[0.833,0.833],"y":[0.833,0.833]},"o":{"x":[0.167,0.167],"y":[0.167,0.167]},"t":365,"s":[29,36]},{"t":405,"s":[83,83]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":365,"s":[50]},{"t":405,"s":[50]}],"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.400000029919,0.61568627451,0.964705942191,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Rectangle 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-255,"op":645,"st":-255,"bm":0},{"ddd":0,"ind":26,"ty":4,"nm":".grey900","cl":"grey900","parent":6,"tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":-239,"s":[71,-82.917,0],"to":[0,-1.25,0],"ti":[0,1.25,0]},{"t":-199,"s":[71,-90.417,0]}],"ix":2,"l":2},"a":{"a":0,"k":[5.5,4,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":-239,"s":[{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-0.07,1.5],[0,-1.5],[-0.047,1.5]],"c":false}]},{"t":-199,"s":[{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-3,1.5],[0,-1.5],[3,1.5]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.125490196078,0.129411764706,0.141176470588,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":1,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[5.5,4],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":-255,"op":-199,"st":-255,"bm":0}],"markers":[{"tm":255,"cm":"","dr":0},{"tm":364,"cm":"","dr":0},{"tm":482,"cm":"","dr":0},{"tm":600,"cm":"","dr":0}]}
\ No newline at end of file diff --git a/packages/SystemUI/res/raw/biometricprompt_symbol_error_to_fingerprint_landscape.json b/packages/SystemUI/res/raw/biometricprompt_symbol_error_to_fingerprint_landscape.json new file mode 100644 index 000000000000..034ac87c0f94 --- /dev/null +++ b/packages/SystemUI/res/raw/biometricprompt_symbol_error_to_fingerprint_landscape.json @@ -0,0 +1 @@ +{"v":"5.9.0","fr":60,"ip":0,"op":21,"w":340,"h":340,"nm":"biometricprompt_symbol_error_to_fingerprint_landscape","ddd":0,"assets":[{"id":"comp_0","nm":"Fingerprint_Animation_ForConfirm_Short_For_ErrorToFingerprint","fr":60,"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"circle fill 5","td":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":239,"s":[0]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":249,"s":[100]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":388,"s":[100]},{"t":408,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,62.45],[-62.45,0],[0,-62.45],[62.45,0]],"o":[[0,-62.45],[62.45,0],[0,62.45],[-62.45,0]],"v":[[-113.08,0],[0,-113.08],[113.08,0],[0,113.08]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[206,150],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333393172,0.403921598547,0.360784313725,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":239,"op":1411,"st":239,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".white","cl":"white","tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-52.056,-2.445],[-17.306,32.25],[52.194,-37.194]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":14,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":239,"s":[0]},{"t":249,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":239,"op":1139,"st":239,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".green400","cl":"green400","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":239,"s":[0]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":249,"s":[100]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":388,"s":[100]},{"t":408,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,62.45],[-62.45,0],[0,-62.45],[62.45,0]],"o":[[0,-62.45],[62.45,0],[0,62.45],[-62.45,0]],"v":[[-113.08,0],[0,-113.08],[113.08,0],[0,113.08]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[206,150],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.450980392157,0.709803921569,0.470588235294,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":239,"op":1411,"st":239,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"circle fill 3","td":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":80,"s":[0]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":90,"s":[100]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":108,"s":[100]},{"t":118,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,62.45],[-62.45,0],[0,-62.45],[62.45,0]],"o":[[0,-62.45],[62.45,0],[0,62.45],[-62.45,0]],"v":[[-113.08,0],[0,-113.08],[113.08,0],[0,113.08]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[206,150],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333393172,0.403921598547,0.360784313725,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":80,"op":1252,"st":80,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".white","cl":"white","tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":80,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.111,14.055],[-0.056,14.056]],"c":false}]},{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":90,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.056,-49.945],[-0.056,14.056]],"c":false}]},{"i":{"x":0.2,"y":1},"o":{"x":0.8,"y":0},"t":108,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.056,-49.945],[-0.056,14.056]],"c":false}]},{"t":118,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.111,14.055],[-0.056,14.056]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":14,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":80,"s":[0,0]},{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":90,"s":[100,100]},{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.8,0.8],"y":[0,0]},"t":108,"s":[100,100]},{"t":118,"s":[0,0]}],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.056,35.389],[-0.111,50.111]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":14,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0.049,42.698],"ix":2},"a":{"a":0,"k":[0.049,42.698],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":80,"s":[0,0]},{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":90,"s":[100,100]},{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.8,0.8],"y":[0,0]},"t":108,"s":[100,100]},{"t":118,"s":[0,0]}],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 2","np":3,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":80,"op":980,"st":80,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":".red400","cl":"red400","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":80,"s":[0]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":90,"s":[100]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":108,"s":[100]},{"t":118,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,62.45],[-62.45,0],[0,-62.45],[62.45,0]],"o":[[0,-62.45],[62.45,0],[0,62.45],[-62.45,0]],"v":[[-113.08,0],[0,-113.08],[113.08,0],[0,113.08]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[206,150],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333393172,0.403921598547,0.360784313725,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":80,"op":1252,"st":80,"bm":0},{"ddd":0,"ind":7,"ty":3,"nm":"Null 1","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0.333},"t":85,"s":[209.333,136.333,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":440,"s":[209.333,136.333,0],"to":[1.944,2.278,0],"ti":[3.056,-2.278,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":450,"s":[221,150,0],"to":[-3.056,2.278,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":460,"s":[191,150,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":470,"s":[221,150,0],"to":[0,0,0],"ti":[2.5,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":480,"s":[191,150,0],"to":[-2.5,0,0],"ti":[-2.5,0,0]},{"t":490,"s":[206,150,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[132,132,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":0,"nm":"Fingerprint_Animation_ForConfirm_Short_For_ErrorToFingerprint","refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[170,77.667,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[30,30,100],"ix":6,"l":2}},"ao":0,"w":412,"h":300,"ip":0,"op":792,"st":-108,"bm":0}],"markers":[{"tm":255,"cm":"","dr":0},{"tm":364,"cm":"","dr":0},{"tm":482,"cm":"","dr":0},{"tm":600,"cm":"","dr":0}]}
\ No newline at end of file diff --git a/packages/SystemUI/res/raw/biometricprompt_symbol_error_to_fingerprint_portrait_bottomright.json b/packages/SystemUI/res/raw/biometricprompt_symbol_error_to_fingerprint_portrait_bottomright.json new file mode 100644 index 000000000000..e5cc565e31d8 --- /dev/null +++ b/packages/SystemUI/res/raw/biometricprompt_symbol_error_to_fingerprint_portrait_bottomright.json @@ -0,0 +1 @@ +{"v":"5.9.0","fr":60,"ip":0,"op":21,"w":340,"h":340,"nm":"biometricprompt_symbol_error_to_fingerprint_portrait_bottomright","ddd":0,"assets":[{"id":"comp_0","nm":"Fingerprint_Animation_ForConfirm_Short_For_ErrorToFingerprint","fr":60,"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"circle fill 5","td":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":239,"s":[0]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":249,"s":[100]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":388,"s":[100]},{"t":408,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,62.45],[-62.45,0],[0,-62.45],[62.45,0]],"o":[[0,-62.45],[62.45,0],[0,62.45],[-62.45,0]],"v":[[-113.08,0],[0,-113.08],[113.08,0],[0,113.08]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[206,150],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333393172,0.403921598547,0.360784313725,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":239,"op":1411,"st":239,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".white","cl":"white","tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-52.056,-2.445],[-17.306,32.25],[52.194,-37.194]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":14,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":239,"s":[0]},{"t":249,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":239,"op":1139,"st":239,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".green400","cl":"green400","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":239,"s":[0]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":249,"s":[100]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":388,"s":[100]},{"t":408,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,62.45],[-62.45,0],[0,-62.45],[62.45,0]],"o":[[0,-62.45],[62.45,0],[0,62.45],[-62.45,0]],"v":[[-113.08,0],[0,-113.08],[113.08,0],[0,113.08]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[206,150],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.450980392157,0.709803921569,0.470588235294,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":239,"op":1411,"st":239,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"circle fill 3","td":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":80,"s":[0]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":90,"s":[100]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":108,"s":[100]},{"t":118,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,62.45],[-62.45,0],[0,-62.45],[62.45,0]],"o":[[0,-62.45],[62.45,0],[0,62.45],[-62.45,0]],"v":[[-113.08,0],[0,-113.08],[113.08,0],[0,113.08]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[206,150],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333393172,0.403921598547,0.360784313725,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":80,"op":1252,"st":80,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".white","cl":"white","tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":80,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.111,14.055],[-0.056,14.056]],"c":false}]},{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":90,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.056,-49.945],[-0.056,14.056]],"c":false}]},{"i":{"x":0.2,"y":1},"o":{"x":0.8,"y":0},"t":108,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.056,-49.945],[-0.056,14.056]],"c":false}]},{"t":118,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.111,14.055],[-0.056,14.056]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":14,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":80,"s":[0,0]},{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":90,"s":[100,100]},{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.8,0.8],"y":[0,0]},"t":108,"s":[100,100]},{"t":118,"s":[0,0]}],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.056,35.389],[-0.111,50.111]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":14,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0.049,42.698],"ix":2},"a":{"a":0,"k":[0.049,42.698],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":80,"s":[0,0]},{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":90,"s":[100,100]},{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.8,0.8],"y":[0,0]},"t":108,"s":[100,100]},{"t":118,"s":[0,0]}],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 2","np":3,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":80,"op":980,"st":80,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":".red400","cl":"red400","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":80,"s":[0]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":90,"s":[100]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":108,"s":[100]},{"t":118,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,62.45],[-62.45,0],[0,-62.45],[62.45,0]],"o":[[0,-62.45],[62.45,0],[0,62.45],[-62.45,0]],"v":[[-113.08,0],[0,-113.08],[113.08,0],[0,113.08]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[206,150],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333393172,0.403921598547,0.360784313725,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":80,"op":1252,"st":80,"bm":0},{"ddd":0,"ind":7,"ty":3,"nm":"Null 1","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0.333},"t":85,"s":[209.333,136.333,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":440,"s":[209.333,136.333,0],"to":[1.944,2.278,0],"ti":[3.056,-2.278,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":450,"s":[221,150,0],"to":[-3.056,2.278,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":460,"s":[191,150,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":470,"s":[221,150,0],"to":[0,0,0],"ti":[2.5,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":480,"s":[191,150,0],"to":[-2.5,0,0],"ti":[-2.5,0,0]},{"t":490,"s":[206,150,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[132,132,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 12","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":90,"ix":10},"p":{"a":0,"k":[170,170,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":0,"nm":"Fingerprint_Animation_ForConfirm_Short_For_ErrorToFingerprint","parent":1,"refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":-90,"ix":10},"p":{"a":0,"k":[0,-92.333,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[30,30,100],"ix":6,"l":2}},"ao":0,"w":412,"h":300,"ip":0,"op":792,"st":-108,"bm":0}],"markers":[{"tm":255,"cm":"","dr":0},{"tm":364,"cm":"","dr":0},{"tm":482,"cm":"","dr":0},{"tm":600,"cm":"","dr":0}]}
\ No newline at end of file diff --git a/packages/SystemUI/res/raw/biometricprompt_symbol_error_to_fingerprint_portrait_topleft.json b/packages/SystemUI/res/raw/biometricprompt_symbol_error_to_fingerprint_portrait_topleft.json new file mode 100644 index 000000000000..b08226551a02 --- /dev/null +++ b/packages/SystemUI/res/raw/biometricprompt_symbol_error_to_fingerprint_portrait_topleft.json @@ -0,0 +1 @@ +{"v":"5.9.0","fr":60,"ip":0,"op":21,"w":340,"h":340,"nm":"biometricprompt_symbol_error_to_fingerprint_portrait_topleft","ddd":0,"assets":[{"id":"comp_0","nm":"Fingerprint_Animation_ForConfirm_Short_For_ErrorToFingerprint","fr":60,"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"circle fill 5","td":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":239,"s":[0]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":249,"s":[100]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":388,"s":[100]},{"t":408,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,62.45],[-62.45,0],[0,-62.45],[62.45,0]],"o":[[0,-62.45],[62.45,0],[0,62.45],[-62.45,0]],"v":[[-113.08,0],[0,-113.08],[113.08,0],[0,113.08]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[206,150],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333393172,0.403921598547,0.360784313725,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":239,"op":1411,"st":239,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".white","cl":"white","tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-52.056,-2.445],[-17.306,32.25],[52.194,-37.194]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":14,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":239,"s":[0]},{"t":249,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":239,"op":1139,"st":239,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".green400","cl":"green400","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":239,"s":[0]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":249,"s":[100]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":388,"s":[100]},{"t":408,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,62.45],[-62.45,0],[0,-62.45],[62.45,0]],"o":[[0,-62.45],[62.45,0],[0,62.45],[-62.45,0]],"v":[[-113.08,0],[0,-113.08],[113.08,0],[0,113.08]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[206,150],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.450980392157,0.709803921569,0.470588235294,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":239,"op":1411,"st":239,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"circle fill 3","td":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":80,"s":[0]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":90,"s":[100]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":108,"s":[100]},{"t":118,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,62.45],[-62.45,0],[0,-62.45],[62.45,0]],"o":[[0,-62.45],[62.45,0],[0,62.45],[-62.45,0]],"v":[[-113.08,0],[0,-113.08],[113.08,0],[0,113.08]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[206,150],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333393172,0.403921598547,0.360784313725,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":80,"op":1252,"st":80,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".white","cl":"white","tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":80,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.111,14.055],[-0.056,14.056]],"c":false}]},{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":90,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.056,-49.945],[-0.056,14.056]],"c":false}]},{"i":{"x":0.2,"y":1},"o":{"x":0.8,"y":0},"t":108,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.056,-49.945],[-0.056,14.056]],"c":false}]},{"t":118,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.111,14.055],[-0.056,14.056]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":14,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":80,"s":[0,0]},{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":90,"s":[100,100]},{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.8,0.8],"y":[0,0]},"t":108,"s":[100,100]},{"t":118,"s":[0,0]}],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.056,35.389],[-0.111,50.111]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":14,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0.049,42.698],"ix":2},"a":{"a":0,"k":[0.049,42.698],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":80,"s":[0,0]},{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":90,"s":[100,100]},{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.8,0.8],"y":[0,0]},"t":108,"s":[100,100]},{"t":118,"s":[0,0]}],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 2","np":3,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":80,"op":980,"st":80,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":".red400","cl":"red400","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":80,"s":[0]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":90,"s":[100]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":108,"s":[100]},{"t":118,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,62.45],[-62.45,0],[0,-62.45],[62.45,0]],"o":[[0,-62.45],[62.45,0],[0,62.45],[-62.45,0]],"v":[[-113.08,0],[0,-113.08],[113.08,0],[0,113.08]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[206,150],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333393172,0.403921598547,0.360784313725,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":80,"op":1252,"st":80,"bm":0},{"ddd":0,"ind":7,"ty":3,"nm":"Null 1","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0.333},"t":85,"s":[209.333,136.333,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":440,"s":[209.333,136.333,0],"to":[1.944,2.278,0],"ti":[3.056,-2.278,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":450,"s":[221,150,0],"to":[-3.056,2.278,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":460,"s":[191,150,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":470,"s":[221,150,0],"to":[0,0,0],"ti":[2.5,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":480,"s":[191,150,0],"to":[-2.5,0,0],"ti":[-2.5,0,0]},{"t":490,"s":[206,150,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[132,132,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 12","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":-90,"ix":10},"p":{"a":0,"k":[170,170,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":0,"nm":"Fingerprint_Animation_ForConfirm_Short_For_ErrorToFingerprint","parent":1,"refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":90,"ix":10},"p":{"a":0,"k":[0,-92.333,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[30,30,100],"ix":6,"l":2}},"ao":0,"w":412,"h":300,"ip":0,"op":792,"st":-108,"bm":0}],"markers":[{"tm":255,"cm":"","dr":0},{"tm":364,"cm":"","dr":0},{"tm":482,"cm":"","dr":0},{"tm":600,"cm":"","dr":0}]}
\ No newline at end of file diff --git a/packages/SystemUI/res/raw/biometricprompt_symbol_error_to_success_landscape.json b/packages/SystemUI/res/raw/biometricprompt_symbol_error_to_success_landscape.json new file mode 100644 index 000000000000..befe3bb61cca --- /dev/null +++ b/packages/SystemUI/res/raw/biometricprompt_symbol_error_to_success_landscape.json @@ -0,0 +1 @@ +{"v":"5.9.0","fr":60,"ip":0,"op":21,"w":340,"h":340,"nm":"biometricprompt_symbol_error_to_success_landscape","ddd":0,"assets":[{"id":"comp_0","nm":"Fingerprint_Animation_ForConfirm_ErrorToSuccess","fr":60,"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"circle fill 5","td":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":108,"s":[0]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":118,"s":[100]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":257,"s":[100]},{"t":277,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,62.45],[-62.45,0],[0,-62.45],[62.45,0]],"o":[[0,-62.45],[62.45,0],[0,62.45],[-62.45,0]],"v":[[-113.08,0],[0,-113.08],[113.08,0],[0,113.08]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[206,150],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333393172,0.403921598547,0.360784313725,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":108,"op":1280,"st":108,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".white","cl":"white","tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-52.056,-2.445],[-17.306,32.25],[52.194,-37.194]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":14,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":112,"s":[0]},{"t":122,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":112,"op":1012,"st":112,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".green400","cl":"green400","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":108,"s":[0]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":118,"s":[100]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":257,"s":[100]},{"t":277,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,62.45],[-62.45,0],[0,-62.45],[62.45,0]],"o":[[0,-62.45],[62.45,0],[0,62.45],[-62.45,0]],"v":[[-113.08,0],[0,-113.08],[113.08,0],[0,113.08]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[206,150],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.450980392157,0.709803921569,0.470588235294,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":108,"op":1280,"st":108,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"circle fill 3","td":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":80,"s":[0]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":90,"s":[100]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":108,"s":[100]},{"t":118,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,62.45],[-62.45,0],[0,-62.45],[62.45,0]],"o":[[0,-62.45],[62.45,0],[0,62.45],[-62.45,0]],"v":[[-113.08,0],[0,-113.08],[113.08,0],[0,113.08]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[206,150],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333393172,0.403921598547,0.360784313725,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":80,"op":1252,"st":80,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".white","cl":"white","tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":80,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.111,14.055],[-0.056,14.056]],"c":false}]},{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":90,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.056,-49.945],[-0.056,14.056]],"c":false}]},{"i":{"x":0.2,"y":1},"o":{"x":0.8,"y":0},"t":108,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.056,-49.945],[-0.056,14.056]],"c":false}]},{"t":118,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.111,14.055],[-0.056,14.056]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":14,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":80,"s":[0,0]},{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":90,"s":[100,100]},{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.8,0.8],"y":[0,0]},"t":108,"s":[100,100]},{"t":118,"s":[0,0]}],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.056,35.389],[-0.111,50.111]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":14,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0.049,42.698],"ix":2},"a":{"a":0,"k":[0.049,42.698],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":80,"s":[0,0]},{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":90,"s":[100,100]},{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.8,0.8],"y":[0,0]},"t":108,"s":[100,100]},{"t":118,"s":[0,0]}],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 2","np":3,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":80,"op":980,"st":80,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":".red400","cl":"red400","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":80,"s":[0]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":90,"s":[100]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":108,"s":[100]},{"t":118,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,62.45],[-62.45,0],[0,-62.45],[62.45,0]],"o":[[0,-62.45],[62.45,0],[0,62.45],[-62.45,0]],"v":[[-113.08,0],[0,-113.08],[113.08,0],[0,113.08]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[206,150],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333393172,0.403921598547,0.360784313725,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":80,"op":1252,"st":80,"bm":0},{"ddd":0,"ind":7,"ty":3,"nm":"Null 1","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0.333},"t":85,"s":[209.333,136.333,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":440,"s":[209.333,136.333,0],"to":[1.944,2.278,0],"ti":[3.056,-2.278,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":450,"s":[221,150,0],"to":[-3.056,2.278,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":460,"s":[191,150,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":470,"s":[221,150,0],"to":[0,0,0],"ti":[2.5,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":480,"s":[191,150,0],"to":[-2.5,0,0],"ti":[-2.5,0,0]},{"t":490,"s":[206,150,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[132,132,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":0,"nm":"Fingerprint_Animation_ForConfirm_ErrorToSuccess","refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[170,77.667,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[30,30,100],"ix":6,"l":2}},"ao":0,"w":412,"h":300,"ip":0,"op":792,"st":-108,"bm":0}],"markers":[{"tm":255,"cm":"","dr":0},{"tm":364,"cm":"","dr":0},{"tm":482,"cm":"","dr":0},{"tm":600,"cm":"","dr":0}]}
\ No newline at end of file diff --git a/packages/SystemUI/res/raw/biometricprompt_symbol_error_to_success_portrait_bottomright.json b/packages/SystemUI/res/raw/biometricprompt_symbol_error_to_success_portrait_bottomright.json new file mode 100644 index 000000000000..d75b335747ce --- /dev/null +++ b/packages/SystemUI/res/raw/biometricprompt_symbol_error_to_success_portrait_bottomright.json @@ -0,0 +1 @@ +{"v":"5.9.0","fr":60,"ip":0,"op":21,"w":340,"h":340,"nm":"biometricprompt_symbol_error_to_success_portrait_bottomright","ddd":0,"assets":[{"id":"comp_0","nm":"Fingerprint_Animation_ForConfirm_ErrorToSuccess","fr":60,"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"circle fill 5","td":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":108,"s":[0]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":118,"s":[100]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":257,"s":[100]},{"t":277,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,62.45],[-62.45,0],[0,-62.45],[62.45,0]],"o":[[0,-62.45],[62.45,0],[0,62.45],[-62.45,0]],"v":[[-113.08,0],[0,-113.08],[113.08,0],[0,113.08]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[206,150],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333393172,0.403921598547,0.360784313725,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":108,"op":1280,"st":108,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".white","cl":"white","tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-52.056,-2.445],[-17.306,32.25],[52.194,-37.194]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":14,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":112,"s":[0]},{"t":122,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":112,"op":1012,"st":112,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".green400","cl":"green400","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":108,"s":[0]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":118,"s":[100]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":257,"s":[100]},{"t":277,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,62.45],[-62.45,0],[0,-62.45],[62.45,0]],"o":[[0,-62.45],[62.45,0],[0,62.45],[-62.45,0]],"v":[[-113.08,0],[0,-113.08],[113.08,0],[0,113.08]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[206,150],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.450980392157,0.709803921569,0.470588235294,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":108,"op":1280,"st":108,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"circle fill 3","td":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":80,"s":[0]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":90,"s":[100]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":108,"s":[100]},{"t":118,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,62.45],[-62.45,0],[0,-62.45],[62.45,0]],"o":[[0,-62.45],[62.45,0],[0,62.45],[-62.45,0]],"v":[[-113.08,0],[0,-113.08],[113.08,0],[0,113.08]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[206,150],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333393172,0.403921598547,0.360784313725,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":80,"op":1252,"st":80,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".white","cl":"white","tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":80,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.111,14.055],[-0.056,14.056]],"c":false}]},{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":90,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.056,-49.945],[-0.056,14.056]],"c":false}]},{"i":{"x":0.2,"y":1},"o":{"x":0.8,"y":0},"t":108,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.056,-49.945],[-0.056,14.056]],"c":false}]},{"t":118,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.111,14.055],[-0.056,14.056]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":14,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":80,"s":[0,0]},{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":90,"s":[100,100]},{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.8,0.8],"y":[0,0]},"t":108,"s":[100,100]},{"t":118,"s":[0,0]}],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.056,35.389],[-0.111,50.111]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":14,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0.049,42.698],"ix":2},"a":{"a":0,"k":[0.049,42.698],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":80,"s":[0,0]},{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":90,"s":[100,100]},{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.8,0.8],"y":[0,0]},"t":108,"s":[100,100]},{"t":118,"s":[0,0]}],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 2","np":3,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":80,"op":980,"st":80,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":".red400","cl":"red400","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":80,"s":[0]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":90,"s":[100]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":108,"s":[100]},{"t":118,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,62.45],[-62.45,0],[0,-62.45],[62.45,0]],"o":[[0,-62.45],[62.45,0],[0,62.45],[-62.45,0]],"v":[[-113.08,0],[0,-113.08],[113.08,0],[0,113.08]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[206,150],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333393172,0.403921598547,0.360784313725,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":80,"op":1252,"st":80,"bm":0},{"ddd":0,"ind":7,"ty":3,"nm":"Null 1","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0.333},"t":85,"s":[209.333,136.333,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":440,"s":[209.333,136.333,0],"to":[1.944,2.278,0],"ti":[3.056,-2.278,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":450,"s":[221,150,0],"to":[-3.056,2.278,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":460,"s":[191,150,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":470,"s":[221,150,0],"to":[0,0,0],"ti":[2.5,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":480,"s":[191,150,0],"to":[-2.5,0,0],"ti":[-2.5,0,0]},{"t":490,"s":[206,150,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[132,132,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 13","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":90,"ix":10},"p":{"a":0,"k":[170,170,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":0,"nm":"Fingerprint_Animation_ForConfirm_ErrorToSuccess","parent":1,"refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":-90,"ix":10},"p":{"a":0,"k":[0,-92.333,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[30,30,100],"ix":6,"l":2}},"ao":0,"w":412,"h":300,"ip":0,"op":792,"st":-108,"bm":0}],"markers":[{"tm":255,"cm":"","dr":0},{"tm":364,"cm":"","dr":0},{"tm":482,"cm":"","dr":0},{"tm":600,"cm":"","dr":0}]}
\ No newline at end of file diff --git a/packages/SystemUI/res/raw/biometricprompt_symbol_error_to_success_portrait_topleft.json b/packages/SystemUI/res/raw/biometricprompt_symbol_error_to_success_portrait_topleft.json new file mode 100644 index 000000000000..e6b2db1fd537 --- /dev/null +++ b/packages/SystemUI/res/raw/biometricprompt_symbol_error_to_success_portrait_topleft.json @@ -0,0 +1 @@ +{"v":"5.9.0","fr":60,"ip":0,"op":21,"w":340,"h":340,"nm":"biometricprompt_symbol_error_to_success_portrait_topleft","ddd":0,"assets":[{"id":"comp_0","nm":"Fingerprint_Animation_ForConfirm_ErrorToSuccess","fr":60,"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"circle fill 5","td":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":108,"s":[0]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":118,"s":[100]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":257,"s":[100]},{"t":277,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,62.45],[-62.45,0],[0,-62.45],[62.45,0]],"o":[[0,-62.45],[62.45,0],[0,62.45],[-62.45,0]],"v":[[-113.08,0],[0,-113.08],[113.08,0],[0,113.08]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[206,150],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333393172,0.403921598547,0.360784313725,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":108,"op":1280,"st":108,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".white","cl":"white","tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-52.056,-2.445],[-17.306,32.25],[52.194,-37.194]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":14,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":112,"s":[0]},{"t":122,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":112,"op":1012,"st":112,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".green400","cl":"green400","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":108,"s":[0]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":118,"s":[100]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":257,"s":[100]},{"t":277,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,62.45],[-62.45,0],[0,-62.45],[62.45,0]],"o":[[0,-62.45],[62.45,0],[0,62.45],[-62.45,0]],"v":[[-113.08,0],[0,-113.08],[113.08,0],[0,113.08]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[206,150],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.450980392157,0.709803921569,0.470588235294,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":108,"op":1280,"st":108,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"circle fill 3","td":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":80,"s":[0]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":90,"s":[100]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":108,"s":[100]},{"t":118,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,62.45],[-62.45,0],[0,-62.45],[62.45,0]],"o":[[0,-62.45],[62.45,0],[0,62.45],[-62.45,0]],"v":[[-113.08,0],[0,-113.08],[113.08,0],[0,113.08]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[206,150],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333393172,0.403921598547,0.360784313725,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":80,"op":1252,"st":80,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".white","cl":"white","tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":80,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.111,14.055],[-0.056,14.056]],"c":false}]},{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":90,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.056,-49.945],[-0.056,14.056]],"c":false}]},{"i":{"x":0.2,"y":1},"o":{"x":0.8,"y":0},"t":108,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.056,-49.945],[-0.056,14.056]],"c":false}]},{"t":118,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.111,14.055],[-0.056,14.056]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":14,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":80,"s":[0,0]},{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":90,"s":[100,100]},{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.8,0.8],"y":[0,0]},"t":108,"s":[100,100]},{"t":118,"s":[0,0]}],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.056,35.389],[-0.111,50.111]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":14,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0.049,42.698],"ix":2},"a":{"a":0,"k":[0.049,42.698],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":80,"s":[0,0]},{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":90,"s":[100,100]},{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.8,0.8],"y":[0,0]},"t":108,"s":[100,100]},{"t":118,"s":[0,0]}],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 2","np":3,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":80,"op":980,"st":80,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":".red400","cl":"red400","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":80,"s":[0]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":90,"s":[100]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":108,"s":[100]},{"t":118,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,62.45],[-62.45,0],[0,-62.45],[62.45,0]],"o":[[0,-62.45],[62.45,0],[0,62.45],[-62.45,0]],"v":[[-113.08,0],[0,-113.08],[113.08,0],[0,113.08]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[206,150],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333393172,0.403921598547,0.360784313725,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":80,"op":1252,"st":80,"bm":0},{"ddd":0,"ind":7,"ty":3,"nm":"Null 1","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0.333},"t":85,"s":[209.333,136.333,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":440,"s":[209.333,136.333,0],"to":[1.944,2.278,0],"ti":[3.056,-2.278,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":450,"s":[221,150,0],"to":[-3.056,2.278,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":460,"s":[191,150,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":470,"s":[221,150,0],"to":[0,0,0],"ti":[2.5,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":480,"s":[191,150,0],"to":[-2.5,0,0],"ti":[-2.5,0,0]},{"t":490,"s":[206,150,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[132,132,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 13","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":-90,"ix":10},"p":{"a":0,"k":[170,170,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":0,"nm":"Fingerprint_Animation_ForConfirm_ErrorToSuccess","parent":1,"refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":90,"ix":10},"p":{"a":0,"k":[0,-92.333,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[30,30,100],"ix":6,"l":2}},"ao":0,"w":412,"h":300,"ip":0,"op":792,"st":-108,"bm":0}],"markers":[{"tm":255,"cm":"","dr":0},{"tm":364,"cm":"","dr":0},{"tm":482,"cm":"","dr":0},{"tm":600,"cm":"","dr":0}]}
\ No newline at end of file diff --git a/packages/SystemUI/res/raw/biometricprompt_symbol_fingerprint_to_error_portrait_bottomright.json b/packages/SystemUI/res/raw/biometricprompt_symbol_fingerprint_to_error_portrait_bottomright.json new file mode 100644 index 000000000000..0da143c9243a --- /dev/null +++ b/packages/SystemUI/res/raw/biometricprompt_symbol_fingerprint_to_error_portrait_bottomright.json @@ -0,0 +1 @@ +{"v":"5.9.0","fr":60,"ip":0,"op":21,"w":340,"h":340,"nm":"biometricprompt_symbol_fingerprint_to_error_portrait_bottomright","ddd":0,"assets":[{"id":"comp_0","nm":"Fingerprint_Animation_ForConfirm_Short","fr":60,"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"circle fill 5","td":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":239,"s":[0]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":249,"s":[100]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":388,"s":[100]},{"t":408,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,62.45],[-62.45,0],[0,-62.45],[62.45,0]],"o":[[0,-62.45],[62.45,0],[0,62.45],[-62.45,0]],"v":[[-113.08,0],[0,-113.08],[113.08,0],[0,113.08]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[206,150],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333393172,0.403921598547,0.360784313725,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":239,"op":1411,"st":239,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".white","cl":"white","tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-52.056,-2.445],[-17.306,32.25],[52.194,-37.194]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":14,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":239,"s":[0]},{"t":249,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":239,"op":1139,"st":239,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".green400","cl":"green400","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":239,"s":[0]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":249,"s":[100]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":388,"s":[100]},{"t":408,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,62.45],[-62.45,0],[0,-62.45],[62.45,0]],"o":[[0,-62.45],[62.45,0],[0,62.45],[-62.45,0]],"v":[[-113.08,0],[0,-113.08],[113.08,0],[0,113.08]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[206,150],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.450980392157,0.709803921569,0.470588235294,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":239,"op":1411,"st":239,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"circle fill 3","td":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":80,"s":[0]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":90,"s":[100]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":108,"s":[100]},{"t":118,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,62.45],[-62.45,0],[0,-62.45],[62.45,0]],"o":[[0,-62.45],[62.45,0],[0,62.45],[-62.45,0]],"v":[[-113.08,0],[0,-113.08],[113.08,0],[0,113.08]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[206,150],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333393172,0.403921598547,0.360784313725,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":80,"op":1252,"st":80,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".white","cl":"white","tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":80,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.111,14.055],[-0.056,14.056]],"c":false}]},{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":90,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.056,-49.945],[-0.056,14.056]],"c":false}]},{"i":{"x":0.2,"y":1},"o":{"x":0.8,"y":0},"t":108,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.056,-49.945],[-0.056,14.056]],"c":false}]},{"t":118,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.111,14.055],[-0.056,14.056]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":14,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":80,"s":[0,0]},{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":90,"s":[100,100]},{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.8,0.8],"y":[0,0]},"t":108,"s":[100,100]},{"t":118,"s":[0,0]}],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.056,35.389],[-0.111,50.111]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":14,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0.049,42.698],"ix":2},"a":{"a":0,"k":[0.049,42.698],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":80,"s":[0,0]},{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":90,"s":[100,100]},{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.8,0.8],"y":[0,0]},"t":108,"s":[100,100]},{"t":118,"s":[0,0]}],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 2","np":3,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":80,"op":980,"st":80,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":".red400","cl":"red400","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":80,"s":[0]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":90,"s":[100]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":108,"s":[100]},{"t":118,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,62.45],[-62.45,0],[0,-62.45],[62.45,0]],"o":[[0,-62.45],[62.45,0],[0,62.45],[-62.45,0]],"v":[[-113.08,0],[0,-113.08],[113.08,0],[0,113.08]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[206,150],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333393172,0.403921598547,0.360784313725,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":80,"op":1252,"st":80,"bm":0},{"ddd":0,"ind":7,"ty":3,"nm":"Null 1","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0.333},"t":85,"s":[209.333,136.333,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":440,"s":[209.333,136.333,0],"to":[1.944,2.278,0],"ti":[3.056,-2.278,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":450,"s":[221,150,0],"to":[-3.056,2.278,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":460,"s":[191,150,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":470,"s":[221,150,0],"to":[0,0,0],"ti":[2.5,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":480,"s":[191,150,0],"to":[-2.5,0,0],"ti":[-2.5,0,0]},{"t":490,"s":[206,150,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[132,132,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 14","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":90,"ix":10},"p":{"a":0,"k":[170,170,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":0,"nm":"Fingerprint_Animation_ForConfirm_Short","parent":1,"refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":-90,"ix":10},"p":{"a":0,"k":[0,-92.333,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[30,30,100],"ix":6,"l":2}},"ao":0,"w":412,"h":300,"ip":0,"op":830,"st":-70,"bm":0}],"markers":[{"tm":255,"cm":"","dr":0},{"tm":364,"cm":"","dr":0},{"tm":482,"cm":"","dr":0},{"tm":600,"cm":"","dr":0}]}
\ No newline at end of file diff --git a/packages/SystemUI/res/raw/biometricprompt_symbol_fingerprint_to_error_portrait_topleft.json b/packages/SystemUI/res/raw/biometricprompt_symbol_fingerprint_to_error_portrait_topleft.json new file mode 100644 index 000000000000..15457c7e19c8 --- /dev/null +++ b/packages/SystemUI/res/raw/biometricprompt_symbol_fingerprint_to_error_portrait_topleft.json @@ -0,0 +1 @@ +{"v":"5.9.0","fr":60,"ip":0,"op":21,"w":340,"h":340,"nm":"biometricprompt_symbol_fingerprint_to_error_portrait_topleft","ddd":0,"assets":[{"id":"comp_0","nm":"Fingerprint_Animation_ForConfirm_Short","fr":60,"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"circle fill 5","td":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":239,"s":[0]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":249,"s":[100]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":388,"s":[100]},{"t":408,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,62.45],[-62.45,0],[0,-62.45],[62.45,0]],"o":[[0,-62.45],[62.45,0],[0,62.45],[-62.45,0]],"v":[[-113.08,0],[0,-113.08],[113.08,0],[0,113.08]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[206,150],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333393172,0.403921598547,0.360784313725,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":239,"op":1411,"st":239,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".white","cl":"white","tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-52.056,-2.445],[-17.306,32.25],[52.194,-37.194]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":14,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":239,"s":[0]},{"t":249,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":239,"op":1139,"st":239,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".green400","cl":"green400","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":239,"s":[0]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":249,"s":[100]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":388,"s":[100]},{"t":408,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,62.45],[-62.45,0],[0,-62.45],[62.45,0]],"o":[[0,-62.45],[62.45,0],[0,62.45],[-62.45,0]],"v":[[-113.08,0],[0,-113.08],[113.08,0],[0,113.08]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[206,150],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.450980392157,0.709803921569,0.470588235294,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":239,"op":1411,"st":239,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"circle fill 3","td":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":80,"s":[0]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":90,"s":[100]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":108,"s":[100]},{"t":118,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,62.45],[-62.45,0],[0,-62.45],[62.45,0]],"o":[[0,-62.45],[62.45,0],[0,62.45],[-62.45,0]],"v":[[-113.08,0],[0,-113.08],[113.08,0],[0,113.08]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[206,150],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333393172,0.403921598547,0.360784313725,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":80,"op":1252,"st":80,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".white","cl":"white","tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":80,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.111,14.055],[-0.056,14.056]],"c":false}]},{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":90,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.056,-49.945],[-0.056,14.056]],"c":false}]},{"i":{"x":0.2,"y":1},"o":{"x":0.8,"y":0},"t":108,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.056,-49.945],[-0.056,14.056]],"c":false}]},{"t":118,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.111,14.055],[-0.056,14.056]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":14,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":80,"s":[0,0]},{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":90,"s":[100,100]},{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.8,0.8],"y":[0,0]},"t":108,"s":[100,100]},{"t":118,"s":[0,0]}],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.056,35.389],[-0.111,50.111]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":14,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0.049,42.698],"ix":2},"a":{"a":0,"k":[0.049,42.698],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":80,"s":[0,0]},{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":90,"s":[100,100]},{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.8,0.8],"y":[0,0]},"t":108,"s":[100,100]},{"t":118,"s":[0,0]}],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 2","np":3,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":80,"op":980,"st":80,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":".red400","cl":"red400","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":80,"s":[0]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":90,"s":[100]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":108,"s":[100]},{"t":118,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,62.45],[-62.45,0],[0,-62.45],[62.45,0]],"o":[[0,-62.45],[62.45,0],[0,62.45],[-62.45,0]],"v":[[-113.08,0],[0,-113.08],[113.08,0],[0,113.08]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[206,150],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333393172,0.403921598547,0.360784313725,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":80,"op":1252,"st":80,"bm":0},{"ddd":0,"ind":7,"ty":3,"nm":"Null 1","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0.333},"t":85,"s":[209.333,136.333,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":440,"s":[209.333,136.333,0],"to":[1.944,2.278,0],"ti":[3.056,-2.278,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":450,"s":[221,150,0],"to":[-3.056,2.278,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":460,"s":[191,150,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":470,"s":[221,150,0],"to":[0,0,0],"ti":[2.5,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":480,"s":[191,150,0],"to":[-2.5,0,0],"ti":[-2.5,0,0]},{"t":490,"s":[206,150,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[132,132,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 14","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":-90,"ix":10},"p":{"a":0,"k":[170,170,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":0,"nm":"Fingerprint_Animation_ForConfirm_Short","parent":1,"refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":90,"ix":10},"p":{"a":0,"k":[0,-92.333,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[30,30,100],"ix":6,"l":2}},"ao":0,"w":412,"h":300,"ip":0,"op":830,"st":-70,"bm":0}],"markers":[{"tm":255,"cm":"","dr":0},{"tm":364,"cm":"","dr":0},{"tm":482,"cm":"","dr":0},{"tm":600,"cm":"","dr":0}]}
\ No newline at end of file diff --git a/packages/SystemUI/res/raw/biometricprompt_symbol_fingerprint_to_success_landscape.json b/packages/SystemUI/res/raw/biometricprompt_symbol_fingerprint_to_success_landscape.json new file mode 100644 index 000000000000..f39894b0a300 --- /dev/null +++ b/packages/SystemUI/res/raw/biometricprompt_symbol_fingerprint_to_success_landscape.json @@ -0,0 +1 @@ +{"v":"5.9.0","fr":60,"ip":0,"op":21,"w":340,"h":340,"nm":"biometricprompt_symbol_fingerprint_to_success_landscape","ddd":0,"assets":[{"id":"comp_0","nm":"Fingerprint_Animation_ForConfirm_Short","fr":60,"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"circle fill 5","td":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":239,"s":[0]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":249,"s":[100]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":388,"s":[100]},{"t":408,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,62.45],[-62.45,0],[0,-62.45],[62.45,0]],"o":[[0,-62.45],[62.45,0],[0,62.45],[-62.45,0]],"v":[[-113.08,0],[0,-113.08],[113.08,0],[0,113.08]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[206,150],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333393172,0.403921598547,0.360784313725,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":239,"op":1411,"st":239,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".white","cl":"white","tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-52.056,-2.445],[-17.306,32.25],[52.194,-37.194]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":14,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":239,"s":[0]},{"t":249,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":239,"op":1139,"st":239,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".green400","cl":"green400","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":239,"s":[0]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":249,"s":[100]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":388,"s":[100]},{"t":408,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,62.45],[-62.45,0],[0,-62.45],[62.45,0]],"o":[[0,-62.45],[62.45,0],[0,62.45],[-62.45,0]],"v":[[-113.08,0],[0,-113.08],[113.08,0],[0,113.08]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[206,150],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.450980392157,0.709803921569,0.470588235294,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":239,"op":1411,"st":239,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"circle fill 3","td":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":80,"s":[0]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":90,"s":[100]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":108,"s":[100]},{"t":118,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,62.45],[-62.45,0],[0,-62.45],[62.45,0]],"o":[[0,-62.45],[62.45,0],[0,62.45],[-62.45,0]],"v":[[-113.08,0],[0,-113.08],[113.08,0],[0,113.08]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[206,150],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333393172,0.403921598547,0.360784313725,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":80,"op":1252,"st":80,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".white","cl":"white","tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":80,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.111,14.055],[-0.056,14.056]],"c":false}]},{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":90,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.056,-49.945],[-0.056,14.056]],"c":false}]},{"i":{"x":0.2,"y":1},"o":{"x":0.8,"y":0},"t":108,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.056,-49.945],[-0.056,14.056]],"c":false}]},{"t":118,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.111,14.055],[-0.056,14.056]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":14,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":80,"s":[0,0]},{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":90,"s":[100,100]},{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.8,0.8],"y":[0,0]},"t":108,"s":[100,100]},{"t":118,"s":[0,0]}],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.056,35.389],[-0.111,50.111]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":14,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0.049,42.698],"ix":2},"a":{"a":0,"k":[0.049,42.698],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":80,"s":[0,0]},{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":90,"s":[100,100]},{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.8,0.8],"y":[0,0]},"t":108,"s":[100,100]},{"t":118,"s":[0,0]}],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 2","np":3,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":80,"op":980,"st":80,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":".red400","cl":"red400","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":80,"s":[0]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":90,"s":[100]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":108,"s":[100]},{"t":118,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,62.45],[-62.45,0],[0,-62.45],[62.45,0]],"o":[[0,-62.45],[62.45,0],[0,62.45],[-62.45,0]],"v":[[-113.08,0],[0,-113.08],[113.08,0],[0,113.08]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[206,150],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333393172,0.403921598547,0.360784313725,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":80,"op":1252,"st":80,"bm":0},{"ddd":0,"ind":7,"ty":3,"nm":"Null 1","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0.333},"t":85,"s":[209.333,136.333,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":440,"s":[209.333,136.333,0],"to":[1.944,2.278,0],"ti":[3.056,-2.278,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":450,"s":[221,150,0],"to":[-3.056,2.278,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":460,"s":[191,150,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":470,"s":[221,150,0],"to":[0,0,0],"ti":[2.5,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":480,"s":[191,150,0],"to":[-2.5,0,0],"ti":[-2.5,0,0]},{"t":490,"s":[206,150,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[132,132,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":0,"nm":"Fingerprint_Animation_ForConfirm_Short","refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[170,77.667,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[30,30,100],"ix":6,"l":2}},"ao":0,"w":412,"h":300,"ip":0,"op":661,"st":-239,"bm":0}],"markers":[{"tm":255,"cm":"","dr":0},{"tm":364,"cm":"","dr":0},{"tm":482,"cm":"","dr":0},{"tm":600,"cm":"","dr":0}]}
\ No newline at end of file diff --git a/packages/SystemUI/res/raw/biometricprompt_symbol_fingerprint_to_success_portrait_bottomright.json b/packages/SystemUI/res/raw/biometricprompt_symbol_fingerprint_to_success_portrait_bottomright.json new file mode 100644 index 000000000000..6d4f4e2e1d23 --- /dev/null +++ b/packages/SystemUI/res/raw/biometricprompt_symbol_fingerprint_to_success_portrait_bottomright.json @@ -0,0 +1 @@ +{"v":"5.9.0","fr":60,"ip":0,"op":21,"w":340,"h":340,"nm":"biometricprompt_symbol_fingerprint_to_success_portrait_bottomright","ddd":0,"assets":[{"id":"comp_0","nm":"Fingerprint_Animation_ForConfirm_Short","fr":60,"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"circle fill 5","td":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":239,"s":[0]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":249,"s":[100]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":388,"s":[100]},{"t":408,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,62.45],[-62.45,0],[0,-62.45],[62.45,0]],"o":[[0,-62.45],[62.45,0],[0,62.45],[-62.45,0]],"v":[[-113.08,0],[0,-113.08],[113.08,0],[0,113.08]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[206,150],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333393172,0.403921598547,0.360784313725,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":239,"op":1411,"st":239,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".white","cl":"white","tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-52.056,-2.445],[-17.306,32.25],[52.194,-37.194]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":14,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":239,"s":[0]},{"t":249,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":239,"op":1139,"st":239,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".green400","cl":"green400","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":239,"s":[0]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":249,"s":[100]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":388,"s":[100]},{"t":408,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,62.45],[-62.45,0],[0,-62.45],[62.45,0]],"o":[[0,-62.45],[62.45,0],[0,62.45],[-62.45,0]],"v":[[-113.08,0],[0,-113.08],[113.08,0],[0,113.08]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[206,150],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.450980392157,0.709803921569,0.470588235294,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":239,"op":1411,"st":239,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"circle fill 3","td":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":80,"s":[0]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":90,"s":[100]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":108,"s":[100]},{"t":118,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,62.45],[-62.45,0],[0,-62.45],[62.45,0]],"o":[[0,-62.45],[62.45,0],[0,62.45],[-62.45,0]],"v":[[-113.08,0],[0,-113.08],[113.08,0],[0,113.08]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[206,150],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333393172,0.403921598547,0.360784313725,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":80,"op":1252,"st":80,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".white","cl":"white","tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":80,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.111,14.055],[-0.056,14.056]],"c":false}]},{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":90,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.056,-49.945],[-0.056,14.056]],"c":false}]},{"i":{"x":0.2,"y":1},"o":{"x":0.8,"y":0},"t":108,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.056,-49.945],[-0.056,14.056]],"c":false}]},{"t":118,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.111,14.055],[-0.056,14.056]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":14,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":80,"s":[0,0]},{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":90,"s":[100,100]},{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.8,0.8],"y":[0,0]},"t":108,"s":[100,100]},{"t":118,"s":[0,0]}],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.056,35.389],[-0.111,50.111]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":14,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0.049,42.698],"ix":2},"a":{"a":0,"k":[0.049,42.698],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":80,"s":[0,0]},{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":90,"s":[100,100]},{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.8,0.8],"y":[0,0]},"t":108,"s":[100,100]},{"t":118,"s":[0,0]}],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 2","np":3,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":80,"op":980,"st":80,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":".red400","cl":"red400","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":80,"s":[0]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":90,"s":[100]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":108,"s":[100]},{"t":118,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,62.45],[-62.45,0],[0,-62.45],[62.45,0]],"o":[[0,-62.45],[62.45,0],[0,62.45],[-62.45,0]],"v":[[-113.08,0],[0,-113.08],[113.08,0],[0,113.08]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[206,150],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333393172,0.403921598547,0.360784313725,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":80,"op":1252,"st":80,"bm":0},{"ddd":0,"ind":7,"ty":3,"nm":"Null 1","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0.333},"t":85,"s":[209.333,136.333,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":440,"s":[209.333,136.333,0],"to":[1.944,2.278,0],"ti":[3.056,-2.278,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":450,"s":[221,150,0],"to":[-3.056,2.278,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":460,"s":[191,150,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":470,"s":[221,150,0],"to":[0,0,0],"ti":[2.5,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":480,"s":[191,150,0],"to":[-2.5,0,0],"ti":[-2.5,0,0]},{"t":490,"s":[206,150,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[132,132,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 15","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":90,"ix":10},"p":{"a":0,"k":[170,170,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":0,"nm":"Fingerprint_Animation_ForConfirm_Short","parent":1,"refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":-90,"ix":10},"p":{"a":0,"k":[0,-92.333,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[30,30,100],"ix":6,"l":2}},"ao":0,"w":412,"h":300,"ip":0,"op":661,"st":-239,"bm":0}],"markers":[{"tm":255,"cm":"","dr":0},{"tm":364,"cm":"","dr":0},{"tm":482,"cm":"","dr":0},{"tm":600,"cm":"","dr":0}]}
\ No newline at end of file diff --git a/packages/SystemUI/res/raw/biometricprompt_symbol_fingerprint_to_success_portrait_topleft.json b/packages/SystemUI/res/raw/biometricprompt_symbol_fingerprint_to_success_portrait_topleft.json new file mode 100644 index 000000000000..b7bb0d5cbb26 --- /dev/null +++ b/packages/SystemUI/res/raw/biometricprompt_symbol_fingerprint_to_success_portrait_topleft.json @@ -0,0 +1 @@ +{"v":"5.9.0","fr":60,"ip":0,"op":21,"w":340,"h":340,"nm":"biometricprompt_symbol_fingerprint_to_success_portrait_topleft","ddd":0,"assets":[{"id":"comp_0","nm":"Fingerprint_Animation_ForConfirm_Short","fr":60,"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"circle fill 5","td":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":239,"s":[0]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":249,"s":[100]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":388,"s":[100]},{"t":408,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,62.45],[-62.45,0],[0,-62.45],[62.45,0]],"o":[[0,-62.45],[62.45,0],[0,62.45],[-62.45,0]],"v":[[-113.08,0],[0,-113.08],[113.08,0],[0,113.08]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[206,150],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333393172,0.403921598547,0.360784313725,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":239,"op":1411,"st":239,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".white","cl":"white","tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[-52.056,-2.445],[-17.306,32.25],[52.194,-37.194]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":14,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":239,"s":[0]},{"t":249,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":239,"op":1139,"st":239,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".green400","cl":"green400","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":239,"s":[0]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":249,"s":[100]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":388,"s":[100]},{"t":408,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,62.45],[-62.45,0],[0,-62.45],[62.45,0]],"o":[[0,-62.45],[62.45,0],[0,62.45],[-62.45,0]],"v":[[-113.08,0],[0,-113.08],[113.08,0],[0,113.08]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[206,150],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.450980392157,0.709803921569,0.470588235294,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":239,"op":1411,"st":239,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"circle fill 3","td":1,"sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":80,"s":[0]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":90,"s":[100]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":108,"s":[100]},{"t":118,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,62.45],[-62.45,0],[0,-62.45],[62.45,0]],"o":[[0,-62.45],[62.45,0],[0,62.45],[-62.45,0]],"v":[[-113.08,0],[0,-113.08],[113.08,0],[0,113.08]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[206,150],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333393172,0.403921598547,0.360784313725,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":80,"op":1252,"st":80,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".white","cl":"white","tt":1,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":80,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.111,14.055],[-0.056,14.056]],"c":false}]},{"i":{"x":0.2,"y":1},"o":{"x":0.7,"y":0},"t":90,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.056,-49.945],[-0.056,14.056]],"c":false}]},{"i":{"x":0.2,"y":1},"o":{"x":0.8,"y":0},"t":108,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.056,-49.945],[-0.056,14.056]],"c":false}]},{"t":118,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.111,14.055],[-0.056,14.056]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":14,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":80,"s":[0,0]},{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":90,"s":[100,100]},{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.8,0.8],"y":[0,0]},"t":108,"s":[100,100]},{"t":118,"s":[0,0]}],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-0.056,35.389],[-0.111,50.111]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":14,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0.049,42.698],"ix":2},"a":{"a":0,"k":[0.049,42.698],"ix":1},"s":{"a":1,"k":[{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":80,"s":[0,0]},{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.7,0.7],"y":[0,0]},"t":90,"s":[100,100]},{"i":{"x":[0.2,0.2],"y":[1,1]},"o":{"x":[0.8,0.8],"y":[0,0]},"t":108,"s":[100,100]},{"t":118,"s":[0,0]}],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Shape 2","np":3,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":80,"op":980,"st":80,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":".red400","cl":"red400","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":80,"s":[0]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":90,"s":[100]},{"i":{"x":[0.2],"y":[1]},"o":{"x":[0.7],"y":[0]},"t":108,"s":[100]},{"t":118,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[206,150,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,62.45],[-62.45,0],[0,-62.45],[62.45,0]],"o":[[0,-62.45],[62.45,0],[0,62.45],[-62.45,0]],"v":[[-113.08,0],[0,-113.08],[113.08,0],[0,113.08]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tr","p":{"a":0,"k":[206,150],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 4","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.933333393172,0.403921598547,0.360784313725,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":80,"op":1252,"st":80,"bm":0},{"ddd":0,"ind":7,"ty":3,"nm":"Null 1","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0.333},"t":85,"s":[209.333,136.333,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":440,"s":[209.333,136.333,0],"to":[1.944,2.278,0],"ti":[3.056,-2.278,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":450,"s":[221,150,0],"to":[-3.056,2.278,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":460,"s":[191,150,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":470,"s":[221,150,0],"to":[0,0,0],"ti":[2.5,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":480,"s":[191,150,0],"to":[-2.5,0,0],"ti":[-2.5,0,0]},{"t":490,"s":[206,150,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[132,132,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":3,"nm":"Null 15","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":-90,"ix":10},"p":{"a":0,"k":[170,170,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":0,"nm":"Fingerprint_Animation_ForConfirm_Short","parent":1,"refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":90,"ix":10},"p":{"a":0,"k":[0,-92.333,0],"ix":2,"l":2},"a":{"a":0,"k":[206,150,0],"ix":1,"l":2},"s":{"a":0,"k":[30,30,100],"ix":6,"l":2}},"ao":0,"w":412,"h":300,"ip":0,"op":661,"st":-239,"bm":0}],"markers":[{"tm":255,"cm":"","dr":0},{"tm":364,"cm":"","dr":0},{"tm":482,"cm":"","dr":0},{"tm":600,"cm":"","dr":0}]}
\ No newline at end of file diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml index 0626058d4ae0..577154763e5b 100644 --- a/packages/SystemUI/res/values-af/strings.xml +++ b/packages/SystemUI/res/values-af/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Kan nie gesig herken nie. Gebruik eerder vingerafdruk."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"Kan nie gesig herken nie"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Gebruik eerder vingerafdruk"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth gekoppel."</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Batterypersentasie is onbekend."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Gekoppel aan <xliff:g id="BLUETOOTH">%s</xliff:g>."</string> @@ -600,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"Aan"</string> <string name="switch_bar_off" msgid="5669805115416379556">"Af"</string> <string name="tile_unavailable" msgid="3095879009136616920">"Onbeskikbaar"</string> - <string name="tile_disabled" msgid="373212051546573069">"Gedeaktiveer"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"kom meer te wete"</string> <string name="nav_bar" msgid="4642708685386136807">"Navigasiebalk"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"Uitleg"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Ekstra linksknoppie-tipe"</string> @@ -673,8 +671,8 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Sommige kenmerke is beperk terwyl foon afkoel.\nTik vir meer inligting"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"Jou foon sal outomaties probeer om af te koel. Jy kan steeds jou foon gebruik, maar dit sal dalk stadiger wees.\n\nJou foon sal normaalweg werk nadat dit afgekoel het."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Sien versorgingstappe"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Trek laaier uit"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"Kan nie hierdie toestel laai nie. Trek die kragprop uit, en wees versigtig, want die kabel kan warm wees."</string> + <string name="high_temp_alarm_title" msgid="8654754369605452169">"Prop jou toestel uit"</string> + <string name="high_temp_alarm_notify_message" msgid="3917622943609118956">"Jou toestel word tans warm naby die laaipoort. Prop dit uit as dit aan ’n laaier of USB-bykomstigheid gekoppel is. Wees versigtig, aangesien die kabel dalk ook warm is."</string> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"Sien versorgingstappe"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Links-kortpad"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"Regs-kortpad"</string> diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml index 651769f0480c..b4eda5de30ed 100644 --- a/packages/SystemUI/res/values-am/strings.xml +++ b/packages/SystemUI/res/values-am/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"መልክን መለየት አልተቻለም። በምትኩ የጣት አሻራ ይጠቀሙ።"</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"መልክን መለየት አልተቻለም"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"በምትኩ የጣት አሻራን ይጠቀሙ"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"ብሉቱዝ ተያይዟል።"</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"የባትሪ መቶኛ አይታወቅም።"</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"ከ<xliff:g id="BLUETOOTH">%s</xliff:g> ጋር ተገናኝቷል።"</string> @@ -423,10 +421,8 @@ <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"የሥዕል መግለጫ ጽሑፎች ንብርብር"</string> <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"አንቃ"</string> <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"አሰናክል"</string> - <!-- no translation found for sound_settings (8874581353127418308) --> - <skip /> - <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) --> - <skip /> + <string name="sound_settings" msgid="8874581353127418308">"ድምጽ እና ንዝረት"</string> + <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"ቅንብሮች"</string> <string name="screen_pinning_title" msgid="9058007390337841305">"መተግበሪያ ተሰክቷል"</string> <string name="screen_pinning_description" msgid="8699395373875667743">"ይሄ እስኪነቅሉት ድረስ በእይታ ውስጥ ያስቀምጠዋል። ለመንቀል ተመለስ እና አጠቃላይ ዕይታ የሚለውን ይጫኑ እና ይያዙ።"</string> <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"ይሄ እስኪነቅሉት ድረስ በእይታ ውስጥ ያስቀምጠዋል። ለመንቀል ተመለስ እና መነሻ የሚለውን ይንኩ እና ይያዙ።"</string> @@ -602,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"በርቷል"</string> <string name="switch_bar_off" msgid="5669805115416379556">"ጠፍቷል"</string> <string name="tile_unavailable" msgid="3095879009136616920">"አይገኝም"</string> - <string name="tile_disabled" msgid="373212051546573069">"ተሰናክሏል"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"የበለጠ ለመረዳት"</string> <string name="nav_bar" msgid="4642708685386136807">"የአሰሳ አሞሌ"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"አቀማመጥ"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"ተጨማሪ የግራ አዝራር ዓይነት"</string> @@ -675,8 +671,10 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"አንዳንድ ባሕሪያት ስልኩ እየቀዘቀዘ እያለ ውስን ይሆናሉ።\nለተጨማሪ መረጃ መታ ያድርጉ"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"የእርስዎ ስልክ በራስ-ሰር ለመቀዝቀዝ ይሞክራል። አሁንም ስልክዎን መጠቀም ይችላሉ፣ ነገር ግን ሊንቀራፈፍ ይችላል።\n\nአንዴ ስልክዎ ከቀዘቀዘ በኋላ በመደበኝነት ያሄዳል።"</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"የእንክብካቤ ደረጃዎችን ይመልከቱ"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"ኃይል መሙያን ይንቀሉ"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"የዚህን መሣሪያ ባትሪ መሙላት ላይ ችግር አለ። የኃይል አስማሚውን ይንቀሉትና ሊግል ስለሚችል ገመዱን ይጠብቁት።"</string> + <!-- no translation found for high_temp_alarm_title (8654754369605452169) --> + <skip /> + <!-- no translation found for high_temp_alarm_notify_message (3917622943609118956) --> + <skip /> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"የእንክብካቤ ደረጃዎችን ይመልከቱ"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"የግራ አቋራጭ"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"የቀኝ አቋራጭ"</string> diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml index 73a9e9bec006..38ce1f92fae0 100644 --- a/packages/SystemUI/res/values-ar/strings.xml +++ b/packages/SystemUI/res/values-ar/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"يتعذّر التعرّف على الوجه. استخدِم بصمة الإصبع بدلاً من ذلك."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"يتعذّر التعرّف على الوجه."</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"يمكنك استخدام بصمة إصبعك."</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"تم توصيل البلوتوث."</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"نسبة شحن البطارية غير معروفة."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"متصل بـ <xliff:g id="BLUETOOTH">%s</xliff:g>."</string> @@ -423,10 +421,8 @@ <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"تراكب الشرح"</string> <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"تفعيل"</string> <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"إيقاف"</string> - <!-- no translation found for sound_settings (8874581353127418308) --> - <skip /> - <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) --> - <skip /> + <string name="sound_settings" msgid="8874581353127418308">"الصوت والاهتزاز"</string> + <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"الإعدادات"</string> <string name="screen_pinning_title" msgid="9058007390337841305">"تم تثبيت الشاشة على التطبيق"</string> <string name="screen_pinning_description" msgid="8699395373875667743">"يؤدي هذا إلى استمرار عرض الشاشة المُختارة إلى أن تتم إزالة تثبيتها. المس مع الاستمرار الزرين \"رجوع\" و\"نظرة عامة\" لإزالة التثبيت."</string> <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"يؤدي هذا إلى استمرار عرض الشاشة المُختارة إلى أن تتم إزالة تثبيتها. المس مع الاستمرار الزرين \"رجوع\" و\"الشاشة الرئيسية\" لإزالة التثبيت."</string> @@ -602,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"مفعّل"</string> <string name="switch_bar_off" msgid="5669805115416379556">"متوقف"</string> <string name="tile_unavailable" msgid="3095879009136616920">"غير متوفّر"</string> - <string name="tile_disabled" msgid="373212051546573069">"غير مفعّل"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"مزيد من المعلومات"</string> <string name="nav_bar" msgid="4642708685386136807">"شريط التنقل"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"التنسيق"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"نوع زر اليسار الإضافي"</string> @@ -675,8 +671,10 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"يتم تقييد عمل بعض الميزات إلى أن تنخفض درجة حرارة الهاتف.\nانقر للحصول على مزيد من المعلومات."</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"سيحاول الهاتف تخفيض درجة حرارته تلقائيًا. سيظل بإمكانك استخدام هاتفك، ولكن قد يعمل بشكل أبطأ.\n\nبعد أن تنخفض درجة حرارة الهاتف، سيستعيد سرعته المعتادة."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"الاطّلاع على خطوات العناية"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"فصل الشاحن"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"هناك مشكلة في شحن هذا الجهاز. يُرجى فصل محوِّل الطاقة بحرص لأن الكابل قد يكون ساخنًا."</string> + <!-- no translation found for high_temp_alarm_title (8654754369605452169) --> + <skip /> + <!-- no translation found for high_temp_alarm_notify_message (3917622943609118956) --> + <skip /> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"الاطّلاع على خطوات العناية"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"اختصار اليسار"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"اختصار اليمين"</string> diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml index 8fe8377b043b..c01d357e3b78 100644 --- a/packages/SystemUI/res/values-as/strings.xml +++ b/packages/SystemUI/res/values-as/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"মুখাৱয়ব চিনিব নোৱাৰি। ফিংগাৰপ্ৰিণ্ট ব্যৱহাৰ কৰক।"</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"মুখাৱয়ব চিনিব নোৱাৰি"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"ইয়াৰ সলনি ফিংগাৰপ্ৰিণ্ট ব্যৱহাৰ কৰক"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"ব্লুটুথ সংযোগ হ’ল।"</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"বেটাৰীৰ চাৰ্জৰ শতাংশ অজ্ঞাত।"</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g>ৰ লগত সংযোগ কৰা হ’ল।"</string> @@ -423,10 +421,8 @@ <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"কেপশ্বন অভাৰলে’"</string> <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"সক্ষম কৰক"</string> <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"অক্ষম কৰক"</string> - <!-- no translation found for sound_settings (8874581353127418308) --> - <skip /> - <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) --> - <skip /> + <string name="sound_settings" msgid="8874581353127418308">"ধ্বনি আৰু কম্পন"</string> + <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"ছেটিং"</string> <string name="screen_pinning_title" msgid="9058007390337841305">"এপ্টো পিন কৰা আছে"</string> <string name="screen_pinning_description" msgid="8699395373875667743">"এই কাৰ্যই আপুনি আনপিন নকৰালৈকে ইয়াক দেখা পোৱা অৱস্থাত ৰাখে। আনপিন কৰিবলৈ \'পিছলৈ যাওক\' আৰু \'অৱলোকন\'-ত স্পৰ্শ কৰি থাকক।"</string> <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"এই কাৰ্যই আপুনি আনপিন নকৰালৈকে ইয়াক দেখা পোৱা অৱস্থাত ৰাখে। আনপিন কৰিবলৈ পিছলৈ যাওক আৰু হ\'মত স্পৰ্শ কৰি সেঁচি ধৰক।"</string> @@ -602,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"অন"</string> <string name="switch_bar_off" msgid="5669805115416379556">"অফ"</string> <string name="tile_unavailable" msgid="3095879009136616920">"উপলব্ধ নহয়"</string> - <string name="tile_disabled" msgid="373212051546573069">"অক্ষম কৰা আছে"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"অধিক জানক"</string> <string name="nav_bar" msgid="4642708685386136807">"নেভিগেশ্বন দণ্ড"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"লেআউট"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"বাওঁ বুটামৰ অতিৰিক্ত প্ৰকাৰ"</string> @@ -675,8 +671,10 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"ফ’নটো ঠাণ্ডা হৈ থকাৰ সময়ত কিছুমান সুবিধা উপলব্ধ নহয়।\nঅধিক তথ্যৰ বাবে টিপক"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"আপোনাৰ ফ\'নটোৱে নিজে নিজে ঠাণ্ডা হ\'বলৈ স্বয়ংক্ৰিয়ভাৱে চেষ্টা কৰিব। আপুনি ফ\'নটো ব্যৱহাৰ কৰি থাকিব পাৰে কিন্তু ই লাহে লাহে চলিব পাৰে।\n\nফ\'নটো সম্পূৰ্ণভাৱে ঠাণ্ডা হোৱাৰ পিছত ই আগৰ নিচিনাকৈয়েই চলিব।"</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"যত্ন লোৱাৰ পদক্ষেপসমূহ চাওক"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"চ্চার্জাৰ আনপ্লাগ কৰক"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"এই ডিভাইচটো চ্চার্জ কৰোঁতে কিবা সমস্যা হৈছে। পাৱাৰ এডাপ্টাৰটো আনপ্লাগ কৰক, কেব’লডাল গৰম হ’ব পাৰে গতিকে সাবধান হ’ব।"</string> + <!-- no translation found for high_temp_alarm_title (8654754369605452169) --> + <skip /> + <!-- no translation found for high_temp_alarm_notify_message (3917622943609118956) --> + <skip /> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"যত্ন লোৱাৰ পদক্ষেপসমূহ চাওক"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"বাওঁ শ্বৰ্টকাট"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"সোঁ শ্বৰ্টকাট"</string> diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml index 15aff513461e..5020b483d4fe 100644 --- a/packages/SystemUI/res/values-az/strings.xml +++ b/packages/SystemUI/res/values-az/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Tanımaq olmur. Barmaq izini işlədin."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"Üzü tanımaq olmur"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Barmaq izi istifadə edin"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth qoşulub."</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Batareyanın faizi naməlumdur."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> üzərindən qoşuldu."</string> @@ -423,10 +421,8 @@ <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Subtitr başlığı"</string> <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"aktiv edin"</string> <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"deaktiv edin"</string> - <!-- no translation found for sound_settings (8874581353127418308) --> - <skip /> - <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) --> - <skip /> + <string name="sound_settings" msgid="8874581353127418308">"Səs və vibrasiya"</string> + <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Ayarlar"</string> <string name="screen_pinning_title" msgid="9058007390337841305">"Tətbiq bərkidilib"</string> <string name="screen_pinning_description" msgid="8699395373875667743">"Sancaq götürülənə qədər bu görünəcək. Sancağı götürmək üçün Geri və İcmal düymələrinə basıb saxlayın."</string> <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"\"Geri\" və \"Əsas ekran\" düymələrinin davamlı basılması ilə çıxarılana qədər tətbiq göz önündə qalır."</string> @@ -602,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"Aktiv"</string> <string name="switch_bar_off" msgid="5669805115416379556">"Deaktiv"</string> <string name="tile_unavailable" msgid="3095879009136616920">"Əlçatan deyil"</string> - <string name="tile_disabled" msgid="373212051546573069">"Deaktiv edilib"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"ətraflı məlumat"</string> <string name="nav_bar" msgid="4642708685386136807">"Naviqasiya paneli"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"Tərtibat"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Əlavə sol düymə növü"</string> @@ -675,8 +671,10 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Telefon soyuyana kimi bəzi funksiyalar məhdudlaşdırılır.\nƏtraflı məlumat üçün toxunun"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"Telefonunuz avtomatik olaraq soyumağa başlayacaq. Telefon istifadəsinə davam edə bilərsiniz, lakin sürəti yavaşlaya bilər.\n\nTelefonunuz soyuduqdan sonra normal işləyəcək."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Ehtiyat tədbiri mərhələlərinə baxın"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Adapteri cərəyandan ayırın"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"Bu cihazın batareya yığmasında problem var. Adapteri cərəyandan ayırın. Ehtiyatlı olun, kabel isti ola bilər."</string> + <!-- no translation found for high_temp_alarm_title (8654754369605452169) --> + <skip /> + <!-- no translation found for high_temp_alarm_notify_message (3917622943609118956) --> + <skip /> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"Ehtiyat tədbiri mərhələlərinə baxın"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Sol qısayol"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"Sağ qısayol"</string> diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml index fad5f18e9bf3..41633f7b9da3 100644 --- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml +++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Lice nije prepoznato. Koristite otisak prsta."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"Lice nije prepoznato"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Koristite otisak prsta"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth je priključen."</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Procenat napunjenosti baterije nije poznat."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Povezani ste sa <xliff:g id="BLUETOOTH">%s</xliff:g>."</string> @@ -423,10 +421,8 @@ <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Preklapanje titlova"</string> <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"omogućite"</string> <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"onemogućite"</string> - <!-- no translation found for sound_settings (8874581353127418308) --> - <skip /> - <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) --> - <skip /> + <string name="sound_settings" msgid="8874581353127418308">"Zvuk i vibriranje"</string> + <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Podešavanja"</string> <string name="screen_pinning_title" msgid="9058007390337841305">"Aplikacija je zakačena"</string> <string name="screen_pinning_description" msgid="8699395373875667743">"Na ovaj način se ovo stalno prikazuje dok ga ne otkačite. Dodirnite i zadržite Nazad i Pregled da biste ga otkačili."</string> <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Na ovaj način se ovo stalno prikazuje dok ga ne otkačite. Dodirnite i zadržite Nazad i Početna da biste ga otkačili."</string> @@ -602,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"Uključeno"</string> <string name="switch_bar_off" msgid="5669805115416379556">"Isključeno"</string> <string name="tile_unavailable" msgid="3095879009136616920">"Nedostupno"</string> - <string name="tile_disabled" msgid="373212051546573069">"Onemogućeno"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"saznajte više"</string> <string name="nav_bar" msgid="4642708685386136807">"Traka za navigaciju"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"Raspored"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Dodatni tip levog dugmeta"</string> @@ -675,8 +671,8 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Neke funkcije su ograničene dok se telefon ne ohladi.\nDodirnite za više informacija"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"Telefon će automatski pokušati da se ohladi. I dalje ćete moći da koristite telefon, ali će sporije reagovati.\n\nKada se telefon ohladi, normalno će raditi."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Pogledajte upozorenja"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Isključite punjač iz struje"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"Došlo je do problema sa punjenjem ovog uređaja. Isključite adapter iz napajanja i budite pažljivi jer kabl može da bude topao."</string> + <string name="high_temp_alarm_title" msgid="8654754369605452169">"Isključite uređaj"</string> + <string name="high_temp_alarm_notify_message" msgid="3917622943609118956">"Uređaj se zagreva u blizini porta za punjenje. Ako je povezan sa punjačem ili USB opremom, isključite je i budite pažljivi jer i kabl može da bude vruć."</string> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"Pogledajte upozorenja"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Leva prečica"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"Desna prečica"</string> diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml index bcf4e05eccf0..988864c12812 100644 --- a/packages/SystemUI/res/values-be/strings.xml +++ b/packages/SystemUI/res/values-be/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Твар не распазнаны. Скарыстайце адбітак пальца."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"Твар не распазнаны"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Скарыстайце адбітак пальца"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth-сувязь."</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Працэнт зараду акумулятара невядомы."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Падлучаны да <xliff:g id="BLUETOOTH">%s</xliff:g>."</string> @@ -423,10 +421,8 @@ <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Накладанне субцітраў"</string> <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"уключыць"</string> <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"адключыць"</string> - <!-- no translation found for sound_settings (8874581353127418308) --> - <skip /> - <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) --> - <skip /> + <string name="sound_settings" msgid="8874581353127418308">"Гук і вібрацыя"</string> + <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Налады"</string> <string name="screen_pinning_title" msgid="9058007390337841305">"Праграма замацавана"</string> <string name="screen_pinning_description" msgid="8699395373875667743">"Будзе паказвацца, пакуль не адмацуеце. Каб адмацаваць, краніце і ўтрымлівайце кнопкі \"Назад\" і \"Агляд\"."</string> <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Будзе паказвацца, пакуль не адмацуеце. Каб адмацаваць, націсніце і ўтрымлівайце кнопкі \"Назад\" і \"Галоўны экран\"."</string> @@ -602,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"Уключана"</string> <string name="switch_bar_off" msgid="5669805115416379556">"Выключана"</string> <string name="tile_unavailable" msgid="3095879009136616920">"Недаступна"</string> - <string name="tile_disabled" msgid="373212051546573069">"Выключана"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"даведацца больш"</string> <string name="nav_bar" msgid="4642708685386136807">"Панэль навігацыі"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"Раскладка"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Дадатковы тып кнопкі \"ўлева\""</string> @@ -675,8 +671,10 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Некаторыя функцыі абмежаваны, пакуль тэлефон не астыне.\nНацісніце, каб даведацца больш"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"Ваш тэлефон аўтаматычна паспрабуе астыць. Вы можаце па-ранейшаму карыстацца сваім тэлефонам, але ён можа працаваць больш павольна.\n\nПасля таго як ваш тэлефон астыне, ён будзе працаваць у звычайным рэжыме."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Глядзець паэтапную дапамогу"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Адключыце зарадную прыладу"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"Узнікла праблема з зарадкай гэтай прылады. Адключыце адаптар сілкавання і праверце, ці не нагрэўся кабель."</string> + <!-- no translation found for high_temp_alarm_title (8654754369605452169) --> + <skip /> + <!-- no translation found for high_temp_alarm_notify_message (3917622943609118956) --> + <skip /> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"Глядзець паэтапную дапамогу"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Ярлык \"улева\""</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"Ярлык \"управа\""</string> diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml index 8515d925218e..9e7ae18946f5 100644 --- a/packages/SystemUI/res/values-bg/strings.xml +++ b/packages/SystemUI/res/values-bg/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Лицето не е разпознато. Използвайте отпечатък."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"Лицето не е разпознато"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Използвайте отпечатък"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth е включен."</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Процентът на батерията е неизвестен."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Има връзка с <xliff:g id="BLUETOOTH">%s</xliff:g>."</string> @@ -423,10 +421,8 @@ <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Наслагване на надписите"</string> <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"активиране"</string> <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"деактивиране"</string> - <!-- no translation found for sound_settings (8874581353127418308) --> - <skip /> - <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) --> - <skip /> + <string name="sound_settings" msgid="8874581353127418308">"Звук и вибриране"</string> + <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Настройки"</string> <string name="screen_pinning_title" msgid="9058007390337841305">"Приложението е фиксирано"</string> <string name="screen_pinning_description" msgid="8699395373875667743">"Екранът ще се показва, докато не го освободите с докосване и задържане на бутона за връщане назад и този за общ преглед."</string> <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Екранът ще се показва, докато не го освободите с докосване и задържане на бутона за връщане назад и „Начало“."</string> @@ -602,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"Вкл."</string> <string name="switch_bar_off" msgid="5669805115416379556">"Изкл."</string> <string name="tile_unavailable" msgid="3095879009136616920">"Не е налице"</string> - <string name="tile_disabled" msgid="373212051546573069">"Деактивирано"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"научете повече"</string> <string name="nav_bar" msgid="4642708685386136807">"Лента за навигация"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"Оформление"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Тип на допълнителния ляв бутон"</string> @@ -675,8 +671,10 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Някои функции са ограничени, докато телефонът се охлажда.\nДокоснете за още информация"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"Телефонът ви автоматично ще направи опит за охлаждане. Пак можете да го използвате, но той може да работи по-бавно.\n\nСлед като се охлади, ще работи нормално."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Вижте стъпките, които да предприемете"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Изключете зарядното устройство"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"При зареждането на това устройство възникна проблем. Изключете захранващия адаптер и внимавайте, тъй като кабелът може да е топъл."</string> + <!-- no translation found for high_temp_alarm_title (8654754369605452169) --> + <skip /> + <!-- no translation found for high_temp_alarm_notify_message (3917622943609118956) --> + <skip /> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"Вижте стъпките, които да предприемете"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Ляв пряк път"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"Десен пряк път"</string> diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml index 9e257cd5cf31..0f7ddfc09dad 100644 --- a/packages/SystemUI/res/values-bn/strings.xml +++ b/packages/SystemUI/res/values-bn/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"মুখ শনাক্ত করতে পারছি না। পরিবর্তে আঙ্গুলের ছাপ ব্যবহার করুন।"</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"ফেস শনাক্ত করা যায়নি"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"পরিবর্তে ফিঙ্গারপ্রিন্ট ব্যবহার করুন"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"ব্লুটুথ সংযুক্ত হয়েছে৷"</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"ব্যাটারি কত শতাংশ আছে তা জানা যায়নি।"</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g>এ সংযুক্ত হয়ে আছে।"</string> @@ -600,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"চালু আছে"</string> <string name="switch_bar_off" msgid="5669805115416379556">"বন্ধ আছে"</string> <string name="tile_unavailable" msgid="3095879009136616920">"উপলভ্য নয়"</string> - <string name="tile_disabled" msgid="373212051546573069">"বন্ধ করা আছে"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"আরও জানুন"</string> <string name="nav_bar" msgid="4642708685386136807">"নেভিগেশন বার"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"লেআউট"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"অতিরিক্ত বাঁদিকের বোতামের ধরণ"</string> @@ -673,8 +671,8 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"ফোন ঠাণ্ডা না হওয়া পর্যন্ত কিছু ফিচার কাজ করে না।\nআরও তথ্যের জন্য ট্যাপ করুন"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"আপনার ফোনটি নিজে থেকেই ঠাণ্ডা হওয়ার চেষ্টা করবে৷ আপনি তবুও আপনার ফোন ব্যবহার করতে পারেন, কিন্তু এটি একটু ধীরে চলতে পারে৷\n\nআপনার ফোনটি পুরোপুরি ঠাণ্ডা হয়ে গেলে এটি স্বাভাবিকভাবে চলবে৷"</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"ডিভাইস রক্ষণাবেক্ষণের ধাপগুলি দেখুন"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"চার্জার আনপ্লাগ করুন"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"এই ডিভাইস চার্জ করার সময় সমস্যা হয়েছে। চার্জিং কেবলটি হয়ত গরম হয়ে গেছে, পাওয়ার অ্যাডাপ্টারটি আনপ্লাগ করুন।"</string> + <string name="high_temp_alarm_title" msgid="8654754369605452169">"আপনার ডিভাইস আনপ্লাগ করা"</string> + <string name="high_temp_alarm_notify_message" msgid="3917622943609118956">"চার্জিং পোর্টের কাছে আপনার ডিভাইসটি গরম হচ্ছে। এটি চার্জার বা ইউএসবি অ্যাক্সেসরির সাথে কানেক্ট করা থাকলে, আনপ্লাগ করুন এবং সতর্ক থাকুন কারণ কেবেলটিও গরম হতে পারে।"</string> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"কী করতে হবে ধাপে ধাপে দেখুন"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"বাঁদিকের শর্টকাট"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"ডানদিকের শর্টকাট"</string> diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml index d3c8ef6f03b8..19bbca63a8c8 100644 --- a/packages/SystemUI/res/values-bs/strings.xml +++ b/packages/SystemUI/res/values-bs/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Nije moguće prepoznati lice. Koristite otisak prsta."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"Nije moguće prepoznati lice"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Koristite otisak prsta"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth je povezan."</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Postotak napunjenosti baterije nije poznat"</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Povezan na <xliff:g id="BLUETOOTH">%s</xliff:g>."</string> @@ -423,10 +421,8 @@ <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Preklapanje titlova"</string> <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"omogući"</string> <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"onemogući"</string> - <!-- no translation found for sound_settings (8874581353127418308) --> - <skip /> - <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) --> - <skip /> + <string name="sound_settings" msgid="8874581353127418308">"Zvuk i vibracija"</string> + <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Postavke"</string> <string name="screen_pinning_title" msgid="9058007390337841305">"Aplikacija je zakačena"</string> <string name="screen_pinning_description" msgid="8699395373875667743">"Ekran ostaje prikazan ovako dok ga ne otkačite. Da ga otkačite, dodirnite i držite dugme Nazad."</string> <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Na ovaj način ekran ostaje prikazan dok ga ne otkačite. Da otkačite ekran, dodirnite i držite dugme Nazad i Početna."</string> @@ -602,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"Uključeno"</string> <string name="switch_bar_off" msgid="5669805115416379556">"Isključeno"</string> <string name="tile_unavailable" msgid="3095879009136616920">"Nedostupno"</string> - <string name="tile_disabled" msgid="373212051546573069">"Onemogućeno"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"saznajte više"</string> <string name="nav_bar" msgid="4642708685386136807">"Navigaciona traka"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"Raspored"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Vrsta dodatnog dugmeta lijevo"</string> @@ -675,8 +671,8 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Neke funkcije su ograničene dok se telefon hladi.\nDodirnite za više informacija"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"Vaš telefon će se automatski pokušati ohladiti. I dalje možete koristi telefon, ali će možda raditi sporije.\n\nNakon što se ohladi, telefon će normalno raditi."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Pogledajte korake za zaštitu"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Isključite punjač"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"Došlo je do problema prilikom punjenja ovog uređaja. Pažljivo isključite adapter za napajanje jer je moguće da je kabl vruć."</string> + <string name="high_temp_alarm_title" msgid="8654754369605452169">"Iskopčajte uređaj"</string> + <string name="high_temp_alarm_notify_message" msgid="3917622943609118956">"Uređaj se zagrijava u blizini priključka za punjenje. Ako je povezan s punjačem ili USB dodatkom, iskopčajte ga i vodite računa jer i kabl može biti topao."</string> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"Prikaz koraka za zaštitu"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Prečica lijevo"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"Prečica desno"</string> diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml index 20e25749c350..32159398f62a 100644 --- a/packages/SystemUI/res/values-ca/strings.xml +++ b/packages/SystemUI/res/values-ca/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"No podem detectar la cara. Usa l\'empremta digital."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"No es reconeix la cara"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Utilitza l\'empremta digital"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth connectat."</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Es desconeix el percentatge de bateria."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"S\'ha connectat a <xliff:g id="BLUETOOTH">%s</xliff:g>."</string> @@ -423,10 +421,8 @@ <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Superposició de subtítols"</string> <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"activar"</string> <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"desactivar"</string> - <!-- no translation found for sound_settings (8874581353127418308) --> - <skip /> - <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) --> - <skip /> + <string name="sound_settings" msgid="8874581353127418308">"So i vibració"</string> + <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Configuració"</string> <string name="screen_pinning_title" msgid="9058007390337841305">"L\'aplicació està fixada"</string> <string name="screen_pinning_description" msgid="8699395373875667743">"Aquest element es continuarà mostrant fins que deixis de fixar-lo. Per fer-ho, toca i mantén premudes els botons Enrere i Aplicacions recents."</string> <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Aquest element es continuarà mostrant fins que deixis de fixar-lo. Per fer-ho, mantén premuts els botons Enrere i Inici."</string> @@ -602,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"Activat"</string> <string name="switch_bar_off" msgid="5669805115416379556">"Desactivat"</string> <string name="tile_unavailable" msgid="3095879009136616920">"No disponible"</string> - <string name="tile_disabled" msgid="373212051546573069">"Desactivat"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"més informació"</string> <string name="nav_bar" msgid="4642708685386136807">"Barra de navegació"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"Disposició"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Tipus de botó addicional de l\'esquerra"</string> @@ -675,8 +671,10 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Algunes funcions estan limitades mentre el telèfon es refreda.\nToca per obtenir més informació"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"El telèfon provarà de refredar-se automàticament. Podràs continuar utilitzant-lo, però és possible que funcioni més lentament.\n\nUn cop s\'hagi refredat, funcionarà amb normalitat."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Mostra els passos de manteniment"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Desconnecta el carregador"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"No es pot carregar el dispositiu. Desconnecta l\'adaptador de corrent amb compte, ja que el cable podria estar calent."</string> + <!-- no translation found for high_temp_alarm_title (8654754369605452169) --> + <skip /> + <!-- no translation found for high_temp_alarm_notify_message (3917622943609118956) --> + <skip /> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"Mostra els pasos de manteniment"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Drecera de l\'esquerra"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"Drecera de la dreta"</string> diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml index f7e116f808fa..c07b99bebd03 100644 --- a/packages/SystemUI/res/values-cs/strings.xml +++ b/packages/SystemUI/res/values-cs/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Obličej se nepodařilo rozpoznat. Použijte místo něj otisk prstu."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"Obličej nelze rozpoznat"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Použijte otisk prstu"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Rozhraní Bluetooth je připojeno."</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Procento baterie není známé."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Připojeno k zařízení <xliff:g id="BLUETOOTH">%s</xliff:g>."</string> @@ -423,10 +421,8 @@ <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Překryvná vrstva titulků"</string> <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"aktivovat"</string> <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"deaktivovat"</string> - <!-- no translation found for sound_settings (8874581353127418308) --> - <skip /> - <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) --> - <skip /> + <string name="sound_settings" msgid="8874581353127418308">"Zvuk a vibrace"</string> + <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Nastavení"</string> <string name="screen_pinning_title" msgid="9058007390337841305">"Aplikace je připnutá"</string> <string name="screen_pinning_description" msgid="8699395373875667743">"Obsah bude připnut v zobrazení, dokud jej neuvolníte. Uvolníte jej stisknutím a podržením tlačítek Zpět a Přehled."</string> <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Obsah bude připnut v zobrazení, dokud ho neuvolníte. Uvolníte ho podržením tlačítek Zpět a Plocha."</string> @@ -602,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"Zapnuto"</string> <string name="switch_bar_off" msgid="5669805115416379556">"Vypnuto"</string> <string name="tile_unavailable" msgid="3095879009136616920">"Nedostupné"</string> - <string name="tile_disabled" msgid="373212051546573069">"Vypnuto"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"další informace"</string> <string name="nav_bar" msgid="4642708685386136807">"Navigační panel"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"Rozvržení"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Zvláštní typ tlačítka vlevo"</string> @@ -675,8 +671,10 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Některé funkce jsou při chladnutí telefonu omezeny.\nKlepnutím zobrazíte další informace"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"Telefon se automaticky pokusí vychladnout. Lze jej nadále používat, ale může být pomalejší.\n\nAž telefon vychladne, bude fungovat normálně."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Zobrazit pokyny, co dělat"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Odpojte nabíječku"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"Při nabíjení zařízení došlo k problému. Odpojte napájecí adaptér (dávejte pozor, kabel může být horký)."</string> + <!-- no translation found for high_temp_alarm_title (8654754369605452169) --> + <skip /> + <!-- no translation found for high_temp_alarm_notify_message (3917622943609118956) --> + <skip /> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"Zobrazit pokyny, co dělat"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Zkratka vlevo"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"Zkratka vpravo"</string> diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml index 23e00fc656e3..3cb0bc1cad4e 100644 --- a/packages/SystemUI/res/values-da/strings.xml +++ b/packages/SystemUI/res/values-da/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Ansigtet kan ikke genkendes. Brug fingeraftryk i stedet."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"Ansigt kan ikke genkendes"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Brug fingeraftryk i stedet"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth tilsluttet."</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Batteriniveauet er ukendt."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Tilsluttet <xliff:g id="BLUETOOTH">%s</xliff:g>."</string> @@ -423,10 +421,8 @@ <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Overlejrede undertekster"</string> <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"aktivér"</string> <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"deaktiver"</string> - <!-- no translation found for sound_settings (8874581353127418308) --> - <skip /> - <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) --> - <skip /> + <string name="sound_settings" msgid="8874581353127418308">"Lyd og vibration"</string> + <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Indstillinger"</string> <string name="screen_pinning_title" msgid="9058007390337841305">"Appen er fastgjort"</string> <string name="screen_pinning_description" msgid="8699395373875667743">"Dette fastholder skærmen i visningen, indtil du frigør den. Tryk på Tilbage og Overblik, og hold fingeren nede for at frigøre skærmen."</string> <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Dette fastholder skærmen i visningen, indtil du frigør den. Hold Tilbage og Startskærm nede for at frigøre skærmen."</string> @@ -602,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"Til"</string> <string name="switch_bar_off" msgid="5669805115416379556">"Fra"</string> <string name="tile_unavailable" msgid="3095879009136616920">"Ikke tilgængelig"</string> - <string name="tile_disabled" msgid="373212051546573069">"Deaktiveret"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"få flere oplysninger"</string> <string name="nav_bar" msgid="4642708685386136807">"Navigationslinje"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"Layout"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Ekstra venstre knaptype"</string> @@ -675,8 +671,10 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Nogle funktioner er begrænsede, mens telefonen køler ned.\nTryk for at få flere oplysninger"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"Din telefon forsøger automatisk at køle ned. Du kan stadig bruge telefonen, men den kører muligvis langsommere.\n\nNår din telefon er kølet ned, fungerer den normalt igen."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Se håndteringsvejledning"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Frakobl opladeren"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"Der er et problem med opladning af denne enhed. Frakobl strømadapteren, og vær forsigtig, da kablet kan være varmt."</string> + <!-- no translation found for high_temp_alarm_title (8654754369605452169) --> + <skip /> + <!-- no translation found for high_temp_alarm_notify_message (3917622943609118956) --> + <skip /> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"Se vejledningen i pleje"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Venstre genvej"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"Højre genvej"</string> diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml index 08fa40e3e1e0..fe3582aed2ae 100644 --- a/packages/SystemUI/res/values-de/strings.xml +++ b/packages/SystemUI/res/values-de/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Gesicht wurde nicht erkannt. Verwende stattdessen den Fingerabdruck."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"Gesicht nicht erkannt"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Fingerabdruck verwenden"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Mit Bluetooth verbunden"</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Akkustand unbekannt."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Mit <xliff:g id="BLUETOOTH">%s</xliff:g> verbunden"</string> @@ -600,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"An"</string> <string name="switch_bar_off" msgid="5669805115416379556">"Aus"</string> <string name="tile_unavailable" msgid="3095879009136616920">"Nicht verfügbar"</string> - <string name="tile_disabled" msgid="373212051546573069">"Deaktiviert"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"Weitere Informationen"</string> <string name="nav_bar" msgid="4642708685386136807">"Navigationsleiste"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"Layout"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Zusätzlicher linker Schaltflächentyp"</string> @@ -673,8 +671,8 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Einige Funktionen sind während der Abkühlphase des Smartphones eingeschränkt.\nFür mehr Informationen tippen."</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"Dein Smartphone kühlt sich automatisch ab. Du kannst dein Smartphone weiterhin nutzen, aber es reagiert möglicherweise langsamer.\n\nSobald dein Smartphone abgekühlt ist, funktioniert es wieder normal."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Schritte zur Abkühlung des Geräts ansehen"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Ladegerät vom Stromnetz trennen"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"Beim Laden dieses Geräts ist ein Problem aufgetreten. Trenne das Netzteil vom Stromnetz. Sei dabei vorsichtig, denn das Netzteil oder das Kabel könnte heiß sein."</string> + <string name="high_temp_alarm_title" msgid="8654754369605452169">"Gerät vom Stromnetz trennen"</string> + <string name="high_temp_alarm_notify_message" msgid="3917622943609118956">"Dein Gerät erwärmt sich am Ladeanschluss. Trenne das Gerät vom Stromnetz, wenn es an ein Ladegerät oder USB-Zubehör angeschlossen ist. Sei vorsichtig, denn das Kabel könnte ebenfalls heiß sein."</string> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"Schritte zur Fehlerbehebung ansehen"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Linke Verknüpfung"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"Rechte Verknüpfung"</string> diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml index 723748852ef4..028f681184cf 100644 --- a/packages/SystemUI/res/values-el/strings.xml +++ b/packages/SystemUI/res/values-el/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Το πρόσωπο δεν αναγνωρίζεται. Χρησιμ. δακτ. αποτ."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"Αδύνατη η αναγν. προσώπου"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Χρησιμ. δακτυλ. αποτύπ."</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Το Bluetooth είναι συνδεδεμένο."</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Άγνωστο ποσοστό μπαταρίας."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Συνδέθηκε στο <xliff:g id="BLUETOOTH">%s</xliff:g>."</string> @@ -600,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"Ενεργό"</string> <string name="switch_bar_off" msgid="5669805115416379556">"Απενεργοποίηση"</string> <string name="tile_unavailable" msgid="3095879009136616920">"Μη διαθέσιμο"</string> - <string name="tile_disabled" msgid="373212051546573069">"Ανενεργό"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"μάθετε περισσότερα"</string> <string name="nav_bar" msgid="4642708685386136807">"Γραμμή πλοήγησης"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"Διάταξη"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Επιπλέον τύπος αριστερού κουμπιού"</string> @@ -673,8 +671,8 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Ορισμένες λειτουργίες περιορίζονται κατά τη μείωση της θερμοκρασίας.\nΠατήστε για περισσότερες πληροφορίες."</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"Το τηλέφωνό σας θα προσπαθήσει να μειώσει αυτόματα τη θερμοκρασία. Μπορείτε να εξακολουθήσετε να το χρησιμοποιείτε, αλλά είναι πιθανό να λειτουργεί πιο αργά.\n\nΜόλις μειωθεί η θερμοκρασία του τηλεφώνου σας, θα λειτουργεί ξανά κανονικά."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Δείτε βήματα αντιμετώπισης."</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Αποσυνδέστε τον φορτιστή"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"Υπάρχει κάποιο πρόβλημα με τη φόρτιση αυτής της συσκευής. Αποσυνδέστε τον μετασχηματιστή με προσοχή, λαμβάνοντας υπόψη ότι το καλώδιο μπορεί να είναι ζεστό."</string> + <string name="high_temp_alarm_title" msgid="8654754369605452169">"Αποσυνδέστε τη συσκευή"</string> + <string name="high_temp_alarm_notify_message" msgid="3917622943609118956">"Η συσκευή έχει αρχίσει να ζεσταίνεται κοντά στη θύρα φόρτισης. Αν είναι συνδεδεμένη σε φορτιστή ή αξεσουάρ USB, αποσυνδέστε την και προσέξτε γιατί και το καλώδιο μπορεί να έχει ζεσταθεί."</string> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"Δείτε βήματα αντιμετώπισης"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Αριστερή συντόμευση"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"Δεξιά συντόμευση"</string> diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml index 47bf1b40387d..a067d96cc294 100644 --- a/packages/SystemUI/res/values-en-rAU/strings.xml +++ b/packages/SystemUI/res/values-en-rAU/strings.xml @@ -421,10 +421,8 @@ <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Captions overlay"</string> <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"enable"</string> <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"disable"</string> - <!-- no translation found for sound_settings (8874581353127418308) --> - <skip /> - <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) --> - <skip /> + <string name="sound_settings" msgid="8874581353127418308">"Sound and vibration"</string> + <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Settings"</string> <string name="screen_pinning_title" msgid="9058007390337841305">"App is pinned"</string> <string name="screen_pinning_description" msgid="8699395373875667743">"This keeps it in view until you unpin. Touch & hold Back and Overview to unpin."</string> <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"This keeps it in view until you unpin. Touch & hold Back and Home to unpin."</string> @@ -600,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"On"</string> <string name="switch_bar_off" msgid="5669805115416379556">"Off"</string> <string name="tile_unavailable" msgid="3095879009136616920">"Unavailable"</string> - <string name="tile_disabled" msgid="373212051546573069">"Disabled"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"learn more"</string> <string name="nav_bar" msgid="4642708685386136807">"Navigation bar"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"Layout"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Extra left button type"</string> @@ -673,8 +671,8 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Some features are limited while phone cools down.\nTap for more info"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"Your phone will automatically try to cool down. You can still use your phone, but it may run more slowly.\n\nOnce your phone has cooled down, it will run normally."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"See care steps"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Unplug charger"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"There’s an issue charging this device. Unplug the power adaptor, and take care as the cable may be warm."</string> + <string name="high_temp_alarm_title" msgid="8654754369605452169">"Unplug your device"</string> + <string name="high_temp_alarm_notify_message" msgid="3917622943609118956">"Your device is getting warm near the charging port. If it’s connected to a charger or USB accessory, unplug it and take care as the cable may also be warm."</string> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"See care steps"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Left shortcut"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"Right shortcut"</string> diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml index 867deb4ce799..30183eb8af5b 100644 --- a/packages/SystemUI/res/values-en-rCA/strings.xml +++ b/packages/SystemUI/res/values-en-rCA/strings.xml @@ -421,10 +421,8 @@ <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Captions overlay"</string> <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"enable"</string> <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"disable"</string> - <!-- no translation found for sound_settings (8874581353127418308) --> - <skip /> - <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) --> - <skip /> + <string name="sound_settings" msgid="8874581353127418308">"Sound and vibration"</string> + <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Settings"</string> <string name="screen_pinning_title" msgid="9058007390337841305">"App is pinned"</string> <string name="screen_pinning_description" msgid="8699395373875667743">"This keeps it in view until you unpin. Touch & hold Back and Overview to unpin."</string> <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"This keeps it in view until you unpin. Touch & hold Back and Home to unpin."</string> @@ -600,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"On"</string> <string name="switch_bar_off" msgid="5669805115416379556">"Off"</string> <string name="tile_unavailable" msgid="3095879009136616920">"Unavailable"</string> - <string name="tile_disabled" msgid="373212051546573069">"Disabled"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"learn more"</string> <string name="nav_bar" msgid="4642708685386136807">"Navigation bar"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"Layout"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Extra left button type"</string> @@ -673,8 +671,8 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Some features are limited while phone cools down.\nTap for more info"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"Your phone will automatically try to cool down. You can still use your phone, but it may run more slowly.\n\nOnce your phone has cooled down, it will run normally."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"See care steps"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Unplug charger"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"There’s an issue charging this device. Unplug the power adaptor, and take care as the cable may be warm."</string> + <string name="high_temp_alarm_title" msgid="8654754369605452169">"Unplug your device"</string> + <string name="high_temp_alarm_notify_message" msgid="3917622943609118956">"Your device is getting warm near the charging port. If it’s connected to a charger or USB accessory, unplug it and take care as the cable may also be warm."</string> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"See care steps"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Left shortcut"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"Right shortcut"</string> diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml index 47bf1b40387d..a067d96cc294 100644 --- a/packages/SystemUI/res/values-en-rGB/strings.xml +++ b/packages/SystemUI/res/values-en-rGB/strings.xml @@ -421,10 +421,8 @@ <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Captions overlay"</string> <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"enable"</string> <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"disable"</string> - <!-- no translation found for sound_settings (8874581353127418308) --> - <skip /> - <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) --> - <skip /> + <string name="sound_settings" msgid="8874581353127418308">"Sound and vibration"</string> + <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Settings"</string> <string name="screen_pinning_title" msgid="9058007390337841305">"App is pinned"</string> <string name="screen_pinning_description" msgid="8699395373875667743">"This keeps it in view until you unpin. Touch & hold Back and Overview to unpin."</string> <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"This keeps it in view until you unpin. Touch & hold Back and Home to unpin."</string> @@ -600,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"On"</string> <string name="switch_bar_off" msgid="5669805115416379556">"Off"</string> <string name="tile_unavailable" msgid="3095879009136616920">"Unavailable"</string> - <string name="tile_disabled" msgid="373212051546573069">"Disabled"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"learn more"</string> <string name="nav_bar" msgid="4642708685386136807">"Navigation bar"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"Layout"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Extra left button type"</string> @@ -673,8 +671,8 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Some features are limited while phone cools down.\nTap for more info"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"Your phone will automatically try to cool down. You can still use your phone, but it may run more slowly.\n\nOnce your phone has cooled down, it will run normally."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"See care steps"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Unplug charger"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"There’s an issue charging this device. Unplug the power adaptor, and take care as the cable may be warm."</string> + <string name="high_temp_alarm_title" msgid="8654754369605452169">"Unplug your device"</string> + <string name="high_temp_alarm_notify_message" msgid="3917622943609118956">"Your device is getting warm near the charging port. If it’s connected to a charger or USB accessory, unplug it and take care as the cable may also be warm."</string> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"See care steps"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Left shortcut"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"Right shortcut"</string> diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml index 47bf1b40387d..a067d96cc294 100644 --- a/packages/SystemUI/res/values-en-rIN/strings.xml +++ b/packages/SystemUI/res/values-en-rIN/strings.xml @@ -421,10 +421,8 @@ <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Captions overlay"</string> <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"enable"</string> <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"disable"</string> - <!-- no translation found for sound_settings (8874581353127418308) --> - <skip /> - <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) --> - <skip /> + <string name="sound_settings" msgid="8874581353127418308">"Sound and vibration"</string> + <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Settings"</string> <string name="screen_pinning_title" msgid="9058007390337841305">"App is pinned"</string> <string name="screen_pinning_description" msgid="8699395373875667743">"This keeps it in view until you unpin. Touch & hold Back and Overview to unpin."</string> <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"This keeps it in view until you unpin. Touch & hold Back and Home to unpin."</string> @@ -600,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"On"</string> <string name="switch_bar_off" msgid="5669805115416379556">"Off"</string> <string name="tile_unavailable" msgid="3095879009136616920">"Unavailable"</string> - <string name="tile_disabled" msgid="373212051546573069">"Disabled"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"learn more"</string> <string name="nav_bar" msgid="4642708685386136807">"Navigation bar"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"Layout"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Extra left button type"</string> @@ -673,8 +671,8 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Some features are limited while phone cools down.\nTap for more info"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"Your phone will automatically try to cool down. You can still use your phone, but it may run more slowly.\n\nOnce your phone has cooled down, it will run normally."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"See care steps"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Unplug charger"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"There’s an issue charging this device. Unplug the power adaptor, and take care as the cable may be warm."</string> + <string name="high_temp_alarm_title" msgid="8654754369605452169">"Unplug your device"</string> + <string name="high_temp_alarm_notify_message" msgid="3917622943609118956">"Your device is getting warm near the charging port. If it’s connected to a charger or USB accessory, unplug it and take care as the cable may also be warm."</string> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"See care steps"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Left shortcut"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"Right shortcut"</string> diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml index f903c969f755..c09d197d25f3 100644 --- a/packages/SystemUI/res/values-en-rXC/strings.xml +++ b/packages/SystemUI/res/values-en-rXC/strings.xml @@ -598,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"On"</string> <string name="switch_bar_off" msgid="5669805115416379556">"Off"</string> <string name="tile_unavailable" msgid="3095879009136616920">"Unavailable"</string> - <string name="tile_disabled" msgid="373212051546573069">"Disabled"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"learn more"</string> <string name="nav_bar" msgid="4642708685386136807">"Navigation bar"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"Layout"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Extra left button type"</string> @@ -671,8 +671,8 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Some features limited while phone cools down.\nTap for more info"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"Your phone will automatically try to cool down. You can still use your phone, but it may run slower.\n\nOnce your phone has cooled down, it will run normally."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"See care steps"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Unplug charger"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"There’s an issue charging this device. Unplug the power adapter, and take care as the cable may be warm."</string> + <string name="high_temp_alarm_title" msgid="8654754369605452169">"Unplug your device"</string> + <string name="high_temp_alarm_notify_message" msgid="3917622943609118956">"Your device is getting warm near the charging port. If it’s connected to a charger or USB accessory, unplug it, and take care as the cable may also be warm."</string> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"See care steps"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Left shortcut"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"Right shortcut"</string> diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml index ce489d269a6b..f4f4999ddf18 100644 --- a/packages/SystemUI/res/values-es-rUS/strings.xml +++ b/packages/SystemUI/res/values-es-rUS/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"No se reconoce el rostro. Usa la huella dactilar."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"No se reconoce el rostro"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Usa la huella dactilar"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth conectado"</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Se desconoce el porcentaje de la batería."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Conectado a <xliff:g id="BLUETOOTH">%s</xliff:g>"</string> @@ -206,7 +204,7 @@ <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"Sensores desactivados sí"</string> <string name="accessibility_clear_all" msgid="970525598287244592">"Eliminar todas las notificaciones"</string> <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"<xliff:g id="NUMBER">%s</xliff:g> más"</string> - <string name="notification_group_overflow_description" msgid="7176322877233433278">"{count,plural, =1{# notificación más en el grupo.}other{# notificaciones más en el grupo.}}"</string> + <string name="notification_group_overflow_description" msgid="7176322877233433278">"{count,plural, =1{# notificación más en el grupo.}many{# notificaciones más en el grupo.}other{# notificaciones más en el grupo.}}"</string> <string name="accessibility_rotation_lock_on_landscape" msgid="936972553861524360">"La pantalla está bloqueada en modo horizontal."</string> <string name="accessibility_rotation_lock_on_portrait" msgid="2356633398683813837">"La pantalla está bloqueada en modo vertical."</string> <string name="dessert_case" msgid="9104973640704357717">"Caja para postres"</string> @@ -254,7 +252,7 @@ <string name="quick_settings_hotspot_label" msgid="1199196300038363424">"Hotspot"</string> <string name="quick_settings_hotspot_secondary_label_transient" msgid="7585604088079160564">"Activando…"</string> <string name="quick_settings_hotspot_secondary_label_data_saver_enabled" msgid="1280433136266439372">"Ahorro de datos act."</string> - <string name="quick_settings_hotspot_secondary_label_num_devices" msgid="7536823087501239457">"{count,plural, =1{# dispositivo}other{# dispositivos}}"</string> + <string name="quick_settings_hotspot_secondary_label_num_devices" msgid="7536823087501239457">"{count,plural, =1{# dispositivo}many{# dispositivos}other{# dispositivos}}"</string> <string name="quick_settings_flashlight_label" msgid="4904634272006284185">"Linterna"</string> <string name="quick_settings_flashlight_camera_in_use" msgid="4820591564526512571">"Cámara en uso"</string> <string name="quick_settings_cellular_detail_title" msgid="792977203299358893">"Datos móviles"</string> @@ -355,7 +353,7 @@ <string name="guest_notification_session_active" msgid="5567273684713471450">"Estás en el modo de invitado"</string> <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Si agregas un usuario nuevo, se desactivará el modo de invitado y se borrarán todas las apps y los datos de la sesión de invitado actual."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Alcanzaste el límite de usuarios"</string> - <string name="user_limit_reached_message" msgid="1070703858915935796">"{count,plural, =1{Solo se puede crear un usuario.}other{Puedes agregar hasta # usuarios.}}"</string> + <string name="user_limit_reached_message" msgid="1070703858915935796">"{count,plural, =1{Solo se puede crear un usuario.}many{Puedes agregar hasta # usuarios.}other{Puedes agregar hasta # usuarios.}}"</string> <string name="user_remove_user_title" msgid="9124124694835811874">"¿Confirmas que quieres quitar el usuario?"</string> <string name="user_remove_user_message" msgid="6702834122128031833">"Se borrarán todas las aplicaciones y los datos de este usuario."</string> <string name="user_remove_user_remove" msgid="8387386066949061256">"Quitar"</string> @@ -543,8 +541,8 @@ <string name="notification_menu_snooze_action" msgid="5415729610393475019">"Recuérdame"</string> <string name="snooze_undo" msgid="2738844148845992103">"Deshacer"</string> <string name="snoozed_for_time" msgid="7586689374860469469">"Posponer <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> - <string name="snoozeHourOptions" msgid="2332819756222425558">"{count,plural, =1{# hora}=2{# horas}other{# horas}}"</string> - <string name="snoozeMinuteOptions" msgid="2222082405822030979">"{count,plural, =1{# minuto}other{# minutos}}"</string> + <string name="snoozeHourOptions" msgid="2332819756222425558">"{count,plural, =1{# hora}=2{# horas}many{# horas}other{# horas}}"</string> + <string name="snoozeMinuteOptions" msgid="2222082405822030979">"{count,plural, =1{# minuto}many{# minutos}other{# minutos}}"</string> <string name="battery_detail_switch_title" msgid="6940976502957380405">"Ahorro de batería"</string> <string name="keyboard_key_button_template" msgid="8005673627272051429">"Botón <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="3734400625170020657">"Inicio"</string> @@ -600,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"Activado"</string> <string name="switch_bar_off" msgid="5669805115416379556">"Desactivado"</string> <string name="tile_unavailable" msgid="3095879009136616920">"No disponible"</string> - <string name="tile_disabled" msgid="373212051546573069">"Inhabilitada"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"más información"</string> <string name="nav_bar" msgid="4642708685386136807">"Barra de navegación"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"Diseño"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Tipo de botón izquierdo adicional"</string> @@ -673,8 +671,8 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Algunas funciones se limitan durante el enfriamiento del teléfono.\nPresiona para obtener más información"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"Tu teléfono intentará enfriarse automáticamente. Podrás usarlo, pero es posible que funcione más lento.\n\nUna vez que se haya enfriado, volverá a funcionar correctamente."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Ver pasos de mantenimiento"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Desconectar cargador"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"No se puede cargar el dispositivo. Desconecta el adaptador de la corriente con cuidado, ya que el cable podría estar caliente."</string> + <string name="high_temp_alarm_title" msgid="8654754369605452169">"Desenchufa el dispositivo"</string> + <string name="high_temp_alarm_notify_message" msgid="3917622943609118956">"El puerto de carga del dispositivo se está calentando. Si está conectado a un cargador o accesorio USB, desenchúfalo con cuidado, ya que el cable también puede estar caliente."</string> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"Ver pasos de mantenimiento"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Acceso directo izquierdo"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"Acceso directo derecho"</string> @@ -768,7 +766,7 @@ <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"activar o desactivar"</string> <string name="quick_controls_title" msgid="6839108006171302273">"Controles de dispositivos"</string> <string name="controls_providers_title" msgid="6879775889857085056">"Elige la app para agregar los controles"</string> - <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Se agregó # control.}other{Se agregaron # controles.}}"</string> + <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{Se agregó # control.}many{Se agregaron # controles.}other{Se agregaron # controles.}}"</string> <string name="controls_removed" msgid="3731789252222856959">"Quitados"</string> <string name="accessibility_control_favorite" msgid="8694362691985545985">"Está en favoritos"</string> <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Está en favoritos en la posición <xliff:g id="NUMBER">%d</xliff:g>"</string> @@ -925,7 +923,7 @@ <string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Agregar tarjeta"</string> <string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"No agregar tarjeta"</string> <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Seleccionar usuario"</string> - <string name="fgs_manager_footer_label" msgid="8276763570622288231">"{count,plural, =1{# app está activa}other{# apps están activas}}"</string> + <string name="fgs_manager_footer_label" msgid="8276763570622288231">"{count,plural, =1{# app está activa}many{# apps están activas}other{# apps están activas}}"</string> <string name="fgs_dot_content_description" msgid="2865071539464777240">"Nueva información"</string> <string name="fgs_manager_dialog_title" msgid="5879184257257718677">"Apps activas"</string> <string name="fgs_manager_dialog_message" msgid="2670045017200730076">"Estas apps están activas y en ejecución, incluso mientras no las usas. Esto mejora su funcionalidad, pero también afecta la duración de batería."</string> @@ -955,7 +953,7 @@ <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"La cámara está desactivada"</string> <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"El micrófono está desactivado"</string> <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"La cámara y el micrófono están apagados"</string> - <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notificación}other{# notificaciones}}"</string> + <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notificación}many{# notificaciones}other{# notificaciones}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Transmitiendo"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"¿Quieres dejar de transmitir <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml index df7c083ed86e..1d73bd7a57de 100644 --- a/packages/SystemUI/res/values-es/strings.xml +++ b/packages/SystemUI/res/values-es/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"No se reconoce la cara. Usa la huella digital."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"No se reconoce la cara"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Usa la huella digital"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth conectado"</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Porcentaje de batería desconocido."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Conectado a <xliff:g id="BLUETOOTH">%s</xliff:g>."</string> @@ -206,7 +204,7 @@ <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"Sensores desactivados"</string> <string name="accessibility_clear_all" msgid="970525598287244592">"Borrar todas las notificaciones"</string> <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"<xliff:g id="NUMBER">%s</xliff:g> más"</string> - <string name="notification_group_overflow_description" msgid="7176322877233433278">"{count,plural, =1{# notificación más en el grupo.}other{# notificaciones más en el grupo.}}"</string> + <string name="notification_group_overflow_description" msgid="7176322877233433278">"{count,plural, =1{# notificación más en el grupo.}many{# notificaciones más en el grupo.}other{# notificaciones más en el grupo.}}"</string> <string name="accessibility_rotation_lock_on_landscape" msgid="936972553861524360">"La pantalla está bloqueada en modo horizontal."</string> <string name="accessibility_rotation_lock_on_portrait" msgid="2356633398683813837">"La pantalla está bloqueada en modo vertical."</string> <string name="dessert_case" msgid="9104973640704357717">"Caja para postres"</string> @@ -254,7 +252,7 @@ <string name="quick_settings_hotspot_label" msgid="1199196300038363424">"Compartir Internet"</string> <string name="quick_settings_hotspot_secondary_label_transient" msgid="7585604088079160564">"Activando…"</string> <string name="quick_settings_hotspot_secondary_label_data_saver_enabled" msgid="1280433136266439372">"Ahorro de datos activado"</string> - <string name="quick_settings_hotspot_secondary_label_num_devices" msgid="7536823087501239457">"{count,plural, =1{# dispositivo}other{# dispositivos}}"</string> + <string name="quick_settings_hotspot_secondary_label_num_devices" msgid="7536823087501239457">"{count,plural, =1{# dispositivo}many{# dispositivos}other{# dispositivos}}"</string> <string name="quick_settings_flashlight_label" msgid="4904634272006284185">"Linterna"</string> <string name="quick_settings_flashlight_camera_in_use" msgid="4820591564526512571">"Cámara en uso"</string> <string name="quick_settings_cellular_detail_title" msgid="792977203299358893">"Datos móviles"</string> @@ -355,7 +353,7 @@ <string name="guest_notification_session_active" msgid="5567273684713471450">"Estás en modo Invitado"</string> <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Si añades un nuevo usuario, saldrás del modo Invitado y se eliminarán todas las aplicaciones y datos de la sesión de invitado actual."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Has alcanzado el límite de usuarios"</string> - <string name="user_limit_reached_message" msgid="1070703858915935796">"{count,plural, =1{Solo se puede crear un usuario.}other{Puedes añadir # usuarios como máximo.}}"</string> + <string name="user_limit_reached_message" msgid="1070703858915935796">"{count,plural, =1{Solo se puede crear un usuario.}many{Puedes añadir # usuarios como máximo.}other{Puedes añadir # usuarios como máximo.}}"</string> <string name="user_remove_user_title" msgid="9124124694835811874">"¿Quitar usuario?"</string> <string name="user_remove_user_message" msgid="6702834122128031833">"Se eliminarán todas las aplicaciones y datos de este usuario."</string> <string name="user_remove_user_remove" msgid="8387386066949061256">"Quitar"</string> @@ -423,10 +421,8 @@ <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Superposición de subtítulos"</string> <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"activar"</string> <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"desactivar"</string> - <!-- no translation found for sound_settings (8874581353127418308) --> - <skip /> - <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) --> - <skip /> + <string name="sound_settings" msgid="8874581353127418308">"Sonido y vibración"</string> + <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Ajustes"</string> <string name="screen_pinning_title" msgid="9058007390337841305">"Aplicación fijada"</string> <string name="screen_pinning_description" msgid="8699395373875667743">"La aplicación se mantendrá visible hasta que dejes de fijarla. Para dejar de fijarla, mantén pulsados los botones Atrás y Aplicaciones recientes."</string> <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"La aplicación se mantendrá visible hasta que dejes de fijarla. Para dejar de fijarla, mantén pulsados los botones Atrás e Inicio."</string> @@ -545,8 +541,8 @@ <string name="notification_menu_snooze_action" msgid="5415729610393475019">"Recordar"</string> <string name="snooze_undo" msgid="2738844148845992103">"Deshacer"</string> <string name="snoozed_for_time" msgid="7586689374860469469">"Volverá a mostrarse en <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> - <string name="snoozeHourOptions" msgid="2332819756222425558">"{count,plural, =1{# hora}=2{# horas}other{# horas}}"</string> - <string name="snoozeMinuteOptions" msgid="2222082405822030979">"{count,plural, =1{# minuto}other{# minutos}}"</string> + <string name="snoozeHourOptions" msgid="2332819756222425558">"{count,plural, =1{# hora}=2{# horas}many{# horas}other{# horas}}"</string> + <string name="snoozeMinuteOptions" msgid="2222082405822030979">"{count,plural, =1{# minuto}many{# minutos}other{# minutos}}"</string> <string name="battery_detail_switch_title" msgid="6940976502957380405">"Ahorro de batería"</string> <string name="keyboard_key_button_template" msgid="8005673627272051429">"Botón <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="3734400625170020657">"Inicio"</string> @@ -602,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"Activado"</string> <string name="switch_bar_off" msgid="5669805115416379556">"Desactivado"</string> <string name="tile_unavailable" msgid="3095879009136616920">"No disponible"</string> - <string name="tile_disabled" msgid="373212051546573069">"Inhabilitado"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"más información"</string> <string name="nav_bar" msgid="4642708685386136807">"Barra de navegación"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"Diseño"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Tipo de botón a la izquierda extra"</string> @@ -675,8 +671,10 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Se han limitado algunas funciones mientras el teléfono se enfría.\nToca para ver más información"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"El teléfono intentará enfriarse. Puedes seguir utilizándolo, pero es posible que funcione con mayor lentitud.\n\nUna vez que se haya enfriado, funcionará con normalidad."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Ver pasos de mantenimiento"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Desconecta el cargador"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"No se puede cargar el dispositivo. Desconecta el adaptador de corriente con cuidado, ya que el cable puede estar caliente."</string> + <!-- no translation found for high_temp_alarm_title (8654754369605452169) --> + <skip /> + <!-- no translation found for high_temp_alarm_notify_message (3917622943609118956) --> + <skip /> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"Ver pasos de mantenimiento"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Acceso directo a la izquierda"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"Acceso directo a la derecha"</string> @@ -770,7 +768,7 @@ <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"activar/desactivar"</string> <string name="quick_controls_title" msgid="6839108006171302273">"Control de dispositivos"</string> <string name="controls_providers_title" msgid="6879775889857085056">"Elige una aplicación para añadir controles"</string> - <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# control añadido.}other{# controles añadidos.}}"</string> + <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# control añadido.}many{# controles añadidos.}other{# controles añadidos.}}"</string> <string name="controls_removed" msgid="3731789252222856959">"Quitado"</string> <string name="accessibility_control_favorite" msgid="8694362691985545985">"Añadido a favoritos"</string> <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Añadido a favoritos (posición <xliff:g id="NUMBER">%d</xliff:g>)"</string> @@ -927,7 +925,7 @@ <string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Añadir recuadro"</string> <string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"No añadir recuadro"</string> <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Selecciona un usuario"</string> - <string name="fgs_manager_footer_label" msgid="8276763570622288231">"{count,plural, =1{# aplicación activa}other{# aplicaciones activas}}"</string> + <string name="fgs_manager_footer_label" msgid="8276763570622288231">"{count,plural, =1{# aplicación activa}many{# aplicaciones activas}other{# aplicaciones activas}}"</string> <string name="fgs_dot_content_description" msgid="2865071539464777240">"Información nueva"</string> <string name="fgs_manager_dialog_title" msgid="5879184257257718677">"Aplicaciones activas"</string> <string name="fgs_manager_dialog_message" msgid="2670045017200730076">"Estas aplicaciones están activas y en funcionamiento, incluso aunque no las estés usando. Esto mejora su funcionalidad, pero también puede afectar a la duración de la batería."</string> @@ -957,7 +955,7 @@ <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"La cámara está desactivada"</string> <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"El micrófono está desactivado"</string> <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"La cámara y el micrófono están desactivados"</string> - <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notificación}other{# notificaciones}}"</string> + <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notificación}many{# notificaciones}other{# notificaciones}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Emitiendo"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"¿Dejar de emitir <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml index d85c81876140..94f4fa6e9739 100644 --- a/packages/SystemUI/res/values-et/strings.xml +++ b/packages/SystemUI/res/values-et/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Nägu ei õnnestu tuvastada. Kasutage sõrmejälge."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"Nägu ei õnnestu tuvastada"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Kasutage sõrmejälge"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth on ühendatud."</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Aku laetuse protsent on teadmata."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Ühendatud: <xliff:g id="BLUETOOTH">%s</xliff:g>."</string> @@ -423,10 +421,8 @@ <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Subtiitrite ülekate"</string> <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"luba"</string> <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"keela"</string> - <!-- no translation found for sound_settings (8874581353127418308) --> - <skip /> - <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) --> - <skip /> + <string name="sound_settings" msgid="8874581353127418308">"Heli ja vibreerimine"</string> + <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Seaded"</string> <string name="screen_pinning_title" msgid="9058007390337841305">"Rakendus on kinnitatud"</string> <string name="screen_pinning_description" msgid="8699395373875667743">"See hoitakse kuval, kuni selle vabastate. Vabastamiseks puudutage pikalt nuppe Tagasi ja Ülevaade."</string> <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"See hoitakse kuval, kuni selle vabastate. Vabastamiseks puudutage pikalt nuppe Tagasi ja Avakuva."</string> @@ -602,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"Sees"</string> <string name="switch_bar_off" msgid="5669805115416379556">"Väljas"</string> <string name="tile_unavailable" msgid="3095879009136616920">"Pole saadaval"</string> - <string name="tile_disabled" msgid="373212051546573069">"Keelatud"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"lisateave"</string> <string name="nav_bar" msgid="4642708685386136807">"Navigeerimisriba"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"Paigutus"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Täiendava vasaku nupu tüüp"</string> @@ -675,8 +671,10 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Mõned funktsioonid on piiratud, kuni telefon jahtub.\nPuudutage lisateabe saamiseks."</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"Teie telefon proovib automaatselt maha jahtuda. Saate telefoni ikka kasutada, kuid see võib olla aeglasem.\n\nKui telefon on jahtunud, töötab see tavapäraselt."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Vaadake hooldusjuhiseid"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Eemaldage laadija vooluvõrgust"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"Selle seadme laadimisega on probleem. Eemaldage toiteadapter ja olge ettevaatlik, sest kaabel võib olla soe."</string> + <!-- no translation found for high_temp_alarm_title (8654754369605452169) --> + <skip /> + <!-- no translation found for high_temp_alarm_notify_message (3917622943609118956) --> + <skip /> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"Vaadake hooldusjuhiseid"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Vasak otsetee"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"Parem otsetee"</string> diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml index a36f923beb57..9bc00514b05b 100644 --- a/packages/SystemUI/res/values-eu/strings.xml +++ b/packages/SystemUI/res/values-eu/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Ezin da hauteman aurpegia. Erabili hatz-marka."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"Ezin da ezagutu aurpegia"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Erabili hatz-marka"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth-a konektatuta."</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Bateriaren ehunekoa ezezaguna da."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> gailura konektatuta."</string> @@ -423,10 +421,8 @@ <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Azpititulu gainjarriak"</string> <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"gaitu"</string> <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"desgaitu"</string> - <!-- no translation found for sound_settings (8874581353127418308) --> - <skip /> - <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) --> - <skip /> + <string name="sound_settings" msgid="8874581353127418308">"Audioa eta dardara"</string> + <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Ezarpenak"</string> <string name="screen_pinning_title" msgid="9058007390337841305">"Aplikazioa ainguratuta dago"</string> <string name="screen_pinning_description" msgid="8699395373875667743">"Horrela, ikusgai egongo da aingura kendu arte. Aingura kentzeko, eduki sakatuta \"Atzera\" eta \"Ikuspegi orokorra\" botoiak."</string> <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Horrela, ikusgai egongo da aingura kendu arte. Aingura kentzeko, eduki sakatuta Atzera eta Hasiera botoiak."</string> @@ -602,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"Aktibatuta"</string> <string name="switch_bar_off" msgid="5669805115416379556">"Desaktibatuta"</string> <string name="tile_unavailable" msgid="3095879009136616920">"Ez dago erabilgarri"</string> - <string name="tile_disabled" msgid="373212051546573069">"Desgaituta"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"lortu informazio gehiago"</string> <string name="nav_bar" msgid="4642708685386136807">"Nabigazio-barra"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"Diseinua"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Ezkerreko botoi gehigarriaren mota"</string> @@ -675,8 +671,8 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Eginbide batzuk ezingo dira erabili telefonoa hoztu arte.\nInformazio gehiago lortzeko, sakatu hau."</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"Telefonoa automatikoki saiatuko da hozten. Hoztu bitartean, telefonoa erabiltzen jarrai dezakezu, baina mantsoago funtziona lezake.\n\nTelefonoaren tenperatura jaitsi bezain laster, ohi bezala funtzionatzen jarraituko du."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Ikusi zaintzeko urratsak"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Deskonektatu kargagailua"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"Arazo bat izan da gailua kargatzean. Deskonektatu egokigailua eta kontuz ibili, kablea bero egon baitaiteke."</string> + <string name="high_temp_alarm_title" msgid="8654754369605452169">"Deskonektatu gailua"</string> + <string name="high_temp_alarm_notify_message" msgid="3917622943609118956">"Gailua berotzen ari da kargatzeko atakaren inguruan. Kargagailu edo USB bidezko osagarri batera konektatuta badago, deskonekta ezazu kontuz, kablea ere beroa egongo baita agian."</string> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"Ikusi zaintzeko urratsak"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Ezkerreko lasterbidea"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"Eskuineko lasterbidea"</string> diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml index 4ba5ede38606..ce8f0ef63163 100644 --- a/packages/SystemUI/res/values-fa/strings.xml +++ b/packages/SystemUI/res/values-fa/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"چهره شناسایی نشد. درعوض از اثر انگشت استفاده کنید."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"چهره شناسایی نشد"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"از اثر انگشت استفاده کنید"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"بلوتوث متصل است."</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"درصد شارژ باتری مشخص نیست."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"به <xliff:g id="BLUETOOTH">%s</xliff:g> متصل شد."</string> @@ -423,10 +421,8 @@ <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"همپوشانی زیرنویس ناشنوایان"</string> <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"فعال کردن"</string> <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"غیرفعال کردن"</string> - <!-- no translation found for sound_settings (8874581353127418308) --> - <skip /> - <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) --> - <skip /> + <string name="sound_settings" msgid="8874581353127418308">"صدا و لرزش"</string> + <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"تنظیمات"</string> <string name="screen_pinning_title" msgid="9058007390337841305">"برنامه سنجاق شده است"</string> <string name="screen_pinning_description" msgid="8699395373875667743">"تا زمانی که سنجاق را برندارید، در نما نگهداشته میشود. برای برداشتن سنجاق، «برگشت» و «نمای کلی» را لمس کنید و نگهدارید."</string> <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"تا برداشتن سنجاق، در نما نگهداشته میشود. برای برداشتن سنجاق، «برگشت» و «صفحه اصلی» را لمس کنید و نگهدارید."</string> @@ -602,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"روشن"</string> <string name="switch_bar_off" msgid="5669805115416379556">"خاموش"</string> <string name="tile_unavailable" msgid="3095879009136616920">"در دسترس نیست"</string> - <string name="tile_disabled" msgid="373212051546573069">"غیرفعال"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"بیشتر بدانید"</string> <string name="nav_bar" msgid="4642708685386136807">"نوار پیمایش"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"طرحبندی"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"نوع دکمه منتهیالیه چپ"</string> @@ -675,8 +671,8 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"وقتی تلفن درحال خنک شدن است، بعضی از ویژگیها محدود میشوند.\nبرای اطلاعات بیشتر ضربه بزنید"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"تلفنتان بهطور خودکار سعی میکند خنک شود. همچنان میتوانید از تلفنتان استفاده کنید، اما ممکن است کندتر عمل کند.\n\nوقتی تلفن خنک شد، عملکرد عادیاش از سرگرفته میشود."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"دیدن اقدامات محافظتی"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"جدا کردن شارژر از برق"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"مشکلی در شارژ کردن این دستگاه وجود دارد. آداپتور برق را از برق جدا کنید و مراقب باشید زیرا ممکن است کابل گرم باشد."</string> + <string name="high_temp_alarm_title" msgid="8654754369605452169">"دستگاه را جدا کنید"</string> + <string name="high_temp_alarm_notify_message" msgid="3917622943609118956">"دستگاهتان کنار درگاه شارژ گرم شده است. اگر دستگاهتان به شارژر یا لوازم جانبی USB متصل است، آن را جدا کنید و مراقب باشید چون ممکن است کابل هم گرم باشد."</string> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"مشاهده مراحل احتیاط"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"میانبر چپ"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"میانبر راست"</string> diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml index 58eb829b5376..754b5b1de20d 100644 --- a/packages/SystemUI/res/values-fi/strings.xml +++ b/packages/SystemUI/res/values-fi/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Kasvoja ei voi tunnistaa. Käytä sormenjälkeä."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"Kasvoja ei voi tunnistaa"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Käytä sormenjälkeä"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth yhdistetty."</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Akun varaustaso ei tiedossa."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Yhteys: <xliff:g id="BLUETOOTH">%s</xliff:g>."</string> @@ -423,10 +421,8 @@ <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Tekstitysten peitto"</string> <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"ota käyttöön"</string> <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"poista käytöstä"</string> - <!-- no translation found for sound_settings (8874581353127418308) --> - <skip /> - <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) --> - <skip /> + <string name="sound_settings" msgid="8874581353127418308">"Ääni ja värinä"</string> + <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Asetukset"</string> <string name="screen_pinning_title" msgid="9058007390337841305">"Sovellus on kiinnitetty"</string> <string name="screen_pinning_description" msgid="8699395373875667743">"Pysyy näkyvissä, kunnes irrotat sen. Irrota painamalla pitkään Edellinen ja Viimeisimmät."</string> <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Pysyy näkyvissä, kunnes irrotat sen. Irrota painamalla pitkään Edellinen ja Aloitusnäyttö."</string> @@ -602,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"Päällä"</string> <string name="switch_bar_off" msgid="5669805115416379556">"Pois päältä"</string> <string name="tile_unavailable" msgid="3095879009136616920">"Ei käytettävissä"</string> - <string name="tile_disabled" msgid="373212051546573069">"Ei käytössä"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"lukeaksesi lisää"</string> <string name="nav_bar" msgid="4642708685386136807">"Navigointipalkki"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"Asettelu"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Ylimääräinen vasen painiketyyppi"</string> @@ -675,8 +671,10 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Joidenkin ominaisuuksien käyttöä on rajoitettu puhelimen jäähtymisen aikana.\nLue lisää napauttamalla"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"Puhelimesi yrittää automaattisesti jäähdyttää itsensä. Voit silti käyttää puhelinta, mutta se voi toimia hitaammin.\n\nKun puhelin on jäähtynyt, se toimii normaalisti."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Katso huoltovaiheet"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Irrota laturi"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"Laitetta ladattaessa tapahtui virhe. Irrota virtalähde varovasti – johto voi olla lämmin."</string> + <!-- no translation found for high_temp_alarm_title (8654754369605452169) --> + <skip /> + <!-- no translation found for high_temp_alarm_notify_message (3917622943609118956) --> + <skip /> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"Katso huoltovaiheet"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Vasen pikakuvake"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"Oikea pikakuvake"</string> diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml index 815cf406cc7f..bbeb0552fa01 100644 --- a/packages/SystemUI/res/values-fr-rCA/strings.xml +++ b/packages/SystemUI/res/values-fr-rCA/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Visage non reconnu. Utilisez plutôt l\'empreinte digitale."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"Visage non reconnu"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Utiliser l\'empreinte digitale"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth connecté"</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Pourcentage de la pile inconnu."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Connecté à : <xliff:g id="BLUETOOTH">%s</xliff:g>"</string> @@ -206,7 +204,7 @@ <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"Option « Capteurs désactivés » active"</string> <string name="accessibility_clear_all" msgid="970525598287244592">"Supprimer toutes les notifications"</string> <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string> - <string name="notification_group_overflow_description" msgid="7176322877233433278">"{count,plural, =1{# autre notification à l\'intérieur.}one{# autre notification à l\'intérieur.}other{# autres notifications à l\'intérieur.}}"</string> + <string name="notification_group_overflow_description" msgid="7176322877233433278">"{count,plural, =1{# autre notification à l\'intérieur.}one{# autre notification à l\'intérieur.}many{# d\'autres notifications à l\'intérieur.}other{# autres notifications à l\'intérieur.}}"</string> <string name="accessibility_rotation_lock_on_landscape" msgid="936972553861524360">"L\'écran est verrouillé en mode paysage."</string> <string name="accessibility_rotation_lock_on_portrait" msgid="2356633398683813837">"L\'écran est verrouillé en mode portrait."</string> <string name="dessert_case" msgid="9104973640704357717">"Vitrine des desserts"</string> @@ -254,7 +252,7 @@ <string name="quick_settings_hotspot_label" msgid="1199196300038363424">"Point d\'accès sans fil"</string> <string name="quick_settings_hotspot_secondary_label_transient" msgid="7585604088079160564">"Activation en cours…"</string> <string name="quick_settings_hotspot_secondary_label_data_saver_enabled" msgid="1280433136266439372">"Écon. données activé"</string> - <string name="quick_settings_hotspot_secondary_label_num_devices" msgid="7536823087501239457">"{count,plural, =1{# appareil}one{# appareil}other{# appareils}}"</string> + <string name="quick_settings_hotspot_secondary_label_num_devices" msgid="7536823087501239457">"{count,plural, =1{# appareil}one{# appareil}many{# d\'appareils}other{# appareils}}"</string> <string name="quick_settings_flashlight_label" msgid="4904634272006284185">"Lampe de poche"</string> <string name="quick_settings_flashlight_camera_in_use" msgid="4820591564526512571">"L\'appareil photo est en cours d\'utilisation"</string> <string name="quick_settings_cellular_detail_title" msgid="792977203299358893">"Données cellulaires"</string> @@ -355,7 +353,7 @@ <string name="guest_notification_session_active" msgid="5567273684713471450">"Vous êtes en mode Invité"</string> <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Si vous ajoutez un nouvel utilisateur, vous quitterez le mode Invité, et toutes les applications et données de la session d\'invité en cours seront supprimées."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Limite d\'utilisateurs atteinte"</string> - <string name="user_limit_reached_message" msgid="1070703858915935796">"{count,plural, =1{Vous ne pouvez créer qu\'un seul utilisateur.}one{Vous pouvez ajouter jusqu\'à # utilisateur.}other{Vous pouvez ajouter jusqu\'à # utilisateurs.}}"</string> + <string name="user_limit_reached_message" msgid="1070703858915935796">"{count,plural, =1{Vous ne pouvez créer qu\'un seul utilisateur.}one{Vous pouvez ajouter jusqu\'à # utilisateur.}many{Vous pouvez ajouter jusqu\'à # d\'utilisateurs.}other{Vous pouvez ajouter jusqu\'à # utilisateurs.}}"</string> <string name="user_remove_user_title" msgid="9124124694835811874">"Supprimer l\'utilisateur?"</string> <string name="user_remove_user_message" msgid="6702834122128031833">"Toutes les applications et les données de cet utilisateur seront supprimées."</string> <string name="user_remove_user_remove" msgid="8387386066949061256">"Supprimer"</string> @@ -543,8 +541,8 @@ <string name="notification_menu_snooze_action" msgid="5415729610393475019">"Me rappeler"</string> <string name="snooze_undo" msgid="2738844148845992103">"Annuler"</string> <string name="snoozed_for_time" msgid="7586689374860469469">"Reporté pour <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> - <string name="snoozeHourOptions" msgid="2332819756222425558">"{count,plural, =1{# heure}=2{# heures}one{# heure}other{# heures}}"</string> - <string name="snoozeMinuteOptions" msgid="2222082405822030979">"{count,plural, =1{# minute}one{# minute}other{# minutes}}"</string> + <string name="snoozeHourOptions" msgid="2332819756222425558">"{count,plural, =1{# heure}=2{# heures}one{# heure}many{# d\'heures}other{# heures}}"</string> + <string name="snoozeMinuteOptions" msgid="2222082405822030979">"{count,plural, =1{# minute}one{# minute}many{# de minutes}other{# minutes}}"</string> <string name="battery_detail_switch_title" msgid="6940976502957380405">"Économiseur de pile"</string> <string name="keyboard_key_button_template" msgid="8005673627272051429">"Bouton <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="3734400625170020657">"Accueil"</string> @@ -600,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"Activé"</string> <string name="switch_bar_off" msgid="5669805115416379556">"Désactivé"</string> <string name="tile_unavailable" msgid="3095879009136616920">"Non disponible"</string> - <string name="tile_disabled" msgid="373212051546573069">"Désactivé"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"En savoir plus"</string> <string name="nav_bar" msgid="4642708685386136807">"Barre de navigation"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"Disposition"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Type de bouton gauche supplémentaire"</string> @@ -673,8 +671,8 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Certaines fonctionnalités sont limitées pendant que le téléphone refroidit.\nTouchez pour en savoir plus"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"Votre téléphone va essayer de se refroidir automatiquement. Vous pouvez toujours l\'utiliser, mais il risque d\'être plus lent.\n\nUne fois refroidi, il fonctionnera normalement."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Afficher les étapes d\'entretien"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Débranchez le chargeur"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"Il y a un problème avec la recharge de cet appareil. Débranchez l\'adaptateur d\'alimentation, et faites attention, car le câble pourrait être chaud."</string> + <string name="high_temp_alarm_title" msgid="8654754369605452169">"Débranchez votre appareil"</string> + <string name="high_temp_alarm_notify_message" msgid="3917622943609118956">"Votre appareil chauffe près du port de recharge. S\'il est connecté à un chargeur ou à un accessoire USB, débranchez-le en faisant attention : le câble pourrait également être chaud."</string> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"Afficher les étapes d\'entretien"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Raccourci gauche"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"Raccourci droit"</string> @@ -768,7 +766,7 @@ <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"basculer"</string> <string name="quick_controls_title" msgid="6839108006171302273">"Commandes des appareils"</string> <string name="controls_providers_title" msgid="6879775889857085056">"Sélectionnez l\'application pour laquelle ajouter des commandes"</string> - <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# commande ajoutée.}one{# commande ajoutée.}other{# commandes ajoutées.}}"</string> + <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# commande ajoutée.}one{# commande ajoutée.}many{# de commandes ajoutées.}other{# commandes ajoutées.}}"</string> <string name="controls_removed" msgid="3731789252222856959">"Supprimé"</string> <string name="accessibility_control_favorite" msgid="8694362691985545985">"Ajouté aux favoris"</string> <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Ajouté aux favoris, en position <xliff:g id="NUMBER">%d</xliff:g>"</string> @@ -925,7 +923,7 @@ <string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Ajouter la tuile"</string> <string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Ne pas ajouter de tuile"</string> <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Choisir l\'utilisateur"</string> - <string name="fgs_manager_footer_label" msgid="8276763570622288231">"{count,plural, =1{# application est active}one{# application est active}other{# applications sont actives}}"</string> + <string name="fgs_manager_footer_label" msgid="8276763570622288231">"{count,plural, =1{# application est active}one{# application est active}many{# d\'applications sont actives}other{# applications sont actives}}"</string> <string name="fgs_dot_content_description" msgid="2865071539464777240">"Nouvelle information"</string> <string name="fgs_manager_dialog_title" msgid="5879184257257718677">"Applications actives"</string> <string name="fgs_manager_dialog_message" msgid="2670045017200730076">"Ces applications sont actives et s\'exécutent même lorsque vous ne les utilisez pas. Cela améliore leur fonctionnalité, mais peut également affecter l\'autonomie de la pile."</string> @@ -955,7 +953,7 @@ <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"L\'appareil photo est désactivé"</string> <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"Le micro est désactivé"</string> <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"L\'appareil photo et le micro sont désactivés"</string> - <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notification}one{# notification}other{# notifications}}"</string> + <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notification}one{# notification}many{# de notifications}other{# notifications}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Diffusion en cours…"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Arrêter la diffusion de <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml index 3dd86507ccc5..4ab5d8315dde 100644 --- a/packages/SystemUI/res/values-fr/strings.xml +++ b/packages/SystemUI/res/values-fr/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Visage non reconnu. Utilisez votre empreinte."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"Visage non reconnu"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Utilisez empreinte digit."</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth connecté"</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Pourcentage de la batterie inconnu."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Connecté à : <xliff:g id="BLUETOOTH">%s</xliff:g>"</string> @@ -206,7 +204,7 @@ <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"Option \"Capteurs désactivés\" active"</string> <string name="accessibility_clear_all" msgid="970525598287244592">"Supprimer toutes les notifications"</string> <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"<xliff:g id="NUMBER">%s</xliff:g> autres"</string> - <string name="notification_group_overflow_description" msgid="7176322877233433278">"{count,plural, =1{# autre notification dans le groupe.}one{# autre notification dans le groupe.}other{# autres notifications dans le groupe.}}"</string> + <string name="notification_group_overflow_description" msgid="7176322877233433278">"{count,plural, =1{# autre notification dans le groupe.}one{# autre notification dans le groupe.}many{# autres notifications dans le groupe.}other{# autres notifications dans le groupe.}}"</string> <string name="accessibility_rotation_lock_on_landscape" msgid="936972553861524360">"L\'écran est verrouillé en mode paysage."</string> <string name="accessibility_rotation_lock_on_portrait" msgid="2356633398683813837">"L\'écran est verrouillé en mode portrait."</string> <string name="dessert_case" msgid="9104973640704357717">"Vitrine des desserts"</string> @@ -254,7 +252,7 @@ <string name="quick_settings_hotspot_label" msgid="1199196300038363424">"Point d\'accès"</string> <string name="quick_settings_hotspot_secondary_label_transient" msgid="7585604088079160564">"Activation…"</string> <string name="quick_settings_hotspot_secondary_label_data_saver_enabled" msgid="1280433136266439372">"Écon. données activé"</string> - <string name="quick_settings_hotspot_secondary_label_num_devices" msgid="7536823087501239457">"{count,plural, =1{# appareil}one{# appareil}other{# appareils}}"</string> + <string name="quick_settings_hotspot_secondary_label_num_devices" msgid="7536823087501239457">"{count,plural, =1{# appareil}one{# appareil}many{# appareils}other{# appareils}}"</string> <string name="quick_settings_flashlight_label" msgid="4904634272006284185">"Lampe de poche"</string> <string name="quick_settings_flashlight_camera_in_use" msgid="4820591564526512571">"Caméra en cours d\'utilisation"</string> <string name="quick_settings_cellular_detail_title" msgid="792977203299358893">"Données mobiles"</string> @@ -355,7 +353,7 @@ <string name="guest_notification_session_active" msgid="5567273684713471450">"Vous êtes en mode Invité"</string> <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Si vous ajoutez un utilisateur, le mode Invité sera désactivé et toutes les applis et les données de la session Invité actuelle seront supprimées."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Limite nombre utilisateurs atteinte"</string> - <string name="user_limit_reached_message" msgid="1070703858915935796">"{count,plural, =1{Vous ne pouvez créer qu\'un seul utilisateur.}one{Vous pouvez ajouter # utilisateur.}other{Vous pouvez ajouter jusqu\'à # utilisateurs.}}"</string> + <string name="user_limit_reached_message" msgid="1070703858915935796">"{count,plural, =1{Vous ne pouvez créer qu\'un seul utilisateur.}one{Vous pouvez ajouter # utilisateur.}many{Vous pouvez ajouter jusqu\'à # utilisateurs.}other{Vous pouvez ajouter jusqu\'à # utilisateurs.}}"</string> <string name="user_remove_user_title" msgid="9124124694835811874">"Supprimer l\'utilisateur ?"</string> <string name="user_remove_user_message" msgid="6702834122128031833">"Toutes les applications et les données de cet utilisateur seront supprimées."</string> <string name="user_remove_user_remove" msgid="8387386066949061256">"Supprimer"</string> @@ -423,10 +421,8 @@ <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Sous-titres en superposition"</string> <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"activer"</string> <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"désactiver"</string> - <!-- no translation found for sound_settings (8874581353127418308) --> - <skip /> - <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) --> - <skip /> + <string name="sound_settings" msgid="8874581353127418308">"Son et vibreur"</string> + <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Paramètres"</string> <string name="screen_pinning_title" msgid="9058007390337841305">"L\'application est épinglée"</string> <string name="screen_pinning_description" msgid="8699395373875667743">"Elle restera visible jusqu\'à ce que vous la retiriez. Pour la retirer, appuyez de manière prolongée sur les boutons Retour et Aperçu."</string> <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Elle restera visible jusqu\'à ce que vous la retiriez. Pour la retirer, appuyez de manière prolongée sur les boutons Retour et Accueil."</string> @@ -545,8 +541,8 @@ <string name="notification_menu_snooze_action" msgid="5415729610393475019">"M\'envoyer un rappel"</string> <string name="snooze_undo" msgid="2738844148845992103">"Annuler"</string> <string name="snoozed_for_time" msgid="7586689374860469469">"Répétée après <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> - <string name="snoozeHourOptions" msgid="2332819756222425558">"{count,plural, =1{# heure}=2{# heures}one{# heure}other{# heures}}"</string> - <string name="snoozeMinuteOptions" msgid="2222082405822030979">"{count,plural, =1{# minute}one{# minute}other{# minutes}}"</string> + <string name="snoozeHourOptions" msgid="2332819756222425558">"{count,plural, =1{# heure}=2{# heures}one{# heure}many{# heures}other{# heures}}"</string> + <string name="snoozeMinuteOptions" msgid="2222082405822030979">"{count,plural, =1{# minute}one{# minute}many{# minutes}other{# minutes}}"</string> <string name="battery_detail_switch_title" msgid="6940976502957380405">"Économiseur de batterie"</string> <string name="keyboard_key_button_template" msgid="8005673627272051429">"Bouton <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="3734400625170020657">"Accueil"</string> @@ -602,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"Activé"</string> <string name="switch_bar_off" msgid="5669805115416379556">"Désactivé"</string> <string name="tile_unavailable" msgid="3095879009136616920">"Indisponible"</string> - <string name="tile_disabled" msgid="373212051546573069">"Désactivé"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"en savoir plus"</string> <string name="nav_bar" msgid="4642708685386136807">"Barre de navigation"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"Disposition"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Type de bouton gauche supplémentaire"</string> @@ -675,8 +671,10 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Fonctionnalités limitées pendant le refroidissement du téléphone.\nAppuyer pour en savoir plus"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"Votre téléphone va essayer de se refroidir automatiquement. Vous pouvez toujours l\'utiliser, mais il risque d\'être plus lent.\n\nUne fois refroidi, il fonctionnera normalement."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Afficher les étapes d\'entretien"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Débrancher le chargeur"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"Un problème est survenu lors de la recharge de cet appareil. Débranchez l\'adaptateur secteur en faisant attention, car le câble risque d\'être chaud."</string> + <!-- no translation found for high_temp_alarm_title (8654754369605452169) --> + <skip /> + <!-- no translation found for high_temp_alarm_notify_message (3917622943609118956) --> + <skip /> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"Afficher les étapes d\'entretien"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Raccourci gauche"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"Raccourci droit"</string> @@ -770,7 +768,7 @@ <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"activer/désactiver"</string> <string name="quick_controls_title" msgid="6839108006171302273">"Commandes des appareils"</string> <string name="controls_providers_title" msgid="6879775889857085056">"Sélectionnez l\'appli pour laquelle ajouter des commandes"</string> - <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# commande ajoutée.}one{# commande ajoutée.}other{# commandes ajoutées.}}"</string> + <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# commande ajoutée.}one{# commande ajoutée.}many{# commandes ajoutées.}other{# commandes ajoutées.}}"</string> <string name="controls_removed" msgid="3731789252222856959">"Supprimé"</string> <string name="accessibility_control_favorite" msgid="8694362691985545985">"Ajouté aux favoris"</string> <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Ajouté aux favoris, en position <xliff:g id="NUMBER">%d</xliff:g>"</string> @@ -927,7 +925,7 @@ <string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Ajouter le bloc"</string> <string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Ne pas ajouter le bloc"</string> <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Choisir l\'utilisateur"</string> - <string name="fgs_manager_footer_label" msgid="8276763570622288231">"{count,plural, =1{# appli est active}one{# appli est active}other{# applis sont actives}}"</string> + <string name="fgs_manager_footer_label" msgid="8276763570622288231">"{count,plural, =1{# appli est active}one{# appli est active}many{# applis sont actives}other{# applis sont actives}}"</string> <string name="fgs_dot_content_description" msgid="2865071539464777240">"Nouvelles informations"</string> <string name="fgs_manager_dialog_title" msgid="5879184257257718677">"Applis actives"</string> <string name="fgs_manager_dialog_message" msgid="2670045017200730076">"Ces applis sont actives et s\'exécutent même lorsque vous ne les utilisez pas. Cela améliore leur fonctionnement, mais peut également affecter l\'autonomie de la batterie."</string> @@ -957,7 +955,7 @@ <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"Caméra désactivée"</string> <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"Micro désactivé"</string> <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Appareil photo et micro désactivés"</string> - <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notification}one{# notification}other{# notifications}}"</string> + <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notification}one{# notification}many{# notifications}other{# notifications}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Diffusion…"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Arrêter la diffusion de <xliff:g id="APP_NAME">%1$s</xliff:g> ?"</string> diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml index ffc8eb128ced..d5197f772fed 100644 --- a/packages/SystemUI/res/values-gl/strings.xml +++ b/packages/SystemUI/res/values-gl/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Non se recoñeceu a cara. Usa a impresión dixital."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"Non se recoñeceu a cara"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Usa a impresión dixital"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth conectado"</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Descoñécese a porcentaxe da batería."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Conectado a <xliff:g id="BLUETOOTH">%s</xliff:g>."</string> @@ -423,10 +421,8 @@ <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Superposición de subtítulos"</string> <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"activa"</string> <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"desactiva"</string> - <!-- no translation found for sound_settings (8874581353127418308) --> - <skip /> - <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) --> - <skip /> + <string name="sound_settings" msgid="8874581353127418308">"Son e vibración"</string> + <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Configuración"</string> <string name="screen_pinning_title" msgid="9058007390337841305">"A aplicación está fixada"</string> <string name="screen_pinning_description" msgid="8699395373875667743">"A pantalla manterase visible ata que deixes de fixala. Para facelo, mantén premido Atrás e Visión xeral."</string> <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"A pantalla manterase visible ata que deixes de fixala. Para facelo, mantén premido Atrás e Inicio."</string> @@ -602,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"Activado"</string> <string name="switch_bar_off" msgid="5669805115416379556">"Desactivado"</string> <string name="tile_unavailable" msgid="3095879009136616920">"Non dispoñible"</string> - <string name="tile_disabled" msgid="373212051546573069">"Desactivado"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"obter máis información"</string> <string name="nav_bar" msgid="4642708685386136807">"Barra de navegación"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"Deseño"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Tipo de botón adicional á esquerda"</string> @@ -675,8 +671,10 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"O uso dalgunhas funcións é limitado mentres o teléfono arrefría.\nToca para obter máis información"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"O teléfono tentará arrefriar automaticamente. Podes utilizalo, pero é probable que funcione máis lento.\n\nUnha vez que arrefríe, funcionará con normalidade."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Ver pasos de mantemento"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Desconecta o cargador"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"Produciuse un problema ao cargar este dispositivo. Desconecta o adaptador de corrente e ten coidado porque o cable pode estar quente."</string> + <!-- no translation found for high_temp_alarm_title (8654754369605452169) --> + <skip /> + <!-- no translation found for high_temp_alarm_notify_message (3917622943609118956) --> + <skip /> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"Ver pasos de mantemento"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Atallo á esquerda"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"Atallo á dereita"</string> diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml index 5731df3a15db..1562101cab2e 100644 --- a/packages/SystemUI/res/values-gu/strings.xml +++ b/packages/SystemUI/res/values-gu/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"ચહેરો ઓળખી શકતા નથી. તેને બદલે ફિંગરપ્રિન્ટ વાપરો."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"ચહેરો ઓળખાતો નથી"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"તો ફિંગરપ્રિન્ટ વાપરો"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"બ્લૂટૂથ કનેક્ટ થયું."</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"બૅટરીની ટકાવારી અજાણ છે."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> થી કનેક્ટ થયાં."</string> @@ -600,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"ચાલુ"</string> <string name="switch_bar_off" msgid="5669805115416379556">"બંધ"</string> <string name="tile_unavailable" msgid="3095879009136616920">"ઉપલબ્ધ નથી"</string> - <string name="tile_disabled" msgid="373212051546573069">"બંધ છે"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"વધુ જાણો"</string> <string name="nav_bar" msgid="4642708685386136807">"નેવિગેશન બાર"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"લેઆઉટ"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"અતિરિક્ત ડાબો બટન પ્રકાર"</string> @@ -673,8 +671,8 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"ફોન ઠંડો થાય ત્યાં સુધી અમુક સુવિધાઓ મર્યાદિત હોય છે.\nવધુ માહિતી માટે ટૅપ કરો"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"તમારો ફોન ઑટોમૅટિક રીતે ઠંડો થવાનો પ્રયાસ કરશે. તમે હજી પણ તમારા ફોનનો ઉપયોગ કરી શકો છો, પરંતુ તે કદાચ થોડો ધીમો ચાલે.\n\nતમારો ફોન ઠંડો થઈ જવા પર, તે સામાન્ય રીતે ચાલશે."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"સારસંભાળના પગલાં જુઓ"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"ચાર્જરને અનપ્લગ કરો"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"આ ડિવાઇસને ચાર્જ કરવામાં કોઈ સમસ્યા છે. પાવર અડૅપ્ટર અનપ્લગ કરો અને કાળજી લેજો કદાચ કેબલ થોડો ગરમ થયો હોઈ શકે છે."</string> + <string name="high_temp_alarm_title" msgid="8654754369605452169">"તમારા ડિવાઇસને અનપ્લગ કરો"</string> + <string name="high_temp_alarm_notify_message" msgid="3917622943609118956">"તમારું ડિવાઇસ ચાર્જિંગ પોર્ટની પાસે ગરમ થઈ રહ્યું છે. જો તે કોઈ ચાર્જર અથવા USB ઍક્સેસરી સાથે કનેક્ટેડ હોય, તો તેને અનપ્લગ કરો અને ધ્યાન રાખો, કારણ કે કેબલ ગરમ પણ હોઈ શકે છે."</string> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"સારસંભાળના પગલાં જુઓ"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"ડાબો શૉર્ટકટ"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"જમણો શૉર્ટકટ"</string> diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml index 43bc1123f917..5664c6a8fc5a 100644 --- a/packages/SystemUI/res/values-hi/strings.xml +++ b/packages/SystemUI/res/values-hi/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"चेहरे की पहचान नहीं हुई. फ़िंगरप्रिंट इस्तेमाल करें."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"चेहरे की पहचान नहीं हुई"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"फ़िंगरप्रिंट इस्तेमाल करें"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"ब्लूटूथ कनेक्ट किया गया."</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"इस बारे में जानकारी नहीं है कि अभी बैटरी कितने प्रतिशत चार्ज है."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> से कनेक्ट किया गया."</string> @@ -423,10 +421,8 @@ <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"कैप्शन ऊपर लगाएं"</string> <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"चालू करें"</string> <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"बंद करें"</string> - <!-- no translation found for sound_settings (8874581353127418308) --> - <skip /> - <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) --> - <skip /> + <string name="sound_settings" msgid="8874581353127418308">"आवाज़ और वाइब्रेशन"</string> + <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"सेटिंग"</string> <string name="screen_pinning_title" msgid="9058007390337841305">"ऐप्लिकेशन पिन किया गया है"</string> <string name="screen_pinning_description" msgid="8699395373875667743">"इससे वह तब तक दिखता रहता है, जब तक कि आप उसे अनपिन नहीं कर देते. अनपिन करने के लिए, \'वापस जाएं\' और \'खास जानकारी\' को दबाकर रखें."</string> <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"इससे वह तब तक दिखाई देती है जब तक आप उसे अनपिन नहीं कर देते. अनपिन करने के लिए, होम और वापस जाएं वाले बटन को दबाकर रखें."</string> @@ -602,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"चालू"</string> <string name="switch_bar_off" msgid="5669805115416379556">"बंद"</string> <string name="tile_unavailable" msgid="3095879009136616920">"उपलब्ध नहीं है"</string> - <string name="tile_disabled" msgid="373212051546573069">"बंद है"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"ज़्यादा जानें"</string> <string name="nav_bar" msgid="4642708685386136807">"नेविगेशन बार"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"लेआउट"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"कुछ और बाएं बटन के प्रकार"</string> @@ -675,8 +671,8 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"फ़ोन के ठंडा होने तक कुछ सुविधाएं काम नहीं करतीं.\nज़्यादा जानकारी के लिए टैप करें"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"आपका फ़ोन अपने आप ठंडा होने की कोशिश करेगा. आप अब भी अपने फ़ोन का उपयोग कर सकते हैं, लेकिन हो सकता है कि यह धीमी गति से चले.\n\nठंडा हो जाने पर आपका फ़ोन सामान्य रूप से चलेगा."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"डिवाइस के रखरखाव के तरीके देखें"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"चार्जर निकालें"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"इस डिवाइस को चार्ज करने में समस्या हुई. पावर अडैप्टर का प्लग निकालें. ऐसा करते समय सावधानी बरतें क्योंकि तार गर्म हो सकता है."</string> + <string name="high_temp_alarm_title" msgid="8654754369605452169">"डिवाइस को अनप्लग करें"</string> + <string name="high_temp_alarm_notify_message" msgid="3917622943609118956">"आपका डिवाइस चार्जिंग पोर्ट के पास गर्म हो रहा है. अगर डिवाइस चार्जर या यूएसबी ऐक्सेसरी से कनेक्ट है, तो उसे अनप्लग करें. साथ ही, ध्यान रखें कि केबल भी गर्म हो सकती है."</string> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"प्रबंधन से जुड़े चरण देखें"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"बायां शॉर्टकट"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"दायां शॉर्टकट"</string> diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml index 19298f4a0a84..1a9768cf5ee9 100644 --- a/packages/SystemUI/res/values-hr/strings.xml +++ b/packages/SystemUI/res/values-hr/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Prepoznavanje lica nije uspjelo. Upotrijebite otisak prsta."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"Lice nije prepoznato"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Upotrijebite otisak prsta"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth povezan."</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Postotak baterije nije poznat."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Spojen na <xliff:g id="BLUETOOTH">%s</xliff:g> ."</string> @@ -423,10 +421,8 @@ <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Sloj titlova"</string> <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"omogući"</string> <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"onemogući"</string> - <!-- no translation found for sound_settings (8874581353127418308) --> - <skip /> - <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) --> - <skip /> + <string name="sound_settings" msgid="8874581353127418308">"Zvuk i vibracija"</string> + <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Postavke"</string> <string name="screen_pinning_title" msgid="9058007390337841305">"Aplikacija je prikvačena"</string> <string name="screen_pinning_description" msgid="8699395373875667743">"Zaslon će tako ostati u prvom planu dok ga ne otkvačite. Dodirnite i zadržite Natrag i Pregled da biste ga otkvačili."</string> <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Zaslon će tako ostati u prvom planu dok ga ne otkvačite. Dodirnite gumbe Natrag i Početna i zadržite pritisak da biste ga otkvačili."</string> @@ -602,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"Uključeno"</string> <string name="switch_bar_off" msgid="5669805115416379556">"Isključeno"</string> <string name="tile_unavailable" msgid="3095879009136616920">"Nedostupno"</string> - <string name="tile_disabled" msgid="373212051546573069">"Onemogućeno"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"saznajte više"</string> <string name="nav_bar" msgid="4642708685386136807">"Navigacijska traka"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"Izgled"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Vrsta dodatnog lijevog gumba"</string> @@ -675,8 +671,8 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Neke su značajke ograničene dok se telefon ne ohladi.\nDodirnite za više informacija"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"Telefon će se automatski pokušati ohladiti. Možete ga nastaviti koristiti, no mogao bi raditi sporije.\n\nKad se ohladi, radit će normalno."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Pročitajte upute za održavanje"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Iskopčajte punjač"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"Pojavio se problem s punjenjem uređaja. Iskopčajte pretvarač napona i pazite jer se kabel može zagrijati."</string> + <string name="high_temp_alarm_title" msgid="8654754369605452169">"Iskopčajte uređaj"</string> + <string name="high_temp_alarm_notify_message" msgid="3917622943609118956">"Vaš se uređaj zagrijava u blizini priključka za punjenje. Ako je priključen u punjač ili USB uređaj, iskopčajte ga. Pazite jer se i kabel možda zagrijao."</string> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"Pogledajte upute za održavanje"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Lijevi prečac"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"Desni prečac"</string> diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml index fb8d5c7fab8c..0d10cdc7e52b 100644 --- a/packages/SystemUI/res/values-hu/strings.xml +++ b/packages/SystemUI/res/values-hu/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Az arc nem felismerhető. Használjon ujjlenyomatot."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"Az arc nem ismerhető fel"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Használjon ujjlenyomatot"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth csatlakoztatva."</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Az akkumulátor töltöttségi szintje ismeretlen."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Csatlakoztatva a következőhöz: <xliff:g id="BLUETOOTH">%s</xliff:g>."</string> @@ -423,10 +421,8 @@ <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Feliratok fedvény"</string> <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"engedélyezés"</string> <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"letiltás"</string> - <!-- no translation found for sound_settings (8874581353127418308) --> - <skip /> - <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) --> - <skip /> + <string name="sound_settings" msgid="8874581353127418308">"Hang és rezgés"</string> + <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Beállítások"</string> <string name="screen_pinning_title" msgid="9058007390337841305">"Az alkalmazás ki van tűzve"</string> <string name="screen_pinning_description" msgid="8699395373875667743">"Megjelenítve tartja addig, amíg Ön fel nem oldja a rögzítést. A feloldáshoz tartsa lenyomva a Vissza és az Áttekintés lehetőséget."</string> <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Megjelenítve tartja addig, amíg Ön fel nem oldja a rögzítést. A feloldáshoz tartsa lenyomva a Vissza és a Kezdőképernyő elemet."</string> @@ -602,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"Be"</string> <string name="switch_bar_off" msgid="5669805115416379556">"Ki"</string> <string name="tile_unavailable" msgid="3095879009136616920">"Nem használható"</string> - <string name="tile_disabled" msgid="373212051546573069">"Kikapcsolva"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"további információ"</string> <string name="nav_bar" msgid="4642708685386136807">"Navigációs sáv"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"Elrendezés"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"További bal oldali gombtípus"</string> @@ -675,8 +671,10 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Bizonyos funkciók korlátozottan működnek a telefon lehűlése közben.\nKoppintson, ha további információra van szüksége."</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"A telefon automatikusan megpróbál lehűlni. Továbbra is tudja használni a telefont, de elképzelhető, hogy működése lelassul.\n\nAmint a telefon lehűl, újra a szokásos módon működik majd."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Olvassa el a kímélő használat lépéseit"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Húzza ki a töltőt"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"Probléma adódott az eszköz töltése során. Húzza ki a hálózati adaptert. Vigyázzon, a kábel forró lehet."</string> + <!-- no translation found for high_temp_alarm_title (8654754369605452169) --> + <skip /> + <!-- no translation found for high_temp_alarm_notify_message (3917622943609118956) --> + <skip /> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"Olvassa el a megfelelő használat lépéseit"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Bal oldali parancsikon"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"Jobb oldali parancsikon"</string> diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml index 3501f5298824..52e54543d323 100644 --- a/packages/SystemUI/res/values-hy/strings.xml +++ b/packages/SystemUI/res/values-hy/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Դեմքը չի հաջողվում ճանաչել։ Օգտագործեք մատնահետքը։"</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"Դեմքը չի ճանաչվել"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Օգտագործեք մատնահետք"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth-ը միացված է:"</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Մարտկոցի լիցքի մակարդակն անհայտ է։"</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Միացված է <xliff:g id="BLUETOOTH">%s</xliff:g>-ին:"</string> @@ -600,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"Միացված է"</string> <string name="switch_bar_off" msgid="5669805115416379556">"Անջատված է"</string> <string name="tile_unavailable" msgid="3095879009136616920">"Հասանելի չէ"</string> - <string name="tile_disabled" msgid="373212051546573069">"Անջատված է"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"Իմանալ ավելին"</string> <string name="nav_bar" msgid="4642708685386136807">"Նավիգացիայի գոտի"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"Դասավորություն"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Լրացուցիչ ձախ կոճակի տեսակ"</string> @@ -673,8 +671,10 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Հովանալու ընթացքում հեռախոսի որոշ գործառույթներ սահմանափակ են։\nՀպեք՝ ավելին իմանալու համար։"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"Ձեր հեռախոսն ավտոմատ կերպով կփորձի hովանալ: Կարող եք շարունակել օգտագործել հեռախոսը, սակայն հնարավոր է, որ այն ավելի դանդաղ աշխատի:\n\nՀովանալուց հետո հեռախոսը կաշխատի կանոնավոր կերպով:"</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Քայլեր գերտաքացման ահազանգի դեպքում"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Անջատեք լիցքավորիչը հոսանքից"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"Չհաջողվեց լիցքավորել սարքը: Անջատեք հոսանքի ադապտերը և ուշադիր եղեք՝ մալուխը կարող է տաքացած լինել:"</string> + <!-- no translation found for high_temp_alarm_title (8654754369605452169) --> + <skip /> + <!-- no translation found for high_temp_alarm_notify_message (3917622943609118956) --> + <skip /> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"Քայլեր գերտաքացման ահազանգի դեպքում"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Ձախ դյուրանցում"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"Աջ դյուրանցում"</string> diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml index 26e7f3e11243..f0a8889acd2f 100644 --- a/packages/SystemUI/res/values-in/strings.xml +++ b/packages/SystemUI/res/values-in/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Tidak dapat mengenali wajah. Gunakan sidik jari."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"Tidak mengenali wajah"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Gunakan sidik jari"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth terhubung."</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Persentase baterai tidak diketahui."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Terhubung ke <xliff:g id="BLUETOOTH">%s</xliff:g>."</string> @@ -423,10 +421,8 @@ <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Overlay teks"</string> <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"aktifkan"</string> <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"nonaktifkan"</string> - <!-- no translation found for sound_settings (8874581353127418308) --> - <skip /> - <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) --> - <skip /> + <string name="sound_settings" msgid="8874581353127418308">"Suara & getaran"</string> + <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Setelan"</string> <string name="screen_pinning_title" msgid="9058007390337841305">"Aplikasi disematkan"</string> <string name="screen_pinning_description" msgid="8699395373875667743">"Ini akan terus ditampilkan sampai Anda melepas sematan. Sentuh lama tombol Kembali dan Ringkasan untuk melepas sematan."</string> <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Ini akan terus ditampilkan sampai Anda melepas sematan. Sentuh lama tombol Kembali dan Beranda untuk melepas sematan."</string> @@ -602,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"Aktif"</string> <string name="switch_bar_off" msgid="5669805115416379556">"Nonaktif"</string> <string name="tile_unavailable" msgid="3095879009136616920">"Tidak tersedia"</string> - <string name="tile_disabled" msgid="373212051546573069">"Nonaktif"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"pelajari lebih lanjut"</string> <string name="nav_bar" msgid="4642708685386136807">"Bilah navigasi"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"Tata Letak"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Jenis tombol ekstra kiri"</string> @@ -675,8 +671,10 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Beberapa fitur dibatasi saat ponsel mendingin.\nKetuk untuk info selengkapnya"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"Ponsel akan otomatis mencoba mendingin. Anda tetap dapat menggunakan ponsel, tetapi mungkin berjalan lebih lambat.\n\nSetelah dingin, ponsel akan berjalan seperti biasa."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Lihat langkah-langkah perawatan"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Cabut pengisi daya"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"Ada masalah saat mengisi daya perangkat ini. Cabut adaptor daya dan berhati-hatilah karena kabelnya mungkin panas."</string> + <!-- no translation found for high_temp_alarm_title (8654754369605452169) --> + <skip /> + <!-- no translation found for high_temp_alarm_notify_message (3917622943609118956) --> + <skip /> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"Lihat langkah-langkah perawatan"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Pintasan kiri"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"Pintasan kanan"</string> diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml index b699135f9751..3b453f233ef6 100644 --- a/packages/SystemUI/res/values-is/strings.xml +++ b/packages/SystemUI/res/values-is/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Andlit þekkist ekki. Notaðu fingrafar í staðinn."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"Andlit þekkist ekki"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Nota fingrafar í staðinn"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth tengt."</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Staða rafhlöðu óþekkt."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Tengt við <xliff:g id="BLUETOOTH">%s</xliff:g>."</string> @@ -423,10 +421,8 @@ <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Yfirlögn myndatexta"</string> <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"virkja"</string> <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"slökkva"</string> - <!-- no translation found for sound_settings (8874581353127418308) --> - <skip /> - <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) --> - <skip /> + <string name="sound_settings" msgid="8874581353127418308">"Hljóð og titringur"</string> + <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Stillingar"</string> <string name="screen_pinning_title" msgid="9058007390337841305">"Forrit er fest"</string> <string name="screen_pinning_description" msgid="8699395373875667743">"Þetta heldur þessu opnu þangað til þú losar það. Haltu fingri á „Til baka“ og „Yfirlit“ til að losa."</string> <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Þetta heldur þessu opnu þangað til það er losað. Haltu inni bakkhnappinum og heimahnappinum til að losa."</string> @@ -602,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"Kveikt"</string> <string name="switch_bar_off" msgid="5669805115416379556">"Slökkt"</string> <string name="tile_unavailable" msgid="3095879009136616920">"Ekki í boði"</string> - <string name="tile_disabled" msgid="373212051546573069">"Slökkt"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"nánar"</string> <string name="nav_bar" msgid="4642708685386136807">"Yfirlitsstika"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"Útlit"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Gerð aukahnapps til vinstri"</string> @@ -675,8 +671,10 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Sumir eiginleikar eru takmarkaðir meðan síminn kælir sig.\nÝttu til að fá frekari upplýsingar"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"Síminn reynir sjálfkrafa að kæla sig. Þú getur enn notað símann en hann gæti verið hægvirkari.\n\nEftir að síminn hefur kælt sig niður virkar hann eðlilega."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Sjá varúðarskref"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Taktu hleðslutækið úr sambandi"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"Upp kom vandamál varðandi hleðslu tækisins. Taktu straumbreytinn úr sambandi og farðu varlega því snúran gæti verið heit."</string> + <!-- no translation found for high_temp_alarm_title (8654754369605452169) --> + <skip /> + <!-- no translation found for high_temp_alarm_notify_message (3917622943609118956) --> + <skip /> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"Sjá varúðarskref"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Flýtilykill til vinstri"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"Flýtilykill til hægri"</string> diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml index e1bf662762ca..468814e459f0 100644 --- a/packages/SystemUI/res/values-it/strings.xml +++ b/packages/SystemUI/res/values-it/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Impossibile riconoscere il volto. Usa l\'impronta."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"Volto non riconosciuto"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Usa l\'impronta"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth collegato."</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Percentuale della batteria sconosciuta."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Connesso a <xliff:g id="BLUETOOTH">%s</xliff:g>."</string> @@ -206,7 +204,7 @@ <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"Opzione Sensori disattivati attiva"</string> <string name="accessibility_clear_all" msgid="970525598287244592">"Cancella tutte le notifiche."</string> <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string> - <string name="notification_group_overflow_description" msgid="7176322877233433278">"{count,plural, =1{# altra notifica nel gruppo.}other{Altre # notifiche nel gruppo.}}"</string> + <string name="notification_group_overflow_description" msgid="7176322877233433278">"{count,plural, =1{# altra notifica nel gruppo.}many{Altre # notifiche nel gruppo.}other{Altre # notifiche nel gruppo.}}"</string> <string name="accessibility_rotation_lock_on_landscape" msgid="936972553861524360">"Lo schermo è bloccato in orientamento orizzontale."</string> <string name="accessibility_rotation_lock_on_portrait" msgid="2356633398683813837">"Lo schermo è bloccato in orientamento verticale."</string> <string name="dessert_case" msgid="9104973640704357717">"Vetrina di dolci"</string> @@ -254,7 +252,7 @@ <string name="quick_settings_hotspot_label" msgid="1199196300038363424">"Hotspot"</string> <string name="quick_settings_hotspot_secondary_label_transient" msgid="7585604088079160564">"Attivazione…"</string> <string name="quick_settings_hotspot_secondary_label_data_saver_enabled" msgid="1280433136266439372">"Risp. dati attivo"</string> - <string name="quick_settings_hotspot_secondary_label_num_devices" msgid="7536823087501239457">"{count,plural, =1{# dispositivo}other{# dispositivi}}"</string> + <string name="quick_settings_hotspot_secondary_label_num_devices" msgid="7536823087501239457">"{count,plural, =1{# dispositivo}many{# dispositivi}other{# dispositivi}}"</string> <string name="quick_settings_flashlight_label" msgid="4904634272006284185">"Torcia"</string> <string name="quick_settings_flashlight_camera_in_use" msgid="4820591564526512571">"Fotocamera in uso"</string> <string name="quick_settings_cellular_detail_title" msgid="792977203299358893">"Dati mobili"</string> @@ -355,7 +353,7 @@ <string name="guest_notification_session_active" msgid="5567273684713471450">"Sei in modalità Ospite"</string> <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Se aggiungi un nuovo utente, la modalità Ospite viene disattivata e vengono eliminati tutti i dati e le app della sessione Ospite corrente."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Limite di utenti raggiunto"</string> - <string name="user_limit_reached_message" msgid="1070703858915935796">"{count,plural, =1{Può essere creato un solo utente.}other{Puoi aggiungere fino a # utenti.}}"</string> + <string name="user_limit_reached_message" msgid="1070703858915935796">"{count,plural, =1{Può essere creato un solo utente.}many{Puoi aggiungere fino a # utenti.}other{Puoi aggiungere fino a # utenti.}}"</string> <string name="user_remove_user_title" msgid="9124124694835811874">"Rimuovere l\'utente?"</string> <string name="user_remove_user_message" msgid="6702834122128031833">"Tutte le app e i dati di questo utente verranno eliminati."</string> <string name="user_remove_user_remove" msgid="8387386066949061256">"Rimuovi"</string> @@ -543,8 +541,8 @@ <string name="notification_menu_snooze_action" msgid="5415729610393475019">"Ricordamelo"</string> <string name="snooze_undo" msgid="2738844148845992103">"Annulla"</string> <string name="snoozed_for_time" msgid="7586689374860469469">"Posticipato di <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> - <string name="snoozeHourOptions" msgid="2332819756222425558">"{count,plural, =1{# ora}=2{# ore}other{# ore}}"</string> - <string name="snoozeMinuteOptions" msgid="2222082405822030979">"{count,plural, =1{# minuto}other{# minuti}}"</string> + <string name="snoozeHourOptions" msgid="2332819756222425558">"{count,plural, =1{# ora}=2{# ore}many{# ore}other{# ore}}"</string> + <string name="snoozeMinuteOptions" msgid="2222082405822030979">"{count,plural, =1{# minuto}many{# minuti}other{# minuti}}"</string> <string name="battery_detail_switch_title" msgid="6940976502957380405">"Risparmio energetico"</string> <string name="keyboard_key_button_template" msgid="8005673627272051429">"Pulsante <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="3734400625170020657">"Home page"</string> @@ -600,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"On"</string> <string name="switch_bar_off" msgid="5669805115416379556">"Off"</string> <string name="tile_unavailable" msgid="3095879009136616920">"Non disponibile"</string> - <string name="tile_disabled" msgid="373212051546573069">"Riquadro disattivato"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"scopri di più"</string> <string name="nav_bar" msgid="4642708685386136807">"Barra di navigazione"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"Layout"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Tipo di pulsante extra sinistra"</string> @@ -673,8 +671,10 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Alcune funzionalità limitate durante il raffreddamento del telefono.\nTocca per ulteriori informazioni"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"Il telefono cercherà automaticamente di raffreddarsi. Puoi comunque usarlo, ma potrebbe essere più lento.\n\nUna volta raffreddato, il telefono funzionerà normalmente."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Leggi le misure da adottare"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Scollega il caricabatterie"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"Si è verificato un problema durante la ricarica del dispositivo. Scollega l\'alimentatore e presta attenzione perché il cavo potrebbe essere caldo."</string> + <!-- no translation found for high_temp_alarm_title (8654754369605452169) --> + <skip /> + <!-- no translation found for high_temp_alarm_notify_message (3917622943609118956) --> + <skip /> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"Leggi le misure da adottare"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Scorciatoia sinistra"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"Scorciatoia destra"</string> @@ -768,7 +768,7 @@ <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"attiva/disattiva"</string> <string name="quick_controls_title" msgid="6839108006171302273">"Controllo dispositivi"</string> <string name="controls_providers_title" msgid="6879775889857085056">"Scegli un\'app per aggiungere controlli"</string> - <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# controllo aggiunto.}other{# controlli aggiunti.}}"</string> + <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# controllo aggiunto.}many{# controlli aggiunti.}other{# controlli aggiunti.}}"</string> <string name="controls_removed" msgid="3731789252222856959">"Rimosso"</string> <string name="accessibility_control_favorite" msgid="8694362691985545985">"Aggiunto ai preferiti"</string> <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Preferito, posizione <xliff:g id="NUMBER">%d</xliff:g>"</string> @@ -925,7 +925,7 @@ <string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Aggiungi riquadro"</string> <string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Non aggiungerlo"</string> <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Seleziona utente"</string> - <string name="fgs_manager_footer_label" msgid="8276763570622288231">"{count,plural, =1{C\'è # app attiva}other{Ci sono # app attive}}"</string> + <string name="fgs_manager_footer_label" msgid="8276763570622288231">"{count,plural, =1{C\'è # app attiva}many{Ci sono # app attive}other{Ci sono # app attive}}"</string> <string name="fgs_dot_content_description" msgid="2865071539464777240">"Nuove informazioni"</string> <string name="fgs_manager_dialog_title" msgid="5879184257257718677">"App attive"</string> <string name="fgs_manager_dialog_message" msgid="2670045017200730076">"Queste app sono attive e in esecuzione, anche quando non le utilizzi. Questo migliora la loro funzionalità, ma influisce sulla durata della batteria."</string> @@ -955,7 +955,7 @@ <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"La fotocamera è disattivata"</string> <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"Il microfono è disattivato"</string> <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"Fotocamera e microfono non attivi"</string> - <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notifica}other{# notifiche}}"</string> + <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notifica}many{# notifiche}other{# notifiche}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Trasmissione in corso…"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Vuoi interrompere la trasmissione dell\'app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml index 9014544ab9c0..e5e37f5341ef 100644 --- a/packages/SystemUI/res/values-iw/strings.xml +++ b/packages/SystemUI/res/values-iw/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"לא ניתן לזהות את הפנים. יש להשתמש בטביעת אצבע במקום."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"לא ניתן לזהות את הפנים"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"שימוש בטביעת אצבע במקום זאת"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth מחובר."</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"אחוז טעינת הסוללה לא ידוע."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"התבצע חיבור אל <xliff:g id="BLUETOOTH">%s</xliff:g>."</string> @@ -600,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"פועל"</string> <string name="switch_bar_off" msgid="5669805115416379556">"כבוי"</string> <string name="tile_unavailable" msgid="3095879009136616920">"לא זמין"</string> - <string name="tile_disabled" msgid="373212051546573069">"מושבת"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"מידע נוסף"</string> <string name="nav_bar" msgid="4642708685386136807">"סרגל הניווט"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"פריסה"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"סוג נוסף של לחצן שמאלי"</string> @@ -673,8 +671,8 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"חלק מהתכונות מוגבלות כל עוד הטלפון מתקרר.\nיש להקיש כדי להציג מידע נוסף"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"קירור הטלפון ייעשה באופן אוטומטי. ניתן עדיין להשתמש בטלפון, אבל ייתכן שהוא יפעל לאט יותר.\n\nהטלפון יחזור לפעול כרגיל לאחר שיתקרר."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"לצפייה בשלבי הטיפול"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"יש לנתק את המטען"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"יש בעיה עם הטעינה של המכשיר הזה. צריך לנתק את מתאם המתח בזהירות כי הכבל עלול להיות חם."</string> + <string name="high_temp_alarm_title" msgid="8654754369605452169">"ניתוק המכשיר"</string> + <string name="high_temp_alarm_notify_message" msgid="3917622943609118956">"המכשיר שלך מתחמם בקרבת יציאת הטעינה. אם המכשיר מחובר למטען או לאביזר בחיבור USB, צריך לנתק אותו בזהירות כיוון שגם הכבל עלול להיות חם."</string> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"לצפייה בשלבי הטיפול"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"קיצור דרך שמאלי"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"קיצור דרך ימני"</string> diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml index c7b636acec4d..15089a4a804e 100644 --- a/packages/SystemUI/res/values-ja/strings.xml +++ b/packages/SystemUI/res/values-ja/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"顔を認識できません。指紋認証を使用してください。"</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"顔を認識できません"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"指紋認証をお使いください"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetoothに接続済み。"</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"バッテリー残量は不明です。"</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g>に接続しました。"</string> @@ -600,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"ON"</string> <string name="switch_bar_off" msgid="5669805115416379556">"OFF"</string> <string name="tile_unavailable" msgid="3095879009136616920">"使用不可"</string> - <string name="tile_disabled" msgid="373212051546573069">"無効"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"詳細"</string> <string name="nav_bar" msgid="4642708685386136807">"ナビゲーション バー"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"レイアウト"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"その他の左ボタンタイプ"</string> @@ -673,8 +671,8 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"スマートフォンのクールダウン中は一部の機能が制限されます。\nタップして詳細を表示"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"スマートフォンは自動的にクールダウンを行います。その間もスマートフォンを使用できますが、動作が遅くなる可能性があります。\n\nクールダウンが完了すると、通常どおり動作します。"</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"取り扱いに関する手順をご覧ください"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"充電器を電源から外してください"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"このデバイスの充電中に問題が発生しました。電源アダプターを電源から外してください。ケーブルが熱くなっている可能性がありますのでご注意ください。"</string> + <string name="high_temp_alarm_title" msgid="8654754369605452169">"デバイスを電源から外します"</string> + <string name="high_temp_alarm_notify_message" msgid="3917622943609118956">"充電ポートの近くにデバイスを置くと、本体が熱くなります。デバイスが充電器や USB アクセサリに接続されている場合は外してください。ケーブルが熱くなっていることもあるので注意してください。"</string> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"取り扱いに関する手順をご覧ください"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"左ショートカット"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"右ショートカット"</string> diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml index ed1eebb805b3..76033ca32588 100644 --- a/packages/SystemUI/res/values-ka/strings.xml +++ b/packages/SystemUI/res/values-ka/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"სახის ამოცნობა ვერ ხერხდება. სანაცვლოდ თითის ანაბეჭდი გამოიყენეთ."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"სახის ამოცნობა შეუძლებ."</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"გამოიყენეთ თითის ანაბეჭდი"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth დაკავშირებულია."</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"ბატარეის პროცენტული მაჩვენებელი უცნობია."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"დაკავშირებულია <xliff:g id="BLUETOOTH">%s</xliff:g>-თან."</string> @@ -600,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"ჩართული"</string> <string name="switch_bar_off" msgid="5669805115416379556">"გამორთვა"</string> <string name="tile_unavailable" msgid="3095879009136616920">"მიუწვდომელი"</string> - <string name="tile_disabled" msgid="373212051546573069">"გათიშულია"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"შეიტყვეთ მეტი"</string> <string name="nav_bar" msgid="4642708685386136807">"ნავიგაციის ზოლი"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"განლაგება"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"მარცხენა დამატებითი ღილაკის ტიპი"</string> @@ -673,8 +671,8 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"ზოგიერთი ფუნქცია შეზღუდული იქნება, სანამ ტელეფონი გაგრილდება.\nშეეხეთ დამატებითი ინფორმაციის მისაღებად"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"თქვენი ტელეფონი გაგრილებას ავტომატურად შეეცდება. შეგიძლიათ გააგრძელოთ მისით სარგებლობა, თუმცა ტელეფონმა შეიძლება უფრო ნელა იმუშაოს.\n\nგაგრილების შემდგომ ის ჩვეულებრივად იმუშავებს."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"მისაღები ზომების გაცნობა"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"გამოაერთეთ დამტენი"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"ამ მოწყობილობის დატენა ვერ ხერხდება პრობლემის გამო. გამოაერთეთ ელკვების ადაპტერი და გამოიჩინეთ სიფრთხილე, რადგან კაბელი შეიძლებოდა გაცხელებულიყო."</string> + <string name="high_temp_alarm_title" msgid="8654754369605452169">"გამოაერᲗეᲗ Თქვენი მოწყობილობა"</string> + <string name="high_temp_alarm_notify_message" msgid="3917622943609118956">"თქვენი მოწყობილობა ხურდება დამტენის პორტთან ახლოს. თუ ის დაკავშირებულია დამტენთან ან USB აქსესუართან, გამორთეთ იგი და იზრუნეთ, რადგან შესაძლოა კაბელიც გახურებული იყოს."</string> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"მისაღები ზომების გაცნობა"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"მარცხენა მალსახმობი"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"მარჯვენა მალსახმობი"</string> diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml index 44149abed3b0..c44d0ccc55fb 100644 --- a/packages/SystemUI/res/values-kk/strings.xml +++ b/packages/SystemUI/res/values-kk/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Бет танылмады. Орнына саусақ ізін пайдаланыңыз."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"Бет танылмады."</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Орнына саусақ ізін пайдаланыңыз."</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth қосылған."</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Батарея зарядының мөлшері белгісіз."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> қосылған."</string> @@ -423,10 +421,8 @@ <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Субтитр қою"</string> <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"қосу"</string> <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"өшіру"</string> - <!-- no translation found for sound_settings (8874581353127418308) --> - <skip /> - <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) --> - <skip /> + <string name="sound_settings" msgid="8874581353127418308">"Дыбыс және діріл"</string> + <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Параметрлер"</string> <string name="screen_pinning_title" msgid="9058007390337841305">"Қолданба бекітілді"</string> <string name="screen_pinning_description" msgid="8699395373875667743">"Өзіңіз босатқаша ашық тұрады. Босату үшін \"Артқа\" және \"Шолу\" түймелерін басып тұрыңыз."</string> <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Өзіңіз босатқаша ашық тұрады. Босату үшін \"Артқа\" және \"Негізгі бет\" түймелерін басып тұрыңыз"</string> @@ -602,7 +598,8 @@ <string name="switch_bar_on" msgid="1770868129120096114">"Қосулы"</string> <string name="switch_bar_off" msgid="5669805115416379556">"Өшірулі"</string> <string name="tile_unavailable" msgid="3095879009136616920">"Қолжетімді емес"</string> - <string name="tile_disabled" msgid="373212051546573069">"Өшірілген"</string> + <!-- no translation found for accessibility_tile_disabled_by_policy_action_description (6958422730461646926) --> + <skip /> <string name="nav_bar" msgid="4642708685386136807">"Шарлау тақтасы"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"Формат"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Қосымша сол жақ түйме түрі"</string> @@ -675,8 +672,10 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Телефон толық суығанға дейін, кейбір функциялардың жұмысы шектеледі.\nТолығырақ ақпарат үшін түртіңіз."</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"Телефон автоматты түрде суи бастайды. Оны пайдалана бере аласыз, бірақ ол баяуырақ жұмыс істеуі мүмкін.\n\nТелефон суығаннан кейін, оның жұмысы қалпына келеді."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Пайдалану нұсқаулығын қараңыз"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Зарядтағышты ажыратыңыз"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"Құрылғыны зарядтау кезінде ақау шықты. Қуат адаптерін ажыратыңыз. Кабель ыстық болуы мүмкін, абай болыңыз."</string> + <!-- no translation found for high_temp_alarm_title (8654754369605452169) --> + <skip /> + <!-- no translation found for high_temp_alarm_notify_message (3917622943609118956) --> + <skip /> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"Пайдалану нұсқаулығын қараңыз"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Сол жақ таңбаша"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"Оң жақ таңбаша"</string> diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml index 1d3a1d490716..e7173ce0cb53 100644 --- a/packages/SystemUI/res/values-km/strings.xml +++ b/packages/SystemUI/res/values-km/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"មិនអាចសម្គាល់មុខបានទេ។ សូមប្រើស្នាមម្រាមដៃជំនួសវិញ។"</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"មិនអាចសម្គាល់មុខបានទេ"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"ប្រើស្នាមម្រាមដៃជំនួសវិញ"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"បានតភ្ជាប់ប៊្លូធូស។"</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"មិនដឹងអំពីភាគរយថ្មទេ។"</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"បានភ្ជាប់ទៅ <xliff:g id="BLUETOOTH">%s</xliff:g> ។"</string> @@ -423,10 +421,8 @@ <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"ការដាក់ត្រួតគ្នាលើអក្សររត់"</string> <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"បើក"</string> <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"បិទ"</string> - <!-- no translation found for sound_settings (8874581353127418308) --> - <skip /> - <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) --> - <skip /> + <string name="sound_settings" msgid="8874581353127418308">"សំឡេង និងការញ័រ"</string> + <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"ការកំណត់"</string> <string name="screen_pinning_title" msgid="9058007390337841305">"កម្មវិធីត្រូវបានខ្ទាស់"</string> <string name="screen_pinning_description" msgid="8699395373875667743">"វានឹងនៅតែបង្ហាញ រហូតទាល់តែអ្នកដកការដៅ។ សូមសង្កត់ប៊ូតុងថយក្រោយ និងប៊ូតុងទិដ្ឋភាពរួមឲ្យជាប់ ដើម្បីដកការដៅ។"</string> <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"វានឹងនៅតែបង្ហាញ រហូតទាល់តែអ្នកដកការដៅ។ សូមចុចប៊ូតុងថយក្រោយ និងប៊ូតុងទំព័រដើមឱ្យជាប់ ដើម្បីដកការដៅ។"</string> @@ -602,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"បើក"</string> <string name="switch_bar_off" msgid="5669805115416379556">"បិទ"</string> <string name="tile_unavailable" msgid="3095879009136616920">"មិនអាចប្រើបាន"</string> - <string name="tile_disabled" msgid="373212051546573069">"បានបិទ"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"ស្វែងយល់បន្ថែម"</string> <string name="nav_bar" msgid="4642708685386136807">"របាររុករក"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"ប្លង់"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"ប្រភេទប៊ូតុងខាងឆ្វេងបន្ថែម"</string> @@ -675,8 +671,10 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"មុខងារមួយចំនួននឹងមិនអាចប្រើបានពេញលេញនោះទេ ខណៈពេលដែលទូរសព្ទកំពុងបញ្ចុះកម្ដៅ។\nសូមចុចដើម្បីទទួលបានព័ត៌មានបន្ថែម"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"ទូរសព្ទរបស់អ្នកនឹងព្យាយាមបញ្ចុះកម្តៅដោយស្វ័យប្រវត្តិ។ អ្នកនៅតែអាចប្រើទូរសព្ទរបស់អ្នកបានដដែល ប៉ុន្តែវានឹងដំណើរការយឺតជាងមុន។\n\nបន្ទាប់ពីទូរសព្ទរបស់អ្នកត្រជាក់ជាងមុនហើយ វានឹងដំណើរការដូចធម្មតា។"</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"មើលជំហានថែទាំ"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"ផ្ដាច់ឆ្នាំងសាក"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"មានបញ្ហាក្នុងការសាកថ្មឧបករណ៍នេះ។ សូមផ្ដាច់ឆ្នាំងសាក ហើយប្រុងប្រយ័ត្ន ដោយសារខ្សែអាចមានកម្ដៅក្ដៅ។"</string> + <!-- no translation found for high_temp_alarm_title (8654754369605452169) --> + <skip /> + <!-- no translation found for high_temp_alarm_notify_message (3917622943609118956) --> + <skip /> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"មើលជំហានថែទាំ"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"ផ្លូវកាត់ខាងឆ្វេង"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"ផ្លូវកាត់ខាងស្តាំ"</string> diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml index f02830b74efb..8d270e3fa9bb 100644 --- a/packages/SystemUI/res/values-kn/strings.xml +++ b/packages/SystemUI/res/values-kn/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"ಮುಖ ಗುರುತಿಸಲಾಗುತ್ತಿಲ್ಲ ಬದಲಿಗೆ ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಬಳಸಿ."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"ಮುಖ ಗುರುತಿಸಲಾಗುತ್ತಿಲ್ಲ"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"ಬದಲಿಗೆ ಫಿಂಗರ್ಪ್ರಿಂಟ್ ಬಳಸಿ"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"ಬ್ಲೂಟೂತ್ ಸಂಪರ್ಕಗೊಂಡಿದೆ."</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"ಬ್ಯಾಟರಿ ಶೇಕಡಾವಾರು ತಿಳಿದಿಲ್ಲ."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> ಗೆ ಸಂಪರ್ಕಪಡಿಸಲಾಗಿದೆ."</string> @@ -423,10 +421,8 @@ <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"ಶೀರ್ಷಿಕೆಗಳ ಓವರ್ಲೇ"</string> <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"ಸಕ್ರಿಯಗೊಳಿಸಿ"</string> <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಿ"</string> - <!-- no translation found for sound_settings (8874581353127418308) --> - <skip /> - <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) --> - <skip /> + <string name="sound_settings" msgid="8874581353127418308">"ಧ್ವನಿ & ವೈಬ್ರೇಷನ್"</string> + <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"ಸೆಟ್ಟಿಂಗ್ಗಳು"</string> <string name="screen_pinning_title" msgid="9058007390337841305">"ಆ್ಯಪ್ ಅನ್ನು ಪಿನ್ ಮಾಡಲಾಗಿದೆ"</string> <string name="screen_pinning_description" msgid="8699395373875667743">"ನೀವು ಅನ್ಪಿನ್ ಮಾಡುವವರೆಗೆ ಅದನ್ನು ವೀಕ್ಷಣೆಯಲ್ಲಿಡುತ್ತದೆ. ಸ್ಪರ್ಶಿಸಿ ಮತ್ತು ಹಿಡಿದುಕೊಳ್ಳಿ ಹಾಗೂ ಅನ್ಪಿನ್ ಮಾಡಲು ಅವಲೋಕಿಸಿ."</string> <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"ನೀವು ಅನ್ಪಿನ್ ಮಾಡುವವರೆಗೆ ಅದನ್ನು ವೀಕ್ಷಣೆಯಲ್ಲಿಡುತ್ತದೆ. ಸ್ಪರ್ಶಿಸಿ ಮತ್ತು ಹಿಡಿದುಕೊಳ್ಳಿ ಹಾಗೂ ಅನ್ಪಿನ್ ಮಾಡಲು ಮುಖಪುಟಕ್ಕೆ ಹಿಂತಿರುಗಿ."</string> @@ -602,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"ಆನ್"</string> <string name="switch_bar_off" msgid="5669805115416379556">"ಆಫ್"</string> <string name="tile_unavailable" msgid="3095879009136616920">"ಲಭ್ಯವಿಲ್ಲ"</string> - <string name="tile_disabled" msgid="373212051546573069">"ನಿಷ್ಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"ಇನ್ನಷ್ಟು ತಿಳಿಯಿರಿ"</string> <string name="nav_bar" msgid="4642708685386136807">"ನ್ಯಾವಿಗೇಷನ್ ಬಾರ್"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"ಲೇಔಟ್"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"ಹೆಚ್ಚುವರಿ ಎಡ ಬಟನ್ ವಿಧ"</string> @@ -675,8 +671,8 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"ಫೋನ್ ತಣ್ಣಗಾಗುವವರೆಗೂ ಕೆಲವು ವೈಶಿಷ್ಟ್ಯಗಳನ್ನು ಸೀಮಿತಗೊಳಿಸಲಾಗುತ್ತದೆ\nಇನ್ನಷ್ಟು ಮಾಹಿತಿಗಾಗಿ ಟ್ಯಾಪ್ ಮಾಡಿ"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"ನಿಮ್ಮ ಫೋನ್ ಸ್ವಯಂಚಾಲಿತವಾಗಿ ತಣ್ಣಗಾಗಲು ಪ್ರಯತ್ನಿಸುತ್ತದೆ. ನಿಮ್ಮ ಫೋನ್ ಅನ್ನು ನೀವು ಈಗಲೂ ಬಳಸಬಹುದಾಗಿರುತ್ತದೆ, ಆದರೆ ಇದು ನಿಧಾನವಾಗಿರಬಹುದು.\n\nಒಮ್ಮೆ ನಿಮ್ಮ ಫೋನ್ ತಣ್ಣಗಾದ ನಂತರ ಇದು ಸಾಮಾನ್ಯ ರೀತಿಯಲ್ಲಿ ಕಾರ್ಯನಿರ್ವಹಿಸುತ್ತದೆ."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"ಕಾಳಜಿಯ ಹಂತಗಳನ್ನು ವೀಕ್ಷಿಸಿ"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"ಚಾರ್ಜರ್ ಅನ್ಪ್ಲಗ್ ಮಾಡಿ"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"ಈ ಸಾಧನವನ್ನು ಚಾರ್ಜ್ ಮಾಡುತ್ತಿರುವಾಗ ಸಮಸ್ಯೆ ಎದುರಾಗಿದೆ. ಪವರ್ ಅಡಾಪ್ಟರ್ ಅನ್ನು ಅನ್ಪ್ಲಗ್ ಮಾಡಿ ಮತ್ತು ಕೇಬಲ್ ಬೆಚ್ಚಗಿರಬೇಕೆಂದು ಜಾಗ್ರತೆ ವಹಿಸಿ."</string> + <string name="high_temp_alarm_title" msgid="8654754369605452169">"ನಿಮ್ಮ ಸಾಧನವನ್ನು ಅನ್ಪ್ಲಗ್ ಮಾಡಿ"</string> + <string name="high_temp_alarm_notify_message" msgid="3917622943609118956">"ಚಾರ್ಜಿಂಗ್ ಪೋರ್ಟ್ ಸಮೀಪದಲ್ಲಿ ನಿಮ್ಮ ಸಾಧನವು ಬಿಸಿಯಾಗುತ್ತಿದೆ. ಅದನ್ನು ಚಾರ್ಜರ್ ಅಥವಾ USB ಪರಿಕರಕ್ಕೆ ಕನೆಕ್ಟ್ ಮಾಡಿದ್ದರೆ, ಅದನ್ನು ಅನ್ಪ್ಲಗ್ ಮಾಡಿ ಹಾಗೂ ಕೇಬಲ್ ಕೂಡ ಬಿಸಿಯಾಗಿರಬಹುದು ಆದ್ದರಿಂದ ಎಚ್ಚರಿಕೆ ವಹಿಸಿ."</string> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"ಕಾಳಜಿ ಹಂತಗಳನ್ನು ನೋಡಿ"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"ಎಡ ಶಾರ್ಟ್ಕಟ್"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"ಬಲ ಶಾರ್ಟ್ಕಟ್"</string> diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml index ebf0db2d8499..e8578df7dc43 100644 --- a/packages/SystemUI/res/values-ko/strings.xml +++ b/packages/SystemUI/res/values-ko/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"얼굴을 인식할 수 없습니다. 대신 지문을 사용하세요."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"얼굴을 인식할 수 없습니다."</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"대신 지문을 사용하세요."</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"블루투스가 연결되었습니다."</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"배터리 잔량을 알 수 없습니다."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g>에 연결되었습니다."</string> @@ -285,7 +283,7 @@ <string name="quick_settings_screen_record_start" msgid="1574725369331638985">"시작"</string> <string name="quick_settings_screen_record_stop" msgid="8087348522976412119">"중지"</string> <string name="quick_settings_onehanded_label" msgid="2416537930246274991">"한 손 사용 모드"</string> - <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"기기 마이크를 차단 해제하시겠습니까?"</string> + <string name="sensor_privacy_start_use_mic_dialog_title" msgid="563796653825944944">"기기 마이크를 &#173;차단 해제하시겠습니까?"</string> <string name="sensor_privacy_start_use_camera_dialog_title" msgid="8807639852654305227">"기기 카메라를 차단 해제하시겠습니까?"</string> <string name="sensor_privacy_start_use_mic_camera_dialog_title" msgid="4316471859905020023">"기기 카메라 및 마이크를 차단 해제하시겠습니까?"</string> <string name="sensor_privacy_start_use_mic_dialog_content" msgid="1624701280680913717">"마이크를 사용할 수 있는 모든 앱 및 서비스에 대해 액세스가 차단 해제됩니다."</string> @@ -423,10 +421,8 @@ <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"캡션 오버레이"</string> <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"사용"</string> <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"사용 중지"</string> - <!-- no translation found for sound_settings (8874581353127418308) --> - <skip /> - <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) --> - <skip /> + <string name="sound_settings" msgid="8874581353127418308">"소리 및 진동"</string> + <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"설정"</string> <string name="screen_pinning_title" msgid="9058007390337841305">"앱 고정됨"</string> <string name="screen_pinning_description" msgid="8699395373875667743">"고정 해제할 때까지 계속 표시됩니다. 고정 해제하려면 뒤로 및 최근 사용을 길게 터치하세요."</string> <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"고정 해제할 때까지 계속 표시됩니다. 고정 해제하려면 뒤로 및 홈을 길게 터치하세요."</string> @@ -602,7 +598,8 @@ <string name="switch_bar_on" msgid="1770868129120096114">"사용"</string> <string name="switch_bar_off" msgid="5669805115416379556">"사용 안함"</string> <string name="tile_unavailable" msgid="3095879009136616920">"사용할 수 없음"</string> - <string name="tile_disabled" msgid="373212051546573069">"사용 안함"</string> + <!-- no translation found for accessibility_tile_disabled_by_policy_action_description (6958422730461646926) --> + <skip /> <string name="nav_bar" msgid="4642708685386136807">"탐색 메뉴"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"레이아웃"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"추가 왼쪽 버튼 유형"</string> @@ -675,8 +672,10 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"휴대전화 온도를 낮추는 동안 일부 기능이 제한됩니다.\n자세히 알아보려면 탭하세요."</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"휴대전화 온도를 자동으로 낮추려고 시도합니다. 휴대전화를 계속 사용할 수는 있지만 작동이 느려질 수도 있습니다.\n\n휴대전화 온도가 낮아지면 정상적으로 작동됩니다."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"해결 방법 확인하기"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"충전기를 연결 해제하세요"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"기기를 충전하는 중에 문제가 발생했습니다. 케이블이 뜨거울 수 있으므로 주의하여 전원 어댑터를 분리하세요."</string> + <!-- no translation found for high_temp_alarm_title (8654754369605452169) --> + <skip /> + <!-- no translation found for high_temp_alarm_notify_message (3917622943609118956) --> + <skip /> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"취해야 할 조치 확인"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"왼쪽 바로가기"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"오른쪽 바로가기"</string> diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml index aa7a67fa6a7f..9bba2da460a8 100644 --- a/packages/SystemUI/res/values-ky/strings.xml +++ b/packages/SystemUI/res/values-ky/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Жүз таанылбай жатат. Манжа изин колдонуңуз."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"Жүз таанылбай жатат"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Манжа изин колдонуңуз"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth байланышта"</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Батарея кубатынын деңгээли белгисиз."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> менен туташкан."</string> @@ -423,10 +421,8 @@ <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Коштомо жазуулардын үстүнө коюу"</string> <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"иштетүү"</string> <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"өчүрүү"</string> - <!-- no translation found for sound_settings (8874581353127418308) --> - <skip /> - <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) --> - <skip /> + <string name="sound_settings" msgid="8874581353127418308">"Үн жана дирилдөө"</string> + <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Параметрлер"</string> <string name="screen_pinning_title" msgid="9058007390337841305">"Колдонмо кадалды"</string> <string name="screen_pinning_description" msgid="8699395373875667743">"Ал бошотулмайынча көрүнө берет. Бошотуу үчүн \"Артка\" жана \"Назар\" баскычтарын басып, кармап туруңуз."</string> <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Ал бошотулмайынча көрүнө берет. Бошотуу үчүн, \"Артка\" жана \"Башкы бет\" баскычтарын басып, кармап туруңуз."</string> @@ -602,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"Күйүк"</string> <string name="switch_bar_off" msgid="5669805115416379556">"Өчүк"</string> <string name="tile_unavailable" msgid="3095879009136616920">"Жеткиликсиз"</string> - <string name="tile_disabled" msgid="373212051546573069">"Өчүрүлгөн"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"кеңири маалымат"</string> <string name="nav_bar" msgid="4642708685386136807">"Чабыттоо тилкеси"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"Калып"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Сол жактагы кошумча баскычтын түрү"</string> @@ -675,8 +671,10 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Телефон сууганча айрым элементтердин иши чектелген.\nКеңири маалымат алуу үчүн таптап коюңуз"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"Телефонуңуз автоматтык түрдө сууйт. Аны колдоно берсеңиз болот, бирок ал жайыраак иштеп калат.\n\nТелефонуңуз суугандан кийин адаттагыдай эле иштеп баштайт."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Тейлөө кадамдарын көрүңүз"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Кубаттагычты сууруңуз"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"Бул түзмөктү кубаттоодо маселе келип чыкты. Кабель ысып кетиши мүмкүн, андыктан кубаттагыч адаптерин сууруп коюңуз."</string> + <!-- no translation found for high_temp_alarm_title (8654754369605452169) --> + <skip /> + <!-- no translation found for high_temp_alarm_notify_message (3917622943609118956) --> + <skip /> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"Тейлөө кадамдарын көрүңүз"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Сол жактагы кыска жол"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"Оң жактагы кыска жол"</string> diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml index 7d09542159ed..c2896090e93c 100644 --- a/packages/SystemUI/res/values-lo/strings.xml +++ b/packages/SystemUI/res/values-lo/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"ບໍ່ສາມາດຈຳແນກໜ້າໄດ້. ກະລຸນາໃຊ້ລາຍນິ້ວມືແທນ."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"ບໍ່ສາມາດຈຳແນກໃບໜ້າໄດ້"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"ກະລຸນາໃຊ້ລາຍນິ້ວມືແທນ"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"ເຊື່ອມຕໍ່ Bluetooth ແລ້ວ."</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"ບໍ່ຮູ້ເປີເຊັນແບັດເຕີຣີ."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"ເຊື່ອມຕໍ່ຫາ <xliff:g id="BLUETOOTH">%s</xliff:g> ແລ້ວ."</string> @@ -423,10 +421,8 @@ <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"ຄຳບັນຍາຍແບບວາງທັບ"</string> <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"ເປີດນຳໃຊ້"</string> <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"ປິດນຳໃຊ້"</string> - <!-- no translation found for sound_settings (8874581353127418308) --> - <skip /> - <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) --> - <skip /> + <string name="sound_settings" msgid="8874581353127418308">"ສຽງ ແລະ ການສັ່ນເຕືອນ"</string> + <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"ການຕັ້ງຄ່າ"</string> <string name="screen_pinning_title" msgid="9058007390337841305">"ແອັບຖືກປັກໝຸດແລ້ວ"</string> <string name="screen_pinning_description" msgid="8699395373875667743">"ນີ້ຈະສະແດງມັນໃນໜ້າຈໍຈົນກວ່າທ່ານຈະເຊົາປັກມຸດ. ໃຫ້ແຕະປຸ່ມກັບຄືນ ແລະ ປຸ່ມພາບຮວມຄ້າງໄວ້ເພື່ອຍົກເລີກການປັກມຸດ."</string> <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"ນີ້ຈະສະແດງມັນໃນໜ້າຈໍຈົນກວ່າທ່ານຈະເຊົາປັກໝຸດ. ໃຫ້ແຕະປຸ່ມກັບຄືນ ແລະ ປຸ່ມພາບຮວມຄ້າງໄວ້ເພື່ອຍົກເລີກການປັກໝຸດ."</string> @@ -602,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"ເປີດ"</string> <string name="switch_bar_off" msgid="5669805115416379556">"ປິດ"</string> <string name="tile_unavailable" msgid="3095879009136616920">"ບໍ່ສາມາດໃຊ້ໄດ້"</string> - <string name="tile_disabled" msgid="373212051546573069">"ປິດການນຳໃຊ້ແລ້ວ"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"ສຶກສາເພີ່ມເຕີມ"</string> <string name="nav_bar" msgid="4642708685386136807">"ແຖບນຳທາງ"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"ຮູບແບບ"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"ປະເພດປຸ່ມຊ້າຍພິເສດ"</string> @@ -675,8 +671,10 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"ຄຸນສົມບັດບາງຢ່າງຖືກຈຳກັດໄວ້ໃນເວລາຫຼຸດອຸນຫະພູມຂອງໂທລະສັບ.\nແຕະເພື່ອເບິ່ງຂໍ້ມູນເພີ່ມເຕີມ"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"ໂທລະສັບຂອງທ່ານຈະພະຍາຍາມລົດອຸນຫະພູມລົງ. ທ່ານຍັງຄົງສາມາດໃຊ້ໂທລະສັບຂອງທ່ານໄດ້ຢູ່, ແຕ່ມັນຈະເຮັດວຽກຊ້າລົງ.\n\nເມື່ອໂທລະສັບຂອງທ່ານບໍ່ຮ້ອນຫຼາຍແລ້ວ, ມັນຈະກັບມາເຮັດວຽກຕາມປົກກະຕິ."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"ເບິ່ງຂັ້ນຕອນການເບິ່ງແຍງ"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"ຖອດສາຍສາກອອກ"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"ເກີດບັນຫາໃນການສາກໄຟອຸປະກອນນີ້. ກະລຸນາຖອດສາຍສາກອອກ ແລະ ລະວັງເນື່ອງຈາກສາຍອາດຈະຍັງອຸ່ນຢູ່."</string> + <!-- no translation found for high_temp_alarm_title (8654754369605452169) --> + <skip /> + <!-- no translation found for high_temp_alarm_notify_message (3917622943609118956) --> + <skip /> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"ເບິ່ງຂັ້ນຕອນການເບິ່ງແຍງ"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"ປຸ່ມລັດຊ້າຍ"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"ປຸ່ມລັດຂວາ"</string> diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml index 34a35b75ad75..fd9c7cc7ceb6 100644 --- a/packages/SystemUI/res/values-lt/strings.xml +++ b/packages/SystemUI/res/values-lt/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Veidas neatpažintas. Naudokite kontrolinį kodą."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"Veidas neatpažintas"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Naudoti piršto antspaudą"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"„Bluetooth“ prijungtas."</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Akumuliatoriaus energija procentais nežinoma."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Prisijungta prie „<xliff:g id="BLUETOOTH">%s</xliff:g>“."</string> @@ -600,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"Įjungta"</string> <string name="switch_bar_off" msgid="5669805115416379556">"Išjungta"</string> <string name="tile_unavailable" msgid="3095879009136616920">"Nepasiekiama"</string> - <string name="tile_disabled" msgid="373212051546573069">"Išjungta"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"sužinoti daugiau"</string> <string name="nav_bar" msgid="4642708685386136807">"Naršymo juosta"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"Išdėstymas"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Papildomo mygtuko kairėje tipas"</string> @@ -673,8 +671,8 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Kai kurios funkcijos gali neveikti, kol telefonas vėsta.\nPalietę gausite daugiau informacijos"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"Telefonas automatiškai bandys atvėsti. Telefoną vis tiek galėsite naudoti, tačiau jis gali veikti lėčiau.\n\nKai telefonas atvės, jis veiks įprastai."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Žr. priežiūros veiksmus"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Atjunkite kroviklį"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"Įkraunant šį įrenginį iškilo problema. Atjunkite maitinimo adapterį. Būkite atsargūs, nes laidas gali būti įkaitęs."</string> + <string name="high_temp_alarm_title" msgid="8654754369605452169">"Atjunkite įrenginį"</string> + <string name="high_temp_alarm_notify_message" msgid="3917622943609118956">"Įrenginys kaista šalia įkrovimo prievado. Jei jis prijungtas prie kroviklio ar USB priedo, atjunkite jį ir patikrinkite, nes laidas taip pat gali būti įkaitęs."</string> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"Žr. priežiūros veiksmus"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Spartusis klavišas kairėje"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"Spartusis klavišas dešinėje"</string> diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml index 51d724c646d8..e9cf36463039 100644 --- a/packages/SystemUI/res/values-lv/strings.xml +++ b/packages/SystemUI/res/values-lv/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Nevar atpazīt seju. Lietojiet pirksta nospiedumu."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"Nevar atpazīt seju"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Lietot pirksta nospiedumu"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth savienojums ir izveidots."</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Akumulatora uzlādes līmenis procentos nav zināms."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Ir izveidots savienojum ar <xliff:g id="BLUETOOTH">%s</xliff:g>."</string> @@ -423,10 +421,8 @@ <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Subtitri pārklājas"</string> <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"iespējot"</string> <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"atspējot"</string> - <!-- no translation found for sound_settings (8874581353127418308) --> - <skip /> - <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) --> - <skip /> + <string name="sound_settings" msgid="8874581353127418308">"Skaņa un vibrācija"</string> + <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Iestatījumi"</string> <string name="screen_pinning_title" msgid="9058007390337841305">"Lietotne ir piesprausta"</string> <string name="screen_pinning_description" msgid="8699395373875667743">"Šādi tas būs redzams līdz brīdim, kad to atspraudīsiet. Lai atspraustu, pieskarieties pogām Atpakaļ un Pārskats un turiet tās."</string> <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Šādi tas būs redzams līdz brīdim, kad to atspraudīsiet. Lai atspraustu, pieskarieties pogām “Atpakaļ” un “Sākums” un turiet tās."</string> @@ -602,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"Ieslēgts"</string> <string name="switch_bar_off" msgid="5669805115416379556">"Izslēgts"</string> <string name="tile_unavailable" msgid="3095879009136616920">"Nav pieejams"</string> - <string name="tile_disabled" msgid="373212051546573069">"Atspējots"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"uzzinātu vairāk"</string> <string name="nav_bar" msgid="4642708685386136807">"Navigācijas josla"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"Izkārtojums"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Kreisās puses papildu pogas veids"</string> @@ -675,8 +671,10 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Dažas funkcijas ir ierobežotas, kamēr notiek tālruņa atdzišana.\nPieskarieties, lai uzzinātu vairāk."</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"Jūsu tālrunis automātiski mēģinās atdzist. Jūs joprojām varat izmantot tālruni, taču tas, iespējams, darbosies lēnāk.\n\nTiklīdz tālrunis būs atdzisis, tas darbosies normāli."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Skatīt apkopes norādījumus"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Lādētāja atvienošana"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"Uzlādējot šo ierīci, radās problēma. Atvienojiet strāvas adapteri. Esiet uzmanīgs — vads var būt uzsilis."</string> + <!-- no translation found for high_temp_alarm_title (8654754369605452169) --> + <skip /> + <!-- no translation found for high_temp_alarm_notify_message (3917622943609118956) --> + <skip /> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"Skatīt apkopes norādījumus"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Saīsne kreisajā pusē"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"Saīsne labajā pusē"</string> diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml index 0032dffad1f8..8b8753ea4133 100644 --- a/packages/SystemUI/res/values-mk/strings.xml +++ b/packages/SystemUI/res/values-mk/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Не се препознава ликот. Користете отпечаток."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"Не се препознава ликот"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Користи отпечаток"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth е поврзан."</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Процентот на батеријата е непознат."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Поврзано со <xliff:g id="BLUETOOTH">%s</xliff:g>."</string> @@ -600,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"Вклучено"</string> <string name="switch_bar_off" msgid="5669805115416379556">"Исклучено"</string> <string name="tile_unavailable" msgid="3095879009136616920">"Недостапно"</string> - <string name="tile_disabled" msgid="373212051546573069">"Оневозможено"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"дознајте повеќе"</string> <string name="nav_bar" msgid="4642708685386136807">"Лента за навигација"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"Распоред"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Тип дополнително лево копче"</string> @@ -673,8 +671,8 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Некои функции се ограничени додека телефонот се лади.\nДопрете за повеќе информации"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"Телефонот автоматски ќе се обиде да се олади. Вие сепак ќе може да го користите, но тој може да работи побавно.\n\nОткако ќе се олади, ќе работи нормално."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Прикажи ги чекорите за грижа за уредот"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Исклучете го полначот"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"Има проблем со полнењето на уредов. Исклучете го адаптерот за напојување и внимавајте зошто кабелот може да е топол."</string> + <string name="high_temp_alarm_title" msgid="8654754369605452169">"Исклучете го уредот од кабел"</string> + <string name="high_temp_alarm_notify_message" msgid="3917622943609118956">"Вашиот уред се загрева во близина на портата за полнење. Ако е поврзан со полнач или USB-додаток, исклучете го од него и внимавајте бидејќи кабелот може да е топол."</string> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"Прикажи ги чекорите за грижа за уредот"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Лева кратенка"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"Десна кратенка"</string> diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml index 325589e22342..0fe68855eee4 100644 --- a/packages/SystemUI/res/values-ml/strings.xml +++ b/packages/SystemUI/res/values-ml/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"മുഖം തിരിച്ചറിയാനായില്ല. പകരം ഫിംഗർപ്രിന്റ് ഉപയോഗിക്കൂ."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"മുഖം തിരിച്ചറിയാനാകുന്നില്ല"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"പകരം ഫിംഗർപ്രിന്റ് ഉപയോഗിക്കൂ"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"ബ്ലൂടൂത്ത് കണക്റ്റുചെയ്തു."</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"ബാറ്ററി ശതമാനം അജ്ഞാതമാണ്."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> എന്നതിലേക്ക് കണക്റ്റുചെയ്തു."</string> @@ -423,10 +421,8 @@ <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"അടിക്കുറിപ്പുകൾ മുകളിൽ വയ്ക്കുക"</string> <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"പ്രവർത്തനക്ഷമമാക്കുക"</string> <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"പ്രവർത്തനരഹിതമാക്കുക"</string> - <!-- no translation found for sound_settings (8874581353127418308) --> - <skip /> - <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) --> - <skip /> + <string name="sound_settings" msgid="8874581353127418308">"ശബ്ദവും വൈബ്രേഷനും"</string> + <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"ക്രമീകരണം"</string> <string name="screen_pinning_title" msgid="9058007390337841305">"ആപ്പ് പിൻ ചെയ്തു"</string> <string name="screen_pinning_description" msgid="8699395373875667743">"നിങ്ങൾ അൺപിൻ ചെയ്യുന്നതുവരെ ഇത് കാണുന്ന വിധത്തിൽ നിലനിർത്തും. അൺപിൻ ചെയ്യാൻ \'തിരികെ\', \'ചുരുക്കവിവരണം\' എന്നിവ സ്പർശിച്ച് പിടിക്കുക."</string> <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"നിങ്ങൾ അൺപിൻ ചെയ്യുന്നതുവരെ ഇത് കാണുന്ന വിധത്തിൽ നിലനിർത്തും. അൺപിൻ ചെയ്യാൻ \'തിരികെ പോവുക\', \'ഹോം\' ബട്ടണുകൾ സ്പർശിച്ച് പിടിക്കുക."</string> @@ -602,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"ഓൺ"</string> <string name="switch_bar_off" msgid="5669805115416379556">"ഓഫ്"</string> <string name="tile_unavailable" msgid="3095879009136616920">"ലഭ്യമല്ല"</string> - <string name="tile_disabled" msgid="373212051546573069">"പ്രവർത്തനരഹിതമാക്കി"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"കൂടുതലറിയുക"</string> <string name="nav_bar" msgid="4642708685386136807">"നാവിഗേഷൻ ബാർ"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"ലേഔട്ട്"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"അധിക ഇടത് ബട്ടൺ തരം"</string> @@ -675,8 +671,10 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"ഫോൺ തണുത്തുകൊണ്ടിരിക്കുമ്പോൾ ചില ഫീച്ചറുകൾ പരിമിതപ്പെടുത്തപ്പെടും.\nകൂടുതൽ വിവരങ്ങൾക്ക് ടാപ്പ് ചെയ്യുക"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"നിങ്ങളുടെ ഫോൺ സ്വയമേവ തണുക്കാൻ ശ്രമിക്കും. നിങ്ങൾക്ക് അപ്പോഴും ഫോൺ ഉപയോഗിക്കാമെങ്കിലും പ്രവർത്തനം മന്ദഗതിയിലായിരിക്കും.\n\nതണുത്തുകഴിഞ്ഞാൽ, ഫോൺ സാധാരണ ഗതിയിൽ പ്രവർത്തിക്കും."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"പരിപാലന നിർദ്ദേശങ്ങൾ കാണുക"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"ചാർജർ അൺപ്ലഗ് ചെയ്യുക"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"ഈ ഉപകരണം ചാർജ് ചെയ്യുന്നതിൽ തടസ്സമുണ്ട്. പവർ അഡാപ്റ്റർ അൺപ്ലഗ് ചെയ്യുക, കേബിളിന് ചൂടുണ്ടായിരിക്കുമെന്നതിനാൽ ശ്രദ്ധിക്കണം."</string> + <!-- no translation found for high_temp_alarm_title (8654754369605452169) --> + <skip /> + <!-- no translation found for high_temp_alarm_notify_message (3917622943609118956) --> + <skip /> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"മുൻകരുതൽ നടപടികൾ കാണുക"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"ഇടത് കുറുക്കുവഴി"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"വലത് കുറുക്കുവഴി"</string> diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml index 5b2dd37c6919..985a0e60e1f4 100644 --- a/packages/SystemUI/res/values-mn/strings.xml +++ b/packages/SystemUI/res/values-mn/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Царай таних боломжгүй. Оронд нь хурууны хээ ашигла"</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"Царайг танихгүй байна"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Оронд нь хурууны хээ ашиглах"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth холбогдсон."</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Батарейн хувь тодорхойгүй байна."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g>-тай холбогдсон."</string> @@ -600,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"Идэвхтэй"</string> <string name="switch_bar_off" msgid="5669805115416379556">"Идэвхгүй"</string> <string name="tile_unavailable" msgid="3095879009136616920">"Боломжгүй"</string> - <string name="tile_disabled" msgid="373212051546573069">"Идэвхгүй болгосон"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"нэмэлт мэдээлэл авах"</string> <string name="nav_bar" msgid="4642708685386136807">"Навигацын самбар"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"Бүдүүвч"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Нэмэлт зүүн товчлуураар шивэх"</string> @@ -673,8 +671,8 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Утсыг хөрөх үед зарим онцлогийг хязгаарлана.\nДэлгэрэнгүй мэдээлэл авах бол товшино уу"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"Таны утас автоматаар хөрөх болно. Та утсаа ашиглаж болох хэдий ч удаан ажиллаж болзошгүй.\n\nТаны утас хөрсний дараагаар хэвийн ажиллана."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Хянамж болгоомжийн алхмыг харах"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Цэнэглэгчийг салгана уу"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"Энэ төхөөрөмжийг цэнэглэхэд асуудал гарлаа. Тэжээлийн залгуурыг салгана уу. Кабель халсан байж болзошгүй тул болгоомжтой байгаарай."</string> + <string name="high_temp_alarm_title" msgid="8654754369605452169">"Төхөөрөмжөө салгана уу"</string> + <string name="high_temp_alarm_notify_message" msgid="3917622943609118956">"Таны төхөөрөмж цэнэглэх портын ойролцоо халж байна. Хэрэв төхөөрөмжийг цэнэглэгч эсвэл USB дагалдах хэрэгсэлд холбосон бол төхөөрөмжийг салгаж, кабель нь халуун байж болзошгүй тул болгоомжтой байгаарай."</string> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"Хянамж болгоомжийн алхмыг харна уу"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Зүүн товчлол"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"Баруун товчлол"</string> diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml index b53641bcaf63..e82548de9300 100644 --- a/packages/SystemUI/res/values-mr/strings.xml +++ b/packages/SystemUI/res/values-mr/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"चेहरा ओळखू शकत नाही. त्याऐवजी फिंगरप्रिंट वापरा."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"चेहरा ओळखू शकत नाही"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"त्याऐवजी फिंगरप्रिंट वापरा"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"ब्लूटूथ कनेक्ट केले."</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"बॅटरीच्या चार्जिंगची टक्केवारी माहित नाही."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> शी कनेक्ट केले."</string> @@ -600,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"सुरू"</string> <string name="switch_bar_off" msgid="5669805115416379556">"बंद"</string> <string name="tile_unavailable" msgid="3095879009136616920">"उपलब्ध नाही"</string> - <string name="tile_disabled" msgid="373212051546573069">"बंद केली"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"अधिक जाणून घ्या"</string> <string name="nav_bar" msgid="4642708685386136807">"नॅव्हिगेशन बार"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"लेआउट"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"अतिरिक्त डाव्या बटणाचा प्रकार"</string> @@ -673,8 +671,10 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"फोन थंड होईपर्यंत काही वैशिष्ट्ये मर्यादित केली.\nअधिक माहितीसाठी टॅप करा"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"तुमचा फोन स्वयंचलितपणे थंड होईल. तुम्ही अद्यापही तुमचा फोन वापरू शकता परंतु तो कदाचित धीमेपणे कार्य करेल.\n\nतुमचा फोन एकदा थंड झाला की, तो सामान्यपणे कार्य करेल."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"काय काळजी घ्यावी ते पहा"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"चार्जर अनप्लग करा"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"हे डिव्हाइस चार्ज करताना समस्या आहे. पॉवर अडॅप्टर अनप्लग करा आणि शक्य तेवढी काळजी घ्या कदाचित केबल गरम असू शकते."</string> + <!-- no translation found for high_temp_alarm_title (8654754369605452169) --> + <skip /> + <!-- no translation found for high_temp_alarm_notify_message (3917622943609118956) --> + <skip /> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"काय काळजी घ्यावी ते पहा"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"डावा शॉर्टकट"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"उजवा शॉर्टकट"</string> diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml index db73d541b3c9..417a0b5b461d 100644 --- a/packages/SystemUI/res/values-ms/strings.xml +++ b/packages/SystemUI/res/values-ms/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Tidak mengenali wajah. Gunakan cap jari."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"Tak dapat mengecam wajah"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Gunakan cap jari"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth disambungkan."</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Peratusan kuasa bateri tidak diketahui."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Disambungkan kepada <xliff:g id="BLUETOOTH">%s</xliff:g>."</string> @@ -423,10 +421,8 @@ <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Tindanan kapsyen"</string> <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"dayakan"</string> <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"lumpuhkan"</string> - <!-- no translation found for sound_settings (8874581353127418308) --> - <skip /> - <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) --> - <skip /> + <string name="sound_settings" msgid="8874581353127418308">"Bunyi & getaran"</string> + <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Tetapan"</string> <string name="screen_pinning_title" msgid="9058007390337841305">"Apl telah disemat"</string> <string name="screen_pinning_description" msgid="8699395373875667743">"Tindakan ini memastikan skrin kelihatan sehingga anda menyahsemat. Sentuh & tahan Kembali dan Ikhtisar untuk menyahsemat."</string> <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Tindakan ini memastikan skrin kelihatan sehingga anda menyahsemat. Sentuh & tahan Kembali dan Skrin Utama untuk menyahsemat."</string> @@ -602,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"Hidup"</string> <string name="switch_bar_off" msgid="5669805115416379556">"Mati"</string> <string name="tile_unavailable" msgid="3095879009136616920">"Tidak tersedia"</string> - <string name="tile_disabled" msgid="373212051546573069">"Dilumpuhkan"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"mengetahui lebih lanjut"</string> <string name="nav_bar" msgid="4642708685386136807">"Bar navigasi"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"Reka letak"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Jenis butang kiri tambahan"</string> @@ -675,8 +671,10 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Sesetengah ciri adalah terhad semasa telefon menyejuk.\nKetik untuk mendapatkan maklumat lanjut"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"Telefon anda akan cuba menyejuk secara automatik. Anda masih dapat menggunakan telefon itu tetapi telefon tersebut mungkin berjalan lebih perlahan.\n\nSetelah telefon anda sejuk, telefon itu akan berjalan seperti biasa."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Lihat langkah penjagaan"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Cabut palam pengejas"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"Terdapat isu semasa mengecas peranti ini. Cabut palam penyesuai kuasa. Berhati-hati kerana kabel mungkin hangat."</string> + <!-- no translation found for high_temp_alarm_title (8654754369605452169) --> + <skip /> + <!-- no translation found for high_temp_alarm_notify_message (3917622943609118956) --> + <skip /> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"Lihat langkah penjagaan"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Pintasan kiri"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"Pintasan kanan"</string> diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml index 7b4bbaf9c1ae..25066ebf9478 100644 --- a/packages/SystemUI/res/values-my/strings.xml +++ b/packages/SystemUI/res/values-my/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"မျက်နှာကို မမှတ်မိပါ။ လက်ဗွေကို အစားထိုးသုံးပါ။"</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"မျက်နှာကို မမှတ်မိပါ"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"လက်ဗွေကို အစားထိုးသုံးပါ"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"ဘလူးတုသ်ချိတ်ဆက်ထားမှု"</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"ဘက်ထရီရာခိုင်နှုန်းကို မသိပါ။"</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g>သို့ ချိတ်ဆက်ထား"</string> @@ -600,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"ဖွင့်"</string> <string name="switch_bar_off" msgid="5669805115416379556">"ပိတ်"</string> <string name="tile_unavailable" msgid="3095879009136616920">"မရနိုင်ပါ"</string> - <string name="tile_disabled" msgid="373212051546573069">"ပိတ်ထားသည်"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"ပိုမိုလေ့လာရန်"</string> <string name="nav_bar" msgid="4642708685386136807">"ရွှေ့လျားရန်ဘားတန်း"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"အပြင်အဆင်"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"လက်ဝဲခလုတ် အမျိုးအစားအပို"</string> @@ -673,8 +671,10 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"ဖုန်းကို အေးအောင်ပြုလုပ်နေစဉ်တွင် အချို့ဝန်ဆောင်မှုများကို ကန့်သတ်ထားပါသည်။\nနောက်ထပ်အချက်အလက်များအတွက် တို့ပါ"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"သင့်ဖုန်းသည် အလိုအလျောက် ပြန်အေးသွားပါလိမ့်မည်။ ဖုန်းကို အသုံးပြုနိုင်ပါသေးသည် သို့သော် ပိုနှေးနိုင်ပါသည်။\n\nသင့်ဖုန်း အေးသွားသည်နှင့် ပုံမှန်အတိုင်း ပြန်အလုပ်လုပ်ပါလိမ့်မည်။"</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"ဂရုပြုစရာ အဆင့်များ ကြည့်ရန်"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"အားသွင်းကိရိယာ ပလပ်ဖြုတ်ပါ"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"ဤစက်ပစ္စည်းကို အားသွင်းရာတွင် ပြဿနာရှိနေသည်။ ပါဝါ ကြားခံကိရိယာကို ပလပ်ဖြုတ်ပါ။ ကေဘယ်ကြိုး ပူနွေးနေနိုင်သဖြင့် သတိထားပါ။"</string> + <!-- no translation found for high_temp_alarm_title (8654754369605452169) --> + <skip /> + <!-- no translation found for high_temp_alarm_notify_message (3917622943609118956) --> + <skip /> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"ဂရုပြုစရာ အဆင့်များ ကြည့်ရန်"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"လက်ဝဲ ဖြတ်လမ်းလင့်ခ်"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"လက်ယာ ဖြတ်လမ်းလင့်ခ်"</string> diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml index 3d03ebf74c76..4e97b48a8d70 100644 --- a/packages/SystemUI/res/values-nb/strings.xml +++ b/packages/SystemUI/res/values-nb/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Ansiktet gjenkjennes ikke. Bruk fingeravtrykk."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"Ansiktet gjenkjennes ikke"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Bruk fingeravtrykk"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth er tilkoblet."</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Batteriprosenten er ukjent."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Koblet til <xliff:g id="BLUETOOTH">%s</xliff:g>."</string> @@ -423,10 +421,8 @@ <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Overlegg med teksting"</string> <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"aktivér"</string> <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"deaktiver"</string> - <!-- no translation found for sound_settings (8874581353127418308) --> - <skip /> - <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) --> - <skip /> + <string name="sound_settings" msgid="8874581353127418308">"Lyd og vibrering"</string> + <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Innstillinger"</string> <string name="screen_pinning_title" msgid="9058007390337841305">"Appen er festet"</string> <string name="screen_pinning_description" msgid="8699395373875667743">"Gjør at den vises til du løsner den. Trykk og hold inne Tilbake og Oversikt for å løsne den."</string> <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Gjør at den vises til du løsner den. Trykk og hold inne Tilbake og Startside for å løsne den."</string> @@ -602,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"På"</string> <string name="switch_bar_off" msgid="5669805115416379556">"Av"</string> <string name="tile_unavailable" msgid="3095879009136616920">"Utilgjengelig"</string> - <string name="tile_disabled" msgid="373212051546573069">"Slått av"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"finne ut mer"</string> <string name="nav_bar" msgid="4642708685386136807">"Navigasjonsrad"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"Oppsett"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Ekstra venstre-knapptype"</string> @@ -675,8 +671,8 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Enkelte funksjoner er begrenset mens telefonen kjøles ned.\nTrykk for å se mer informasjon"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"Telefonen din kommer til å prøve å kjøle seg ned automatisk. Du kan fremdeles bruke telefonen, men den kjører muligens saktere.\n\nTelefonen kommer til å kjøre som normalt, når den har kjølt seg ned."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Se vedlikeholdstrinnene"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Koble fra laderen"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"Det oppsto et problem med lading av enheten. Koble fra strømadapteren, og vær forsiktig, kabelen kan være varm."</string> + <string name="high_temp_alarm_title" msgid="8654754369605452169">"Koble fra enheten"</string> + <string name="high_temp_alarm_notify_message" msgid="3917622943609118956">"Enheten begynner å bli varm nær ladeporten. Hvis den er koblet til en lader eller et USB-tilbehør, må du koble den fra. Vær forsiktig da kabelen også kan være varm."</string> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"Se vedlikeholdstrinnene"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Venstre hurtigtast"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"Høyre hurtigtast"</string> diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml index 6e298dfe4f09..caeceb41a533 100644 --- a/packages/SystemUI/res/values-ne/strings.xml +++ b/packages/SystemUI/res/values-ne/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"अनुहार पहिचान गर्न सकिएन। बरु फिंगरप्रिन्ट प्रयोग गर्नुहोस्।"</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"अनुहार पहिचान गर्न सकिएन"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"बरु फिंगरप्रिन्ट प्रयोग गर्नुहोस्"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"ब्लुटुथ जडान भयो।"</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"ब्याट्रीमा कति प्रतिशत चार्ज छ भन्ने कुराको जानाकरी छैन।"</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> मा जडित।"</string> @@ -600,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"अन छ"</string> <string name="switch_bar_off" msgid="5669805115416379556">"अफ छ"</string> <string name="tile_unavailable" msgid="3095879009136616920">"उपलब्ध छैन"</string> - <string name="tile_disabled" msgid="373212051546573069">"अफ गरियो"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"थप जान्नुहोस्"</string> <string name="nav_bar" msgid="4642708685386136807">"नेभिगेशन पट्टी"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"लेआउट"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"अतिरिक्त बायाँतिरको बटनको प्रकार"</string> @@ -673,8 +671,8 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"फोन नचिस्सिँदासम्म केही सुविधाहरू उपलब्ध हुने छैनन्।\nथप जानकारीका लागि ट्याप गर्नुहोस्"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"तपाईंको फोन स्वतः चिसो हुने प्रयास गर्ने छ। तपाईं अझै पनि आफ्नो फोनको प्रयोग गर्न सक्नुहुन्छ तर त्यो अझ ढिलो चल्न सक्छ।\n\nचिसो भएपछि तपाईंको फोन सामान्य गतिमा चल्नेछ।"</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"डिभाइसको हेरचाह गर्ने तरिका हेर्नुहोस्"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"चार्जर अनप्लग गर्नुहोस्"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"यो डिभाइस चार्ज गर्दा कुनै समस्या भयो। पावर एडाप्टर अनप्लग गर्नुहोस् र केबल तातो हुन सक्ने भएकाले ध्यान दिनुहोस्।"</string> + <string name="high_temp_alarm_title" msgid="8654754369605452169">"डिभाइस बिजुलीको स्रोतबाट निकाल्नुहोस्"</string> + <string name="high_temp_alarm_notify_message" msgid="3917622943609118956">"तपाईंको डिभाइसको चार्जिङ पोर्टतिरको भाग तातीरहेको छ। तपाईंको डिभाइस चार्जर वा USB एक्सेसरीमा जोडिएको गरिएको छ भने त्यसलाई निकाल्नुहोस्। यसका साथै सो केबल तातो हुन सक्ने भएकाले ख्याल गर्नुहोला।"</string> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"हेरचाहसम्बन्धी चरणहरू हेर्नुहोस्"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"बायाँतिरको सर्टकट"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"दायाँतिरको सर्टकट"</string> diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml index 3a50909b0e02..da55ac366239 100644 --- a/packages/SystemUI/res/values-nl/strings.xml +++ b/packages/SystemUI/res/values-nl/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Gezicht niet herkend. Gebruik je vingerafdruk."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"Gezicht niet herkend"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Vingerafdruk gebruiken"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth-verbinding ingesteld."</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Batterijpercentage onbekend."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Verbonden met <xliff:g id="BLUETOOTH">%s</xliff:g>."</string> @@ -600,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"Aan"</string> <string name="switch_bar_off" msgid="5669805115416379556">"Uit"</string> <string name="tile_unavailable" msgid="3095879009136616920">"Niet beschikbaar"</string> - <string name="tile_disabled" msgid="373212051546573069">"Uitgezet"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"meer informatie"</string> <string name="nav_bar" msgid="4642708685386136807">"Navigatiebalk"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"Lay-out"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Extra knoptype links"</string> @@ -673,8 +671,10 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Bepaalde functies zijn beperkt terwijl de telefoon afkoelt.\nTik voor meer informatie"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"Je telefoon probeert automatisch af te koelen. Je kunt je telefoon nog steeds gebruiken, maar deze kan langzamer werken.\n\nZodra de telefoon is afgekoeld, werkt deze weer normaal."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Onderhoudsstappen bekijken"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Oplader loskoppelen"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"Er is een probleem met het opladen van dit apparaat. Koppel de voedingsadapter los. Wees voorzichtig, want de kabel kan warm zijn."</string> + <!-- no translation found for high_temp_alarm_title (8654754369605452169) --> + <skip /> + <!-- no translation found for high_temp_alarm_notify_message (3917622943609118956) --> + <skip /> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"Onderhoudsstappen bekijken"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Snelkoppeling links"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"Snelkoppeling rechts"</string> diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml index 671e60fc21a8..5d1664208f93 100644 --- a/packages/SystemUI/res/values-or/strings.xml +++ b/packages/SystemUI/res/values-or/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"ଫେସ୍ ଚିହ୍ନଟ କରିହେବ ନାହିଁ। ଟିପଚିହ୍ନ ବ୍ୟବହାର କରନ୍ତୁ।"</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"ଫେସ ଚିହ୍ନଟ ହୋଇପାରିବ ନାହିଁ"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"ଟିପଚିହ୍ନ ବ୍ୟବହାର କରନ୍ତୁ"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"ବ୍ଲୁଟୂଥ୍ ସଂଯୋଗ କରାଯାଇଛି।"</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"ବ୍ୟାଟେରୀ ଶତକଡ଼ା ଅଜଣା ଅଟେ।"</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> ସହ ସଂଯୁକ୍ତ"</string> @@ -600,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"ଚାଲୁ ଅଛି"</string> <string name="switch_bar_off" msgid="5669805115416379556">"ବନ୍ଦ ଅଛି"</string> <string name="tile_unavailable" msgid="3095879009136616920">"ଅନୁପଲବ୍ଧ"</string> - <string name="tile_disabled" msgid="373212051546573069">"ଅକ୍ଷମ କରାଯାଇଛି"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"ଅଧିକ ଜାଣନ୍ତୁ"</string> <string name="nav_bar" msgid="4642708685386136807">"ନାଭିଗେଶନ୍ ବାର୍"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"ଲେଆଉଟ୍"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"ସମ୍ପୂର୍ଣ୍ଣ ବାମ ବଟନ୍ ପ୍ରକାର"</string> @@ -673,8 +671,8 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"ଫୋନ୍ ଥଣ୍ଡା ହେବା ସମୟରେ କିଛି ଫିଚର୍ ଠିକ ଭାବେ କାମ କରିନଥାଏ।\nଅଧିକ ସୂଚନା ପାଇଁ ଟାପ୍ କରନ୍ତୁ"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"ଆପଣଙ୍କ ଫୋନ୍ ସ୍ୱଚାଳିତ ଭାବେ ଥଣ୍ଡା ହେବାକୁ ଚେଷ୍ଟା କରିବ। ଆପଣ ତଥାପି ନିଜ ଫୋନ୍ ବ୍ୟବହାର କରିପାରିବେ, କିନ୍ତୁ ଏହା ଧୀରେ ଚାଲିପାରେ।\n\nଆପଣଙ୍କ ଫୋନ୍ ଥଣ୍ଡା ହୋଇଯିବାପରେ, ଏହା ସାମାନ୍ୟ ଭାବେ ଚାଲିବ।"</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"ଯତ୍ନ ନେବା ପାଇଁ ଷ୍ଟେପଗୁଡ଼ିକ ଦେଖନ୍ତୁ"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"ଚାର୍ଜର୍ ଅନ୍ପ୍ଲଗ୍ କରନ୍ତୁ"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"ଏହି ଡିଭାଇସ୍ ଚାର୍ଜ କରିବାରେ ଗୋଟିଏ ସମସ୍ୟା ଅଛି। ଯେହେତୁ କେବଳ ଗରମ ହୋଇଯାଇପାରେ, ତେଣୁ ପାୱାର୍ ଆଡପ୍ଟର୍ ଅନ୍ପ୍ଲଗ୍ କରନ୍ତୁ ଏବଂ ଯତ୍ନ ନିଅନ୍ତୁ।"</string> + <string name="high_temp_alarm_title" msgid="8654754369605452169">"ଆପଣଙ୍କ ଡିଭାଇସକୁ ଅନପ୍ଲଗ କରନ୍ତୁ"</string> + <string name="high_temp_alarm_notify_message" msgid="3917622943609118956">"ଚାର୍ଜିଂ ପୋର୍ଟ ନିକଟରେ ଆପଣଙ୍କ ଡିଭାଇସ ଗରମ ହୋଇଯାଉଛି। ଯଦି ଏହା ଏକ ଚାର୍ଜର କିମ୍ବା USB ଆକସେସୋରୀ ସହ କନେକ୍ଟ କରାଯାଇଥାଏ ତେବେ ଏହାକୁ ଅନପ୍ଲଗ କରନ୍ତୁ ଏବଂ ଧ୍ୟାନ ରଖନ୍ତୁ କାରଣ କେବୁଲ ମଧ୍ୟ ଗରମ ହୋଇପାରେ।"</string> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"ସେବା ସମ୍ବନ୍ଧିତ ଷ୍ଟେପ୍ଗୁଡ଼ିକ ଦେଖନ୍ତୁ"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"ବାମ ଶର୍ଟକଟ୍"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"ଡାହାଣ ଶର୍ଟକଟ୍"</string> diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml index 003c54834afa..80efeddcca78 100644 --- a/packages/SystemUI/res/values-pa/strings.xml +++ b/packages/SystemUI/res/values-pa/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"ਚਿਹਰਾ ਨਹੀਂ ਪਛਾਣ ਸਕਦੇ। ਇਸਦੀ ਬਜਾਏ ਫਿੰਗਰਪ੍ਰਿੰਟ ਵਰਤੋ।"</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"ਚਿਹਰੇ ਦੀ ਪਛਾਣ ਨਹੀਂ ਹੋਈ"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"ਇਸਦੀ ਬਜਾਏ ਫਿੰਗਰਪ੍ਰਿੰਟ ਵਰਤੋ"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth ਕਨੈਕਟ ਕੀਤੀ।"</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"ਬੈਟਰੀ ਪ੍ਰਤੀਸ਼ਤ ਅਗਿਆਤ ਹੈ।"</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> ਨਾਲ ਕਨੈਕਟ ਕੀਤਾ।"</string> @@ -423,10 +421,8 @@ <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"ਸੁਰਖੀਆਂ ਓਵਰਲੇ"</string> <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"ਚਾਲੂ ਕਰੋ"</string> <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"ਬੰਦ ਕਰੋ"</string> - <!-- no translation found for sound_settings (8874581353127418308) --> - <skip /> - <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) --> - <skip /> + <string name="sound_settings" msgid="8874581353127418308">"ਧੁਨੀ ਅਤੇ ਥਰਥਰਾਹਟ"</string> + <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"ਸੈਟਿੰਗਾਂ"</string> <string name="screen_pinning_title" msgid="9058007390337841305">"ਐਪ ਨੂੰ ਪਿੰਨ ਕੀਤਾ ਗਿਆ ਹੈ"</string> <string name="screen_pinning_description" msgid="8699395373875667743">"ਇਹ ਇਸ ਨੂੰ ਤਦ ਤੱਕ ਦ੍ਰਿਸ਼ ਵਿੱਚ ਰੱਖਦਾ ਹੈ ਜਦ ਤੱਕ ਤੁਸੀਂ ਅਨਪਿੰਨ ਨਹੀਂ ਕਰਦੇ। ਅਨਪਿੰਨ ਕਰਨ ਲਈ \'ਪਿੱਛੇ\' ਅਤੇ \'ਰੂਪ-ਰੇਖਾ\' ਨੂੰ ਸਪੱਰਸ਼ ਕਰੋ ਅਤੇ ਦਬਾ ਕੇ ਰੱਖੋ।"</string> <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"ਤੁਹਾਡੇ ਵੱਲੋਂ ਅਨਪਿੰਨ ਕੀਤੇ ਜਾਣ ਤੱਕ ਇਸਨੂੰ ਦਿਖਾਇਆ ਜਾਂਦਾ ਹੈ। ਅਨਪਿੰਨ ਕਰਨ ਲਈ \'ਪਿੱਛੇ\' ਅਤੇ \'ਹੋਮ\' ਨੂੰ ਸਪਰਸ਼ ਕਰਕੇ ਰੱਖੋ।"</string> @@ -602,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"ਚਾਲੂ"</string> <string name="switch_bar_off" msgid="5669805115416379556">"ਬੰਦ"</string> <string name="tile_unavailable" msgid="3095879009136616920">"ਅਣਉਪਲਬਧ"</string> - <string name="tile_disabled" msgid="373212051546573069">"ਬੰਦ ਹੈ"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"ਹੋਰ ਜਾਣੋ"</string> <string name="nav_bar" msgid="4642708685386136807">"ਨੈਵੀਗੇਸ਼ਨ ਵਾਲੀ ਪੱਟੀ"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"ਖਾਕਾ"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"ਵਧੇਰੇ ਖੱਬੇ ਬਟਨ ਕਿਸਮ"</string> @@ -675,8 +671,10 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"ਫ਼ੋਨ ਦੇ ਠੰਡਾ ਹੋਣ ਦੇ ਦੌਰਾਨ ਕੁਝ ਵਿਸ਼ੇਸ਼ਤਾਵਾਂ ਸੀਮਤ ਹੁੰਦੀਆਂ ਹਨ।\nਵਧੇਰੇ ਜਾਣਕਾਰੀ ਲਈ ਟੈਪ ਕਰੋ"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"ਤੁਹਾਡਾ ਫ਼ੋਨ ਸਵੈਚਲਿਤ ਰੂਪ ਵਿੱਚ ਠੰਡਾ ਹੋਣ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰੇਗਾ। ਤੁਸੀਂ ਹਾਲੇ ਵੀ ਆਪਣੇ ਫ਼ੋਨ ਨੂੰ ਵਰਤ ਸਕਦੇ ਹੋ, ਪਰੰਤੂ ਹੋ ਸਕਦਾ ਹੈ ਕਿ ਇਹ ਵਧੇਰੇ ਹੌਲੀ ਚੱਲੇ।\n\nਇੱਕ ਵਾਰ ਠੰਡਾ ਹੋਣ ਤੋਂ ਬਾਅਦ ਤੁਹਾਡਾ ਫ਼ੋਨ ਸਧਾਰਨ ਤੌਰ \'ਤੇ ਚੱਲੇਗਾ।"</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"ਦੇਖਭਾਲ ਦੇ ਪੜਾਅ ਦੇਖੋ"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"ਚਾਰਜਰ ਨੂੰ ਕੱਢੋ"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"ਇਸ ਡੀਵਾਈਸ ਨੂੰ ਚਾਰਜ ਕਰਨ ਵਿੱਚ ਕੋਈ ਸਮੱਸਿਆ ਆ ਗਈ ਹੈ। ਪਾਵਰ ਅਡਾਪਟਰ ਨੂੰ ਕੱਢੋ ਅਤੇ ਧਿਆਨ ਰੱਖੋ ਸ਼ਾਇਦ ਕੇਬਲ ਗਰਮ ਹੋਵੇ।"</string> + <!-- no translation found for high_temp_alarm_title (8654754369605452169) --> + <skip /> + <!-- no translation found for high_temp_alarm_notify_message (3917622943609118956) --> + <skip /> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"ਦੇਖਭਾਲ ਦੇ ਪੜਾਅ ਦੇਖੋ"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"ਖੱਬਾ ਸ਼ਾਰਟਕੱਟ"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"ਸੱਜਾ ਸ਼ਾਰਟਕੱਟ"</string> diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml index 7082ff8a33f8..063ffbfda205 100644 --- a/packages/SystemUI/res/values-pl/strings.xml +++ b/packages/SystemUI/res/values-pl/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Nie rozpoznaję twarzy. Użyj odcisku palca."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"Nie można rozpoznać twarzy"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Użyj odcisku palca"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth połączony."</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Poziom naładowania baterii jest nieznany."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Połączono z <xliff:g id="BLUETOOTH">%s</xliff:g>."</string> @@ -345,8 +343,7 @@ <string name="keyguard_indication_charging_time_slowly" msgid="301936949731705417">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Wolne ładowanie • Pełne naładowanie za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="keyguard_indication_charging_time_dock" msgid="3149328898931741271">"<xliff:g id="PERCENTAGE">%2$s</xliff:g> • Ładowanie • Pełne naładowanie za <xliff:g id="CHARGING_TIME_LEFT">%1$s</xliff:g>"</string> <string name="accessibility_multi_user_switch_switcher" msgid="5330448341251092660">"Przełącz użytkownika"</string> - <!-- no translation found for accessibility_multi_user_list_switcher (8574105376229857407) --> - <skip /> + <string name="accessibility_multi_user_list_switcher" msgid="8574105376229857407">"menu"</string> <string name="guest_exit_guest_dialog_message" msgid="8183450985628495709">"Wszystkie aplikacje i dane w tej sesji zostaną usunięte."</string> <string name="guest_wipe_session_title" msgid="7147965814683990944">"Witaj ponownie, Gościu!"</string> <string name="guest_wipe_session_message" msgid="3393823610257065457">"Chcesz kontynuować sesję?"</string> @@ -424,10 +421,8 @@ <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Nakładka z napisami"</string> <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"włącz"</string> <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"wyłącz"</string> - <!-- no translation found for sound_settings (8874581353127418308) --> - <skip /> - <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) --> - <skip /> + <string name="sound_settings" msgid="8874581353127418308">"Dźwięk i wibracje"</string> + <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Ustawienia"</string> <string name="screen_pinning_title" msgid="9058007390337841305">"Aplikacja jest przypięta"</string> <string name="screen_pinning_description" msgid="8699395373875667743">"Ekran będzie widoczny, dopóki go nie odepniesz. Aby to zrobić, kliknij i przytrzymaj Wstecz oraz Przegląd."</string> <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Ekran będzie widoczny, dopóki go nie odepniesz. Aby to zrobić, naciśnij i przytrzymaj Wstecz oraz Ekran główny."</string> @@ -603,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"Włączono"</string> <string name="switch_bar_off" msgid="5669805115416379556">"Wyłączono"</string> <string name="tile_unavailable" msgid="3095879009136616920">"Niedostępne"</string> - <string name="tile_disabled" msgid="373212051546573069">"Wyłączono"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"Więcej informacji"</string> <string name="nav_bar" msgid="4642708685386136807">"Pasek nawigacji"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"Układ"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Typ dodatkowego lewego przycisku"</string> @@ -676,8 +671,8 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Podczas obniżania temperatury telefonu niektóre funkcje są ograniczone\nKliknij, by dowiedzieć się więcej"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"Telefon automatycznie podejmie próbę obniżenia temperatury. Możesz go wciąż używać, ale telefon może działać wolniej.\n\nGdy temperatura się obniży, telefon będzie działał normalnie."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Zobacz instrukcję postępowania"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Odłącz ładowarkę"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"Podczas ładowania tego urządzenia wystąpił błąd. Odłącz zasilacz, zwracając uwagę na kabel, który może być gorący."</string> + <string name="high_temp_alarm_title" msgid="8654754369605452169">"Odłącz urządzenie"</string> + <string name="high_temp_alarm_notify_message" msgid="3917622943609118956">"Urządzenie za bardzo się nagrzewa w okolicy gniazda ładowania. Jeśli jest podłączone do ładowarki albo akcesorium USB, odłącz je. Uważaj, bo kabel również może być nagrzany."</string> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"Zobacz instrukcję postępowania"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Lewy skrót"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"Prawy skrót"</string> diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml index 9a8ff6673182..f85ab52b11b4 100644 --- a/packages/SystemUI/res/values-pt-rBR/strings.xml +++ b/packages/SystemUI/res/values-pt-rBR/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Não foi possível reconhecer o rosto Use a impressão digital."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"Rosto não reconhecido"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Use a impressão digital"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth conectado."</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Porcentagem da bateria desconhecida."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Conectado a <xliff:g id="BLUETOOTH">%s</xliff:g>."</string> @@ -206,7 +204,7 @@ <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"A opção \"Sensores desativados\" está ativa"</string> <string name="accessibility_clear_all" msgid="970525598287244592">"Limpar todas as notificações."</string> <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"Mais <xliff:g id="NUMBER">%s</xliff:g>"</string> - <string name="notification_group_overflow_description" msgid="7176322877233433278">"{count,plural, =1{Mais # notificação no grupo.}one{Mais # notificação no grupo.}other{Mais # notificações no grupo.}}"</string> + <string name="notification_group_overflow_description" msgid="7176322877233433278">"{count,plural, =1{Mais # notificação no grupo.}one{Mais # notificação no grupo.}many{Mais # de notificações no grupo.}other{Mais # notificações no grupo.}}"</string> <string name="accessibility_rotation_lock_on_landscape" msgid="936972553861524360">"A tela está bloqueada na orientação paisagem."</string> <string name="accessibility_rotation_lock_on_portrait" msgid="2356633398683813837">"A tela está bloqueada na orientação retrato."</string> <string name="dessert_case" msgid="9104973640704357717">"Mostruário de sobremesas"</string> @@ -254,7 +252,7 @@ <string name="quick_settings_hotspot_label" msgid="1199196300038363424">"Ponto de acesso"</string> <string name="quick_settings_hotspot_secondary_label_transient" msgid="7585604088079160564">"Ativando…"</string> <string name="quick_settings_hotspot_secondary_label_data_saver_enabled" msgid="1280433136266439372">"Economia de dados ativada"</string> - <string name="quick_settings_hotspot_secondary_label_num_devices" msgid="7536823087501239457">"{count,plural, =1{# dispositivo}one{# dispositivo}other{# dispositivos}}"</string> + <string name="quick_settings_hotspot_secondary_label_num_devices" msgid="7536823087501239457">"{count,plural, =1{# dispositivo}one{# dispositivo}many{# de dispositivos}other{# dispositivos}}"</string> <string name="quick_settings_flashlight_label" msgid="4904634272006284185">"Lanterna"</string> <string name="quick_settings_flashlight_camera_in_use" msgid="4820591564526512571">"Câmera em uso"</string> <string name="quick_settings_cellular_detail_title" msgid="792977203299358893">"Dados móveis"</string> @@ -355,7 +353,7 @@ <string name="guest_notification_session_active" msgid="5567273684713471450">"Você está no modo visitante"</string> <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Ao adicionar um novo usuário, o dispositivo vai sair do modo visitante e excluir todos os apps e dados da Sessão de visitante atual."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Limite de usuários atingido"</string> - <string name="user_limit_reached_message" msgid="1070703858915935796">"{count,plural, =1{Você só pode criar 1 usuário.}one{Você pode adicionar até # usuário.}other{Você pode adicionar até # usuários.}}"</string> + <string name="user_limit_reached_message" msgid="1070703858915935796">"{count,plural, =1{Você só pode criar 1 usuário.}one{Você pode adicionar até # usuário.}many{Você pode adicionar até # de usuários.}other{Você pode adicionar até # usuários.}}"</string> <string name="user_remove_user_title" msgid="9124124694835811874">"Remover usuário?"</string> <string name="user_remove_user_message" msgid="6702834122128031833">"Todos os apps e dados deste usuário serão excluídos."</string> <string name="user_remove_user_remove" msgid="8387386066949061256">"Remover"</string> @@ -543,8 +541,8 @@ <string name="notification_menu_snooze_action" msgid="5415729610393475019">"Lembrete"</string> <string name="snooze_undo" msgid="2738844148845992103">"Desfazer"</string> <string name="snoozed_for_time" msgid="7586689374860469469">"Adiada para <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> - <string name="snoozeHourOptions" msgid="2332819756222425558">"{count,plural, =1{# hora}=2{# horas}one{# hora}other{# horas}}"</string> - <string name="snoozeMinuteOptions" msgid="2222082405822030979">"{count,plural, =1{# minuto}one{# minuto}other{# minuto}}"</string> + <string name="snoozeHourOptions" msgid="2332819756222425558">"{count,plural, =1{# hora}=2{# horas}one{# hora}many{# de horas}other{# horas}}"</string> + <string name="snoozeMinuteOptions" msgid="2222082405822030979">"{count,plural, =1{# minuto}one{# minuto}many{# de minutos}other{# minuto}}"</string> <string name="battery_detail_switch_title" msgid="6940976502957380405">"Economia de bateria"</string> <string name="keyboard_key_button_template" msgid="8005673627272051429">"Botão <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="3734400625170020657">"Home"</string> @@ -600,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"Ativado"</string> <string name="switch_bar_off" msgid="5669805115416379556">"Desativado"</string> <string name="tile_unavailable" msgid="3095879009136616920">"Indisponível"</string> - <string name="tile_disabled" msgid="373212051546573069">"Desativado"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"saber mais"</string> <string name="nav_bar" msgid="4642708685386136807">"Barra de navegação"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"Layout"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Tipo de botão esquerdo extra"</string> @@ -673,8 +671,8 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Alguns recursos ficam limitados enquanto o smartphone é resfriado.\nToque para saber mais"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"Seu smartphone tentará se resfriar automaticamente. Você ainda poderá usá-lo, mas talvez ele fique mais lento.\n\nQuando o smartphone estiver resfriado, ele voltará ao normal."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Ver etapas de cuidado"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Desconecte o carregador"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"Ocorreu um problema com o carregamento deste dispositivo. Desconecte o adaptador de energia com cuidado, já que o cabo pode estar quente."</string> + <string name="high_temp_alarm_title" msgid="8654754369605452169">"Desconecte seu dispositivo"</string> + <string name="high_temp_alarm_notify_message" msgid="3917622943609118956">"Seu dispositivo está ficando quente perto da porta de carregamento. Desconecte qualquer carregador ou acessório USB que esteja conectado, mas tome cuidado, porque o cabo também pode estar quente."</string> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"Ver etapas de cuidado"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Atalho à esquerda"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"Atalho à direita"</string> @@ -768,7 +766,7 @@ <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"alternar"</string> <string name="quick_controls_title" msgid="6839108006171302273">"Controles do dispositivo"</string> <string name="controls_providers_title" msgid="6879775889857085056">"Escolha um app para adicionar controles"</string> - <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# controle adicionado.}one{# controle adicionado.}other{# controles adicionados.}}"</string> + <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# controle adicionado.}one{# controle adicionado.}many{# de controles adicionados.}other{# controles adicionados.}}"</string> <string name="controls_removed" msgid="3731789252222856959">"Removido"</string> <string name="accessibility_control_favorite" msgid="8694362691985545985">"Adicionado como favorito"</string> <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Adicionado como favorito (posição <xliff:g id="NUMBER">%d</xliff:g>)"</string> @@ -925,7 +923,7 @@ <string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Adicionar bloco"</string> <string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Não adicionar bloco"</string> <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Selecionar usuário"</string> - <string name="fgs_manager_footer_label" msgid="8276763570622288231">"{count,plural, =1{# app está ativo}one{# apps está ativo}other{# apps estão ativos}}"</string> + <string name="fgs_manager_footer_label" msgid="8276763570622288231">"{count,plural, =1{# app está ativo}one{# apps está ativo}many{# de apps estão ativos}other{# apps estão ativos}}"</string> <string name="fgs_dot_content_description" msgid="2865071539464777240">"Nova informação"</string> <string name="fgs_manager_dialog_title" msgid="5879184257257718677">"Apps ativos"</string> <string name="fgs_manager_dialog_message" msgid="2670045017200730076">"Esses apps ficam ativos e em execução mesmo quando não estão em uso. Isso melhora a funcionalidade deles, mas também pode afetar a duração da bateria."</string> @@ -955,7 +953,7 @@ <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"A câmera está desativada"</string> <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"O microfone está desativado"</string> <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"A câmera e o microfone estão desativados"</string> - <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notificação}one{# notificação}other{# notificações}}"</string> + <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notificação}one{# notificação}many{# notificações}other{# notificações}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Transmitindo"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Interromper a transmissão do app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml index c2436e19aca1..a33552b97503 100644 --- a/packages/SystemUI/res/values-pt-rPT/strings.xml +++ b/packages/SystemUI/res/values-pt-rPT/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Impos. reconh. rosto. Utilize a impressão digital."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"Imposs. reconhecer rosto"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Usar impressão digital"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth ligado."</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Percentagem da bateria desconhecida."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Ligado a <xliff:g id="BLUETOOTH">%s</xliff:g>."</string> @@ -206,7 +204,7 @@ <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"Sensores desativados ativo"</string> <string name="accessibility_clear_all" msgid="970525598287244592">"Limpar todas as notificações."</string> <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string> - <string name="notification_group_overflow_description" msgid="7176322877233433278">"{count,plural, =1{Mais # notificação no grupo.}other{Mais # notificações no grupo.}}"</string> + <string name="notification_group_overflow_description" msgid="7176322877233433278">"{count,plural, =1{Mais # notificação no grupo.}many{Mais # notificações no grupo.}other{Mais # notificações no grupo.}}"</string> <string name="accessibility_rotation_lock_on_landscape" msgid="936972553861524360">"O ecrã está bloqueado na orientação horizontal."</string> <string name="accessibility_rotation_lock_on_portrait" msgid="2356633398683813837">"O ecrã está bloqueado na orientação vertical."</string> <string name="dessert_case" msgid="9104973640704357717">"Vitrina de sobremesas"</string> @@ -254,7 +252,7 @@ <string name="quick_settings_hotspot_label" msgid="1199196300038363424">"Zona Wi-Fi"</string> <string name="quick_settings_hotspot_secondary_label_transient" msgid="7585604088079160564">"A ativar..."</string> <string name="quick_settings_hotspot_secondary_label_data_saver_enabled" msgid="1280433136266439372">"Poup. dados ativada"</string> - <string name="quick_settings_hotspot_secondary_label_num_devices" msgid="7536823087501239457">"{count,plural, =1{# dispositivo}other{# dispositivos}}"</string> + <string name="quick_settings_hotspot_secondary_label_num_devices" msgid="7536823087501239457">"{count,plural, =1{# dispositivo}many{# dispositivos}other{# dispositivos}}"</string> <string name="quick_settings_flashlight_label" msgid="4904634272006284185">"Lanterna"</string> <string name="quick_settings_flashlight_camera_in_use" msgid="4820591564526512571">"Câmara em utilização"</string> <string name="quick_settings_cellular_detail_title" msgid="792977203299358893">"Dados móveis"</string> @@ -355,7 +353,7 @@ <string name="guest_notification_session_active" msgid="5567273684713471450">"Está no modo convidado"</string> <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Ao adicionar um novo utilizador, o modo convidado é fechado e todas as apps e dados da sessão de convidado atual são eliminados."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Limite de utilizadores alcançado"</string> - <string name="user_limit_reached_message" msgid="1070703858915935796">"{count,plural, =1{Só é possível criar um utilizador.}other{É possível adicionar até # utilizadores.}}"</string> + <string name="user_limit_reached_message" msgid="1070703858915935796">"{count,plural, =1{Só é possível criar um utilizador.}many{É possível adicionar até # utilizadores.}other{É possível adicionar até # utilizadores.}}"</string> <string name="user_remove_user_title" msgid="9124124694835811874">"Remover o utilizador?"</string> <string name="user_remove_user_message" msgid="6702834122128031833">"Serão eliminados todos os dados e todas as aplicações deste utilizador."</string> <string name="user_remove_user_remove" msgid="8387386066949061256">"Remover"</string> @@ -543,8 +541,8 @@ <string name="notification_menu_snooze_action" msgid="5415729610393475019">"Lembrar-me"</string> <string name="snooze_undo" msgid="2738844148845992103">"Anular"</string> <string name="snoozed_for_time" msgid="7586689374860469469">"Suspensa por <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> - <string name="snoozeHourOptions" msgid="2332819756222425558">"{count,plural, =1{# hora}=2{# horas}other{# horas}}"</string> - <string name="snoozeMinuteOptions" msgid="2222082405822030979">"{count,plural, =1{# minuto}other{# minutos}}"</string> + <string name="snoozeHourOptions" msgid="2332819756222425558">"{count,plural, =1{# hora}=2{# horas}many{# horas}other{# horas}}"</string> + <string name="snoozeMinuteOptions" msgid="2222082405822030979">"{count,plural, =1{# minuto}many{# minutos}other{# minutos}}"</string> <string name="battery_detail_switch_title" msgid="6940976502957380405">"Poupança de bateria"</string> <string name="keyboard_key_button_template" msgid="8005673627272051429">"Botão <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="3734400625170020657">"Início"</string> @@ -600,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"Ativado"</string> <string name="switch_bar_off" msgid="5669805115416379556">"Desativado"</string> <string name="tile_unavailable" msgid="3095879009136616920">"Indisponível"</string> - <string name="tile_disabled" msgid="373212051546573069">"Desativado"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"saber mais"</string> <string name="nav_bar" msgid="4642708685386136807">"Barra de navegação"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"Esquema"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Tipo de botão esquerdo adicional"</string> @@ -673,8 +671,8 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Algumas funcionalidades são limitadas enquanto o telemóvel arrefece.\nToque para obter mais informações."</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"O telemóvel tenta arrefecer automaticamente. Pode continuar a utilizá-lo, mas este poderá funcionar mais lentamente.\n\nAssim que o telemóvel tiver arrefecido, funcionará normalmente."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Veja os passos de manutenção"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Desligar o carregador"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"Ocorreu um problema ao carregar este dispositivo. Desligue o transformador e tenha cuidado porque o cabo pode estar quente."</string> + <string name="high_temp_alarm_title" msgid="8654754369605452169">"Desligue o dispositivo"</string> + <string name="high_temp_alarm_notify_message" msgid="3917622943609118956">"O dispositivo está a ficar quente perto da porta de carregamento. Se estiver ligado a um carregador ou um acessório USB, desligue-o e tenha cuidado, uma vez que o cabo também pode estar quente."</string> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"Ver os passos a ter em consideração"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Atalho esquerdo"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"Atalho direito"</string> @@ -768,7 +766,7 @@ <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"ativar/desativar"</string> <string name="quick_controls_title" msgid="6839108006171302273">"Controlos de dispositivos"</string> <string name="controls_providers_title" msgid="6879775889857085056">"Escolha uma app para adicionar controlos"</string> - <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# controlo adicionado.}other{# controlos adicionados.}}"</string> + <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# controlo adicionado.}many{# controlos adicionados.}other{# controlos adicionados.}}"</string> <string name="controls_removed" msgid="3731789252222856959">"Removido"</string> <string name="accessibility_control_favorite" msgid="8694362691985545985">"Adicionado aos favoritos"</string> <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Adicionados aos favoritos, posição <xliff:g id="NUMBER">%d</xliff:g>"</string> @@ -925,7 +923,7 @@ <string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Adicionar mosaico"</string> <string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Não adicion. mosaico"</string> <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Selecione utilizador"</string> - <string name="fgs_manager_footer_label" msgid="8276763570622288231">"{count,plural, =1{# app está ativa}other{# apps estão ativas}}"</string> + <string name="fgs_manager_footer_label" msgid="8276763570622288231">"{count,plural, =1{# app está ativa}many{# apps estão ativas}other{# apps estão ativas}}"</string> <string name="fgs_dot_content_description" msgid="2865071539464777240">"Novas informações"</string> <string name="fgs_manager_dialog_title" msgid="5879184257257718677">"Apps ativas"</string> <string name="fgs_manager_dialog_message" msgid="2670045017200730076">"Estas apps estão ativas e a funcionar, mesmo quando não as está a usar. Isto melhora a sua funcionalidade, mas também afeta a autonomia da bateria."</string> @@ -955,7 +953,7 @@ <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"A câmara está desativada"</string> <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"O microfone está desativado"</string> <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"A câmara e o microfone estão desativados"</string> - <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notificação}other{# notificações}}"</string> + <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notificação}many{# notificações}other{# notificações}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"A transmitir"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Interromper a transmissão da app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml index 9a8ff6673182..f85ab52b11b4 100644 --- a/packages/SystemUI/res/values-pt/strings.xml +++ b/packages/SystemUI/res/values-pt/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Não foi possível reconhecer o rosto Use a impressão digital."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"Rosto não reconhecido"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Use a impressão digital"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth conectado."</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Porcentagem da bateria desconhecida."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Conectado a <xliff:g id="BLUETOOTH">%s</xliff:g>."</string> @@ -206,7 +204,7 @@ <string name="accessibility_sensors_off_active" msgid="2619725434618911551">"A opção \"Sensores desativados\" está ativa"</string> <string name="accessibility_clear_all" msgid="970525598287244592">"Limpar todas as notificações."</string> <string name="notification_group_overflow_indicator" msgid="7605120293801012648">"Mais <xliff:g id="NUMBER">%s</xliff:g>"</string> - <string name="notification_group_overflow_description" msgid="7176322877233433278">"{count,plural, =1{Mais # notificação no grupo.}one{Mais # notificação no grupo.}other{Mais # notificações no grupo.}}"</string> + <string name="notification_group_overflow_description" msgid="7176322877233433278">"{count,plural, =1{Mais # notificação no grupo.}one{Mais # notificação no grupo.}many{Mais # de notificações no grupo.}other{Mais # notificações no grupo.}}"</string> <string name="accessibility_rotation_lock_on_landscape" msgid="936972553861524360">"A tela está bloqueada na orientação paisagem."</string> <string name="accessibility_rotation_lock_on_portrait" msgid="2356633398683813837">"A tela está bloqueada na orientação retrato."</string> <string name="dessert_case" msgid="9104973640704357717">"Mostruário de sobremesas"</string> @@ -254,7 +252,7 @@ <string name="quick_settings_hotspot_label" msgid="1199196300038363424">"Ponto de acesso"</string> <string name="quick_settings_hotspot_secondary_label_transient" msgid="7585604088079160564">"Ativando…"</string> <string name="quick_settings_hotspot_secondary_label_data_saver_enabled" msgid="1280433136266439372">"Economia de dados ativada"</string> - <string name="quick_settings_hotspot_secondary_label_num_devices" msgid="7536823087501239457">"{count,plural, =1{# dispositivo}one{# dispositivo}other{# dispositivos}}"</string> + <string name="quick_settings_hotspot_secondary_label_num_devices" msgid="7536823087501239457">"{count,plural, =1{# dispositivo}one{# dispositivo}many{# de dispositivos}other{# dispositivos}}"</string> <string name="quick_settings_flashlight_label" msgid="4904634272006284185">"Lanterna"</string> <string name="quick_settings_flashlight_camera_in_use" msgid="4820591564526512571">"Câmera em uso"</string> <string name="quick_settings_cellular_detail_title" msgid="792977203299358893">"Dados móveis"</string> @@ -355,7 +353,7 @@ <string name="guest_notification_session_active" msgid="5567273684713471450">"Você está no modo visitante"</string> <string name="user_add_user_message_guest_remove" msgid="5589286604543355007">\n\n"Ao adicionar um novo usuário, o dispositivo vai sair do modo visitante e excluir todos os apps e dados da Sessão de visitante atual."</string> <string name="user_limit_reached_title" msgid="2429229448830346057">"Limite de usuários atingido"</string> - <string name="user_limit_reached_message" msgid="1070703858915935796">"{count,plural, =1{Você só pode criar 1 usuário.}one{Você pode adicionar até # usuário.}other{Você pode adicionar até # usuários.}}"</string> + <string name="user_limit_reached_message" msgid="1070703858915935796">"{count,plural, =1{Você só pode criar 1 usuário.}one{Você pode adicionar até # usuário.}many{Você pode adicionar até # de usuários.}other{Você pode adicionar até # usuários.}}"</string> <string name="user_remove_user_title" msgid="9124124694835811874">"Remover usuário?"</string> <string name="user_remove_user_message" msgid="6702834122128031833">"Todos os apps e dados deste usuário serão excluídos."</string> <string name="user_remove_user_remove" msgid="8387386066949061256">"Remover"</string> @@ -543,8 +541,8 @@ <string name="notification_menu_snooze_action" msgid="5415729610393475019">"Lembrete"</string> <string name="snooze_undo" msgid="2738844148845992103">"Desfazer"</string> <string name="snoozed_for_time" msgid="7586689374860469469">"Adiada para <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string> - <string name="snoozeHourOptions" msgid="2332819756222425558">"{count,plural, =1{# hora}=2{# horas}one{# hora}other{# horas}}"</string> - <string name="snoozeMinuteOptions" msgid="2222082405822030979">"{count,plural, =1{# minuto}one{# minuto}other{# minuto}}"</string> + <string name="snoozeHourOptions" msgid="2332819756222425558">"{count,plural, =1{# hora}=2{# horas}one{# hora}many{# de horas}other{# horas}}"</string> + <string name="snoozeMinuteOptions" msgid="2222082405822030979">"{count,plural, =1{# minuto}one{# minuto}many{# de minutos}other{# minuto}}"</string> <string name="battery_detail_switch_title" msgid="6940976502957380405">"Economia de bateria"</string> <string name="keyboard_key_button_template" msgid="8005673627272051429">"Botão <xliff:g id="NAME">%1$s</xliff:g>"</string> <string name="keyboard_key_home" msgid="3734400625170020657">"Home"</string> @@ -600,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"Ativado"</string> <string name="switch_bar_off" msgid="5669805115416379556">"Desativado"</string> <string name="tile_unavailable" msgid="3095879009136616920">"Indisponível"</string> - <string name="tile_disabled" msgid="373212051546573069">"Desativado"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"saber mais"</string> <string name="nav_bar" msgid="4642708685386136807">"Barra de navegação"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"Layout"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Tipo de botão esquerdo extra"</string> @@ -673,8 +671,8 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Alguns recursos ficam limitados enquanto o smartphone é resfriado.\nToque para saber mais"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"Seu smartphone tentará se resfriar automaticamente. Você ainda poderá usá-lo, mas talvez ele fique mais lento.\n\nQuando o smartphone estiver resfriado, ele voltará ao normal."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Ver etapas de cuidado"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Desconecte o carregador"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"Ocorreu um problema com o carregamento deste dispositivo. Desconecte o adaptador de energia com cuidado, já que o cabo pode estar quente."</string> + <string name="high_temp_alarm_title" msgid="8654754369605452169">"Desconecte seu dispositivo"</string> + <string name="high_temp_alarm_notify_message" msgid="3917622943609118956">"Seu dispositivo está ficando quente perto da porta de carregamento. Desconecte qualquer carregador ou acessório USB que esteja conectado, mas tome cuidado, porque o cabo também pode estar quente."</string> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"Ver etapas de cuidado"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Atalho à esquerda"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"Atalho à direita"</string> @@ -768,7 +766,7 @@ <string name="accessibility_floating_button_action_double_tap_to_toggle" msgid="7976492639670692037">"alternar"</string> <string name="quick_controls_title" msgid="6839108006171302273">"Controles do dispositivo"</string> <string name="controls_providers_title" msgid="6879775889857085056">"Escolha um app para adicionar controles"</string> - <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# controle adicionado.}one{# controle adicionado.}other{# controles adicionados.}}"</string> + <string name="controls_number_of_favorites" msgid="4481806788981836355">"{count,plural, =1{# controle adicionado.}one{# controle adicionado.}many{# de controles adicionados.}other{# controles adicionados.}}"</string> <string name="controls_removed" msgid="3731789252222856959">"Removido"</string> <string name="accessibility_control_favorite" msgid="8694362691985545985">"Adicionado como favorito"</string> <string name="accessibility_control_favorite_position" msgid="54220258048929221">"Adicionado como favorito (posição <xliff:g id="NUMBER">%d</xliff:g>)"</string> @@ -925,7 +923,7 @@ <string name="qs_tile_request_dialog_add" msgid="4888460910694986304">"Adicionar bloco"</string> <string name="qs_tile_request_dialog_not_add" msgid="4168716573114067296">"Não adicionar bloco"</string> <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Selecionar usuário"</string> - <string name="fgs_manager_footer_label" msgid="8276763570622288231">"{count,plural, =1{# app está ativo}one{# apps está ativo}other{# apps estão ativos}}"</string> + <string name="fgs_manager_footer_label" msgid="8276763570622288231">"{count,plural, =1{# app está ativo}one{# apps está ativo}many{# de apps estão ativos}other{# apps estão ativos}}"</string> <string name="fgs_dot_content_description" msgid="2865071539464777240">"Nova informação"</string> <string name="fgs_manager_dialog_title" msgid="5879184257257718677">"Apps ativos"</string> <string name="fgs_manager_dialog_message" msgid="2670045017200730076">"Esses apps ficam ativos e em execução mesmo quando não estão em uso. Isso melhora a funcionalidade deles, mas também pode afetar a duração da bateria."</string> @@ -955,7 +953,7 @@ <string name="dream_overlay_status_bar_camera_off" msgid="5273073778969890823">"A câmera está desativada"</string> <string name="dream_overlay_status_bar_mic_off" msgid="8366534415013819396">"O microfone está desativado"</string> <string name="dream_overlay_status_bar_camera_mic_off" msgid="3199425257833773569">"A câmera e o microfone estão desativados"</string> - <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notificação}one{# notificação}other{# notificações}}"</string> + <string name="dream_overlay_status_bar_notification_indicator" msgid="8091389255691081711">"{count,plural, =1{# notificação}one{# notificação}many{# notificações}other{# notificações}}"</string> <string name="dream_overlay_weather_complication_desc" msgid="824503662089783824">"<xliff:g id="WEATHER_CONDITION">%1$s</xliff:g>, <xliff:g id="TEMPERATURE">%2$s</xliff:g>"</string> <string name="broadcasting_description_is_broadcasting" msgid="765627502786404290">"Transmitindo"</string> <string name="bt_le_audio_broadcast_dialog_title" msgid="3605428497924077811">"Interromper a transmissão do app <xliff:g id="APP_NAME">%1$s</xliff:g>?"</string> diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml index f62ff137579f..67e463a00e8e 100644 --- a/packages/SystemUI/res/values-ro/strings.xml +++ b/packages/SystemUI/res/values-ro/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Chipul nu a fost recunoscut. Folosiți amprenta."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"Chip nerecunoscut"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Folosește amprenta"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Conectat prin Bluetooth."</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Procentajul bateriei este necunoscut."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Conectat la <xliff:g id="BLUETOOTH">%s</xliff:g>."</string> @@ -600,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"Activat"</string> <string name="switch_bar_off" msgid="5669805115416379556">"Dezactivați"</string> <string name="tile_unavailable" msgid="3095879009136616920">"Indisponibil"</string> - <string name="tile_disabled" msgid="373212051546573069">"Dezactivat"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"a afla mai multe"</string> <string name="nav_bar" msgid="4642708685386136807">"Bară de navigare"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"Aspect"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Tip de buton din extrema stângă"</string> @@ -673,8 +671,8 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Anumite funcții sunt limitate în timp ce telefonul se răcește.\nAtingeți pentru mai multe informații"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"Telefonul va încerca automat să se răcească. Puteți folosi telefonul în continuare, dar este posibil să funcționeze mai lent.\n\nDupă ce se răcește, telefonul va funcționa normal."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Vedeți pașii pentru îngrijire"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Deconectați încărcătorul"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"Există o problemă la încărcarea acestui dispozitiv. Deconectați adaptorul de curent și aveți grijă, deoarece cablul poate fi cald."</string> + <string name="high_temp_alarm_title" msgid="8654754369605452169">"Deconectează dispozitivul"</string> + <string name="high_temp_alarm_notify_message" msgid="3917622943609118956">"Dispozitivul se încălzește lângă portul de încărcare. Dacă este conectat la un încărcător sau accesoriu USB, deconectează-l și ai grijă, deoarece și cablul poate fi cald."</string> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"Vedeți pașii pentru îngrijire"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Comanda rapidă din stânga"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"Comanda rapidă din dreapta"</string> diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml index 6a8ee315e84b..adda24d30ae5 100644 --- a/packages/SystemUI/res/values-ru/strings.xml +++ b/packages/SystemUI/res/values-ru/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Не удалось распознать лицо. Используйте отпечаток."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"Лицо не распознано."</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Используйте отпечаток."</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth-соединение установлено."</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Уровень заряда батареи в процентах неизвестен."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g>: подключено."</string> @@ -423,10 +421,8 @@ <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Наложение субтитров"</string> <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"включить"</string> <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"отключить"</string> - <!-- no translation found for sound_settings (8874581353127418308) --> - <skip /> - <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) --> - <skip /> + <string name="sound_settings" msgid="8874581353127418308">"Звук и вибрация"</string> + <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Открыть настройки"</string> <string name="screen_pinning_title" msgid="9058007390337841305">"Приложение закреплено"</string> <string name="screen_pinning_description" msgid="8699395373875667743">"Приложение останется активным, пока вы не отмените блокировку, нажав и удерживая кнопки \"Назад\" и \"Обзор\"."</string> <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Приложение останется активным, пока вы не отмените блокировку, нажав и удерживая кнопки \"Назад\" и \"Главный экран\"."</string> @@ -602,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"Вкл."</string> <string name="switch_bar_off" msgid="5669805115416379556">"Откл."</string> <string name="tile_unavailable" msgid="3095879009136616920">"Недоступно"</string> - <string name="tile_disabled" msgid="373212051546573069">"Отключено"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"узнать больше"</string> <string name="nav_bar" msgid="4642708685386136807">"Панель навигации"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"Расположение кнопок"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Дополнительный тип кнопки \"Влево\""</string> @@ -675,8 +671,10 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Пока телефон не остынет, некоторые функции могут быть недоступны.\nНажмите, чтобы получить дополнительную информацию"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"Ваш телефон остынет автоматически.\n\nОбратите внимание, что до тех пор он может работать медленнее, чем обычно."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Подробнее о действиях при перегреве…"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Отключите зарядное устройство"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"Во время зарядки возникла проблема. Отключите адаптер питания. Будьте осторожны, кабель может быть горячим."</string> + <!-- no translation found for high_temp_alarm_title (8654754369605452169) --> + <skip /> + <!-- no translation found for high_temp_alarm_notify_message (3917622943609118956) --> + <skip /> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"Подробнее о действиях при перегреве…"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Ярлык слева"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"Ярлык справа"</string> diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml index bbf1619c8c53..be32cc5c75b0 100644 --- a/packages/SystemUI/res/values-si/strings.xml +++ b/packages/SystemUI/res/values-si/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"මුහුණ හැඳිනිය නොහැක. ඒ වෙනුවට ඇඟිලි සලකුණ භාවිත ක."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"මුහුණ හඳුනා ගත නොහැක"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"ඒ වෙනුවට ඇඟිලි සලකුණ භාවිත කරන්න"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"බ්ලූටූත් සම්බන්ධිතයි."</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"බැටරි ප්රතිශතය නොදනී."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> වෙත සම්බන්ධ කරන ලදි."</string> @@ -423,10 +421,8 @@ <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"සිරස්තල උඩැතිරිය"</string> <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"සබල කරන්න"</string> <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"අබල කරන්න"</string> - <!-- no translation found for sound_settings (8874581353127418308) --> - <skip /> - <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) --> - <skip /> + <string name="sound_settings" msgid="8874581353127418308">"ශබ්ද සහ කම්පනය"</string> + <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"සැකසීම්"</string> <string name="screen_pinning_title" msgid="9058007390337841305">"යෙදුම අමුණා ඇත"</string> <string name="screen_pinning_description" msgid="8699395373875667743">"මෙය ඔබ ගලවන තෙක් එය දසුන තුළ තබයි. ගැලවීමට දළ විශ්ලේෂණය ස්පර්ශ කර ආපසු අල්ලාගෙන සිටින්න."</string> <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"මෙය ඔබ ගලවන තෙක් එය දසුන තුළ තබයි. ගැලවීමට මුල් පිටුව ස්පර්ශ කර අල්ලාගෙන සිටින්න."</string> @@ -602,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"ක්රියාත්මකයි"</string> <string name="switch_bar_off" msgid="5669805115416379556">"ක්රියාවිරහිතයි"</string> <string name="tile_unavailable" msgid="3095879009136616920">"ලබා ගත නොහැකිය"</string> - <string name="tile_disabled" msgid="373212051546573069">"අබලයි"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"තව දැන ගන්න"</string> <string name="nav_bar" msgid="4642708685386136807">"සංචලන තීරුව"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"පිරිසැලසුම"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"අමතර වම් බොත්තම් වර්ගය"</string> @@ -675,8 +671,10 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"දුරකථනය සිසිල් වන අතරතුර සමහර විශේෂාංග සීමිත විය හැකිය.\nතව තතු සඳහා තට්ටු කරන්න"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"ඔබගේ දුරකථනය ස්වයංක්රියව සිසිල් වීමට උත්සාහ කරනු ඇත. ඔබට තවම ඔබේ දුරකථනය භාවිත කළ හැකිය, නමුත් එය සෙමින් ධාවනය විය හැකිය.\n\nඔබේ දුරකථනය සිසිල් වූ පසු, එය සාමාන්ය ලෙස ධාවනය වනු ඇත."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"රැකවරණ පියවර බලන්න"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"චාජරය පේනුවෙන් ඉවත් කරන්න"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"මෙම උපාංගය ආරෝපණ කිරීමේ ගැටලුවක් තිබේ බල ඇඩැප්ටරය ගලවා කේබලය උණුසුම් විය හැකි බැවින් පරෙස්සම් වන්න."</string> + <!-- no translation found for high_temp_alarm_title (8654754369605452169) --> + <skip /> + <!-- no translation found for high_temp_alarm_notify_message (3917622943609118956) --> + <skip /> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"රැකවරණ පියවර බලන්න"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"වම් කෙටි මග"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"දකුණු කෙටි මග"</string> diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml index 96880911356b..ce512934511f 100644 --- a/packages/SystemUI/res/values-sk/strings.xml +++ b/packages/SystemUI/res/values-sk/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Tvár sa nedá rozpoznať. Použite odtlačok prsta."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"Tvár sa nedá rozpoznať"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Používať radšej odtlačok"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth pripojené."</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Percento batérie nie je známe."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Pripojené k zariadeniu <xliff:g id="BLUETOOTH">%s</xliff:g>."</string> @@ -600,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"Zapnuté"</string> <string name="switch_bar_off" msgid="5669805115416379556">"Vypnuté"</string> <string name="tile_unavailable" msgid="3095879009136616920">"Nedostupné"</string> - <string name="tile_disabled" msgid="373212051546573069">"Deaktivované"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"ďalšie informácie"</string> <string name="nav_bar" msgid="4642708685386136807">"Navigačný panel"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"Rozloženie"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Dodatočný typ ľavého tlačidla"</string> @@ -673,8 +671,8 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Niektoré funkcie budú obmedzené, dokým neklesne teplota telefónu.\nViac sa dozviete po klepnutí."</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"Váš telefón sa automaticky pokúsi schladiť. Môžete ho naďalej používať, ale môže fungovať pomalšie.\n\nPo poklese teploty bude telefón fungovať ako normálne."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Zobraziť opatrenia"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Odpojte nabíjačku"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"Vyskytol sa problém s nabíjaním tohto zariadenia. Odpojte nabíjačku a postupujte opatrne, pretože kábel môže byť horúci."</string> + <string name="high_temp_alarm_title" msgid="8654754369605452169">"Odpojte zariadenie"</string> + <string name="high_temp_alarm_notify_message" msgid="3917622943609118956">"Zariadenie sa zahrieva pri nabíjacom porte. Ak je pripojené k nabíjačke alebo príslušenstvu USB, odpojte ho a dajte pozor, lebo môže byť horúci aj kábel."</string> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"Zobraziť opatrenia"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Ľavá skratka"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"Pravá skratka"</string> diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml index f9ab048b0436..620d9b530376 100644 --- a/packages/SystemUI/res/values-sl/strings.xml +++ b/packages/SystemUI/res/values-sl/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Obraza ni mogoče prepoznati. Uporabite prstni odtis."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"Obraz ni bil prepoznan."</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Uporabite prstni odtis."</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Povezava Bluetooth vzpostavljena."</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Neznan odstotek napolnjenosti baterije."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Povezava vzpostavljena z: <xliff:g id="BLUETOOTH">%s</xliff:g>."</string> @@ -600,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"Vklopljeno"</string> <string name="switch_bar_off" msgid="5669805115416379556">"Izklopljeno"</string> <string name="tile_unavailable" msgid="3095879009136616920">"Ni na voljo"</string> - <string name="tile_disabled" msgid="373212051546573069">"Onemogočeno"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"za več informacij"</string> <string name="nav_bar" msgid="4642708685386136807">"Vrstica za krmarjenje"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"Postavitev"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Vrsta dodatnega levega gumba"</string> @@ -673,8 +671,8 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Nekatere funkcije bodo med ohlajanjem telefona omejene.\nDotaknite se za več informacij"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"Telefon se bo samodejno poskusil ohladiti. Še naprej ga lahko uporabljate, vendar bo morda deloval počasneje.\n\nKo se telefon ohladi, bo zopet deloval kot običajno."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Oglejte si navodila za ukrepanje"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Odklopite polnilnik"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"Pri polnjenju te naprave je prišlo do težave. Previdno odklopite napajalnik, ker se je kabel morda segrel."</string> + <string name="high_temp_alarm_title" msgid="8654754369605452169">"Odklopite napravo"</string> + <string name="high_temp_alarm_notify_message" msgid="3917622943609118956">"Naprava se segreva pri vratih za polnjenje. Če je priključena na polnilnik ali dodatek USB, ga odklopite in bodite tem previdni, saj je tudi kabel lahko topel."</string> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"Oglejte si navodila za ukrepanje"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Leva bližnjica"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"Desna bližnjica"</string> diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml index c8a0f24cd585..4d0481a9d1da 100644 --- a/packages/SystemUI/res/values-sq/strings.xml +++ b/packages/SystemUI/res/values-sq/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Nuk mund ta dallojë fytyrën. Përdor më mirë gjurmën e gishtit."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"Fytyra nuk mund të njihet"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Përdor më mirë gjurmën e gishtit"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Pajisja është lidhur me \"bluetooth\"."</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Përqindja e baterisë e panjohur."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Lidhur me <xliff:g id="BLUETOOTH">%s</xliff:g>"</string> @@ -423,10 +421,8 @@ <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Mbivendosja e titrave"</string> <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"aktivizo"</string> <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"çaktivizo"</string> - <!-- no translation found for sound_settings (8874581353127418308) --> - <skip /> - <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) --> - <skip /> + <string name="sound_settings" msgid="8874581353127418308">"Tingulli dhe dridhjet"</string> + <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Cilësimet"</string> <string name="screen_pinning_title" msgid="9058007390337841305">"Aplikacioni është i gozhduar"</string> <string name="screen_pinning_description" msgid="8699395373875667743">"Kjo e ruan në pamje deri sa ta heqësh nga gozhdimi. Prek dhe mbaj të shtypur \"Prapa\" dhe \"Përmbledhje\" për ta hequr nga gozhdimi."</string> <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Kjo e ruan në pamje deri sa ta heqësh nga gozhdimi. Prek dhe mbaj të shtypur \"Prapa\" dhe \"Kreu\" për ta hequr nga gozhdimi."</string> @@ -602,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"Aktiv"</string> <string name="switch_bar_off" msgid="5669805115416379556">"Joaktiv"</string> <string name="tile_unavailable" msgid="3095879009136616920">"Nuk ofrohet"</string> - <string name="tile_disabled" msgid="373212051546573069">"Joaktiv"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"mëso më shumë"</string> <string name="nav_bar" msgid="4642708685386136807">"Shiriti i navigimit"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"Struktura"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Lloji i butonit shtesë majtas"</string> @@ -675,8 +671,10 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Disa veçori janë të kufizuara kur telefoni është duke u ftohur.\nTrokit për më shumë informacione"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"Telefoni yt do të përpiqet automatikisht që të ftohet. Mund ta përdorësh përsëri telefonin, por ai mund të punojë më ngadalë.\n\nPasi telefoni të jetë ftohur, ai do të punojë si normalisht."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Shiko hapat për kujdesin"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Shkëput karikuesin"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"Ka një problem me karikimin e kësaj pajisjeje. Hiqe spinën dhe trego kujdes pasi kablloja mund të jetë e ngrohtë."</string> + <!-- no translation found for high_temp_alarm_title (8654754369605452169) --> + <skip /> + <!-- no translation found for high_temp_alarm_notify_message (3917622943609118956) --> + <skip /> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"Shiko hapat për kujdesin"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Shkurtorja majtas"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"Shkurtorja djathtas"</string> diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml index 80f4d203e4cf..f7ef6543252e 100644 --- a/packages/SystemUI/res/values-sr/strings.xml +++ b/packages/SystemUI/res/values-sr/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Лице није препознато. Користите отисак прста."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"Лице није препознато"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Користите отисак прста"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth је прикључен."</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Проценат напуњености батерије није познат."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Повезани сте са <xliff:g id="BLUETOOTH">%s</xliff:g>."</string> @@ -423,10 +421,8 @@ <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Преклапање титлова"</string> <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"омогућите"</string> <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"онемогућите"</string> - <!-- no translation found for sound_settings (8874581353127418308) --> - <skip /> - <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) --> - <skip /> + <string name="sound_settings" msgid="8874581353127418308">"Звук и вибрирање"</string> + <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Подешавања"</string> <string name="screen_pinning_title" msgid="9058007390337841305">"Апликација је закачена"</string> <string name="screen_pinning_description" msgid="8699395373875667743">"На овај начин се ово стално приказује док га не откачите. Додирните и задржите Назад и Преглед да бисте га откачили."</string> <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"На овај начин се ово стално приказује док га не откачите. Додирните и задржите Назад и Почетна да бисте га откачили."</string> @@ -602,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"Укључено"</string> <string name="switch_bar_off" msgid="5669805115416379556">"Искључено"</string> <string name="tile_unavailable" msgid="3095879009136616920">"Недоступно"</string> - <string name="tile_disabled" msgid="373212051546573069">"Онемогућено"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"сазнајте више"</string> <string name="nav_bar" msgid="4642708685386136807">"Трака за навигацију"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"Распоред"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Додатни тип левог дугмета"</string> @@ -675,8 +671,8 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Неке функције су ограничене док се телефон не охлади.\nДодирните за више информација"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"Телефон ће аутоматски покушати да се охлади. И даље ћете моћи да користите телефон, али ће спорије реаговати.\n\nКада се телефон охлади, нормално ће радити."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Погледајте упозорења"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Искључите пуњач из струје"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"Дошло је до проблема са пуњењем овог уређаја. Искључите адаптер из напајања и будите пажљиви јер кабл може да буде топао."</string> + <string name="high_temp_alarm_title" msgid="8654754369605452169">"Искључите уређај"</string> + <string name="high_temp_alarm_notify_message" msgid="3917622943609118956">"Уређај се загрева у близини порта за пуњење. Ако је повезан са пуњачем или USB опремом, искључите је и будите пажљиви јер и кабл може да буде врућ."</string> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"Погледајте упозорења"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Лева пречица"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"Десна пречица"</string> diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml index 912fbf7b0511..6d771756479b 100644 --- a/packages/SystemUI/res/values-sv/strings.xml +++ b/packages/SystemUI/res/values-sv/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Ansiktet kändes inte igen. Använd fingeravtryck."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"Ansiktet kändes inte igen"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Använd fingeravtryck"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth ansluten."</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Okänd batterinivå."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Ansluten till <xliff:g id="BLUETOOTH">%s</xliff:g>."</string> @@ -600,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"På"</string> <string name="switch_bar_off" msgid="5669805115416379556">"Av"</string> <string name="tile_unavailable" msgid="3095879009136616920">"Inte tillgängligt"</string> - <string name="tile_disabled" msgid="373212051546573069">"Inaktiverat"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"läs mer"</string> <string name="nav_bar" msgid="4642708685386136807">"Navigeringsfält"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"Layout"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Knapptyp för extra vänster"</string> @@ -673,8 +671,10 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Vissa funktioner är begränsade medan telefonen svalnar.\nTryck för mer information"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"Mobilen försöker svalna automatiskt. Du kan fortfarande använda mobilen, men den kan vara långsammare än vanligt.\n\nMobilen fungerar som vanligt när den har svalnat."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Visa alla skötselråd"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Koppla ur laddaren"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"Det går inte att ladda denna enhet. Koppla ur nätadaptern, men var försiktig eftersom kabeln kan vara varm."</string> + <!-- no translation found for high_temp_alarm_title (8654754369605452169) --> + <skip /> + <!-- no translation found for high_temp_alarm_notify_message (3917622943609118956) --> + <skip /> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"Visa alla skötselråd"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Vänster genväg"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"Höger genväg"</string> diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml index 9b7de6299aea..29db51296622 100644 --- a/packages/SystemUI/res/values-sw/strings.xml +++ b/packages/SystemUI/res/values-sw/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Imeshindwa kutambua uso. Tumia alama ya kidole."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"Imeshindwa kutambua uso"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Badala yake, tumia alama ya kidole"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth imeunganishwa."</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Asilimia ya betri haijulikani."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Imeunganishwa kwenye <xliff:g id="BLUETOOTH">%s</xliff:g>."</string> @@ -600,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"Imewashwa"</string> <string name="switch_bar_off" msgid="5669805115416379556">"Imezimwa"</string> <string name="tile_unavailable" msgid="3095879009136616920">"Hakipatikani"</string> - <string name="tile_disabled" msgid="373212051546573069">"Imezimwa"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"pata maelezo zaidi"</string> <string name="nav_bar" msgid="4642708685386136807">"Sehemu ya viungo muhimu"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"Mpangilio"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Aina ya kitufe cha kushoto cha ziada"</string> @@ -673,8 +671,10 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Baadhi ya vipengele havitatumika kwenye simu wakati inapoa.\nGusa ili upate maelezo zaidi"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"Simu yako itajaribu kupoa kiotomatiki. Bado unaweza kutumia simu yako, lakini huenda ikafanya kazi polepole. \n\nPindi simu yako itakapopoa, itaendelea kufanya kazi kama kawaida."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Angalia hatua za utunzaji"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Chomoa chaja"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"Kuna tatizo la kuchaji kifaa hiki. Chomoa adapta ya nishati na uwe mwangalifu, huenda kebo ni moto."</string> + <!-- no translation found for high_temp_alarm_title (8654754369605452169) --> + <skip /> + <!-- no translation found for high_temp_alarm_notify_message (3917622943609118956) --> + <skip /> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"Angalia hatua za ulinzi"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Njia ya mkato ya kushoto"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"Njia ya mkato ya kulia"</string> diff --git a/packages/SystemUI/res/values-sw600dp-land/dimens.xml b/packages/SystemUI/res/values-sw600dp-land/dimens.xml index d638c9d5742e..f4d482406fa0 100644 --- a/packages/SystemUI/res/values-sw600dp-land/dimens.xml +++ b/packages/SystemUI/res/values-sw600dp-land/dimens.xml @@ -49,54 +49,29 @@ <dimen name="status_view_margin_horizontal">8dp</dimen> - <!-- Distance that the full shade transition takes in order to complete by tapping on a button - like "expand". --> + <!-- Lockscreen shade transition values --> <dimen name="lockscreen_shade_transition_by_tap_distance">200dp</dimen> - - <!-- Distance that the full shade transition takes in order to complete. --> <dimen name="lockscreen_shade_full_transition_distance">200dp</dimen> - - <!-- Distance that the full shade transition takes in order for media to fully transition to - the shade --> - <dimen name="lockscreen_shade_media_transition_distance">200dp</dimen> - - <!-- Distance that the full shade transition takes in order for scrim to fully transition to - the shade (in alpha) --> + <!-- Media transition distance = qs delay + qs distance --> + <dimen name="lockscreen_shade_media_transition_distance">129.28dp</dimen> <dimen name="lockscreen_shade_scrim_transition_distance">80dp</dimen> - <!-- The notifications scrim transition should start when the other scrims' transition is at 95%. --> <dimen name="lockscreen_shade_notifications_scrim_transition_delay">76dp</dimen> - <!-- The notifications scrim transition duration is 66.6% of the duration of the other scrims' - transition. --> + transition. --> <dimen name="lockscreen_shade_notifications_scrim_transition_distance">53.28dp</dimen> - - <!-- Distance that the full shade transition takes in order for the keyguard content on - NotificationPanelViewController to fully fade (e.g. Clock & Smartspace) --> <dimen name="lockscreen_shade_npvc_keyguard_content_alpha_transition_distance">80dp</dimen> - - <!-- Distance that the full shade transition takes in order for the notification shell to fully - expand. --> <dimen name="lockscreen_shade_notif_shelf_transition_distance">@dimen/lockscreen_shade_full_transition_distance</dimen> - - <!-- Distance that the full shade transition takes in order for the Quick Settings to fully - fade and expand. --> - <dimen name="lockscreen_shade_qs_transition_distance">@dimen/lockscreen_shade_full_transition_distance</dimen> - - <!-- Distance that the full shade transition takes in order for depth of the wallpaper to fully - change. - On split-shade, there should be no depth effect, so setting the value to 0. --> + <dimen name="lockscreen_shade_qs_transition_distance">@dimen/lockscreen_shade_notifications_scrim_transition_distance</dimen> + <dimen name="lockscreen_shade_qs_transition_delay">@dimen/lockscreen_shade_notifications_scrim_transition_delay</dimen> + <dimen name="lockscreen_shade_qs_squish_transition_distance">@dimen/lockscreen_shade_qs_transition_distance</dimen> + <!-- On split-shade, the QS squish transition should start from half height. --> + <item name="lockscreen_shade_qs_squish_start_fraction" type="dimen" format="float" >0.5</item> + <!-- On split-shade, there should be no depth effect, so setting the value to 0. --> <dimen name="lockscreen_shade_depth_controller_transition_distance">0dp</dimen> - - <!-- Distance that the full shade transition takes in order for the UDFPS Keyguard View to fully - fade. --> <dimen name="lockscreen_shade_udfps_keyguard_transition_distance">@dimen/lockscreen_shade_full_transition_distance</dimen> - - <!-- Used for StatusBar to know that a transition is in progress. At the moment it only checks - whether the progress is > 0, therefore this value is not very important. --> <dimen name="lockscreen_shade_status_bar_transition_distance">@dimen/lockscreen_shade_full_transition_distance</dimen> - <dimen name="lockscreen_shade_keyguard_transition_distance">@dimen/lockscreen_shade_media_transition_distance</dimen> <!-- Roughly the same distance as media on LS to media on QS. We will translate by this value diff --git a/packages/SystemUI/res/values-sw600dp/config.xml b/packages/SystemUI/res/values-sw600dp/config.xml index c0071cb45e21..80628f903e76 100644 --- a/packages/SystemUI/res/values-sw600dp/config.xml +++ b/packages/SystemUI/res/values-sw600dp/config.xml @@ -35,9 +35,6 @@ <!-- How many lines to show in the security footer --> <integer name="qs_security_footer_maxLines">1</integer> - <!-- Determines whether to allow the nav bar handle to be forced to be opaque. --> - <bool name="allow_force_nav_bar_handle_opaque">false</bool> - <bool name="config_use_large_screen_shade_header">true</bool> <!-- Whether to show the side fps hint while on bouncer --> diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml index 008299bd9b1c..a587e5a806ca 100644 --- a/packages/SystemUI/res/values-sw600dp/dimens.xml +++ b/packages/SystemUI/res/values-sw600dp/dimens.xml @@ -73,4 +73,24 @@ <dimen name="large_dialog_width">472dp</dimen> <dimen name="large_screen_shade_header_height">42dp</dimen> + + <!-- Lockscreen shade transition values --> + <dimen name="lockscreen_shade_transition_by_tap_distance">200dp</dimen> + <dimen name="lockscreen_shade_full_transition_distance">80dp</dimen> + <dimen name="lockscreen_shade_media_transition_distance">120dp</dimen> + <dimen name="lockscreen_shade_scrim_transition_distance">@dimen/lockscreen_shade_full_transition_distance</dimen> + <dimen name="lockscreen_shade_notifications_scrim_transition_delay">@dimen/lockscreen_shade_scrim_transition_distance</dimen> + <dimen name="lockscreen_shade_notifications_scrim_transition_distance">@dimen/lockscreen_shade_scrim_transition_distance</dimen> + <dimen name="lockscreen_shade_npvc_keyguard_content_alpha_transition_distance">@dimen/lockscreen_shade_full_transition_distance</dimen> + <dimen name="lockscreen_shade_notif_shelf_transition_distance">@dimen/lockscreen_shade_full_transition_distance</dimen> + <dimen name="lockscreen_shade_qs_transition_distance">@dimen/lockscreen_shade_full_transition_distance</dimen> + <dimen name="lockscreen_shade_qs_transition_delay">@dimen/lockscreen_shade_scrim_transition_distance</dimen> + <dimen name="lockscreen_shade_qs_squish_transition_distance">@dimen/lockscreen_shade_qs_transition_distance</dimen> + <!-- On large screen portrait, the QS squish transition should start from half height. --> + <item name="lockscreen_shade_qs_squish_start_fraction" type="dimen" format="float" >0.5</item> + <dimen name="lockscreen_shade_depth_controller_transition_distance">@dimen/lockscreen_shade_full_transition_distance</dimen> + <dimen name="lockscreen_shade_udfps_keyguard_transition_distance">@dimen/lockscreen_shade_full_transition_distance</dimen> + <dimen name="lockscreen_shade_status_bar_transition_distance">@dimen/lockscreen_shade_full_transition_distance</dimen> + <dimen name="lockscreen_shade_keyguard_transition_distance">@dimen/lockscreen_shade_media_transition_distance</dimen> + </resources> diff --git a/packages/SystemUI/res/values-sw720dp-port/dimens.xml b/packages/SystemUI/res/values-sw720dp-port/dimens.xml index a0bf072ed27c..3d8da8a6c3e8 100644 --- a/packages/SystemUI/res/values-sw720dp-port/dimens.xml +++ b/packages/SystemUI/res/values-sw720dp-port/dimens.xml @@ -23,7 +23,7 @@ <dimen name="status_view_margin_horizontal">124dp</dimen> <dimen name="keyguard_clock_top_margin">80dp</dimen> <dimen name="keyguard_status_view_bottom_margin">80dp</dimen> - <dimen name="bouncer_user_switcher_y_trans">90dp</dimen> + <dimen name="bouncer_user_switcher_y_trans">200dp</dimen> <dimen name="large_screen_shade_header_left_padding">24dp</dimen> <dimen name="qqs_layout_padding_bottom">40dp</dimen> diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml index 496accae38d5..0550387435bc 100644 --- a/packages/SystemUI/res/values-ta/strings.xml +++ b/packages/SystemUI/res/values-ta/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"முகத்தை அடையாளம் காண முடியவில்லை. கைரேகையைப் பயன்படுத்தவும்."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"முகத்தை கண்டறிய இயலவில்லை"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"கைரேகையை உபயோகிக்கவும்"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"புளூடூத் இணைக்கப்பட்டது."</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"பேட்டரி சதவீதம் தெரியவில்லை."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g>க்கு இணைக்கப்பட்டது."</string> @@ -600,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"ஆன்"</string> <string name="switch_bar_off" msgid="5669805115416379556">"ஆஃப்"</string> <string name="tile_unavailable" msgid="3095879009136616920">"இல்லை"</string> - <string name="tile_disabled" msgid="373212051546573069">"முடக்கப்பட்டது"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"மேலும் அறிக"</string> <string name="nav_bar" msgid="4642708685386136807">"வழிசெலுத்தல் பட்டி"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"தளவமைப்பு"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"கூடுதல் இடப்புற பட்டன் வகை"</string> @@ -673,8 +671,8 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"மொபைலின் வெப்ப அளவு குறையும் வரை சில அம்சங்களைப் பயன்படுத்த முடியாது.\nமேலும் தகவலுக்கு தட்டவும்"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"உங்கள் மொபைலின் வெப்ப அளவு தானாகவே குறையும். தொடர்ந்து நீங்கள் மொபைலைப் பயன்படுத்தலாம், ஆனால் அதன் வேகம் குறைவாக இருக்கக்கூடும்.\n\nமொபைலின் வெப்ப அளவு குறைந்தவுடன், அது இயல்பு நிலையில் இயங்கும்."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"மேலும் விவரங்களுக்கு இதைப் பார்க்கவும்"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"சார்ஜரைத் துண்டிக்கவும்"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"இந்தச் சாதனத்தைச் சார்ஜ் செய்வதில் சிக்கல் உள்ளது. பவர் அடாப்டரைத் துண்டிக்கவும், கேபிள் சூடாக இருக்கக்கூடும் என்பதால் கவனமாகக் கையாளவும்."</string> + <string name="high_temp_alarm_title" msgid="8654754369605452169">"சாதன இணைப்பைத் துண்டித்தல்"</string> + <string name="high_temp_alarm_notify_message" msgid="3917622943609118956">"சார்ஜிங் போர்ட்டிற்கு அருகே உங்கள் சாதனம் சூடாகிறது. சார்ஜருடனோ USB உபகரணத்துடனோ சாதனம் இணைக்கப்பட்டிருந்தால் அதன் இணைப்பைத் துண்டிக்கவும். கேபிளும் சூடாக இருக்கக்கூடும் என்பதால் கவனத்துடன் கையாளவும்."</string> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"மேலும் விவரங்களுக்கு இதைப் பார்க்கவும்"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"இடப்புற ஷார்ட்கட்"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"வலப்புற ஷார்ட்கட்"</string> diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml index 27a9fa38a37e..1e4fce675845 100644 --- a/packages/SystemUI/res/values-te/strings.xml +++ b/packages/SystemUI/res/values-te/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"ముఖం గుర్తించలేము. బదులుగా వేలిముద్ర ఉపయోగించండి."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"ముఖం గుర్తించడం కుదరలేదు"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"బదులుగా వేలిముద్రను ఉపయోగించండి"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"బ్లూటూత్ కనెక్ట్ చేయబడింది."</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"బ్యాటరీ శాతం తెలియదు."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g>కి కనెక్ట్ చేయబడింది."</string> @@ -600,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"ఆన్"</string> <string name="switch_bar_off" msgid="5669805115416379556">"ఆఫ్ చేయి"</string> <string name="tile_unavailable" msgid="3095879009136616920">"అందుబాటులో లేదు"</string> - <string name="tile_disabled" msgid="373212051546573069">"డిజేబుల్ చేయబడింది"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"మరింత తెలుసుకోండి"</string> <string name="nav_bar" msgid="4642708685386136807">"నావిగేషన్ బార్"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"లేఅవుట్"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"అత్యంత ఎడమ వైపు ఉన్న బటన్ రకం"</string> @@ -673,8 +671,8 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"ఫోన్ను చల్లబరిచే క్రమంలో కొన్ని ఫీచర్లు పరిమితం చేయబడ్డాయి.\nమరింత సమాచారం కోసం ట్యాప్ చేయండి"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"మీ ఫోన్ ఆటోమేటిక్గా చల్లబడటానికి ప్రయత్నిస్తుంది. మీరు ఇప్పటికీ మీ ఫోన్ను ఉపయోగించవచ్చు, కానీ దాని పనితీరు నెమ్మదిగా ఉండవచ్చు.\n\nమీ ఫోన్ చల్లబడిన తర్వాత, అది సాధారణ రీతిలో పని చేస్తుంది."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"తీసుకోవాల్సిన జాగ్రత్తలు ఏమిటో చూడండి"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"ప్లగ్ నుండి ఛార్జర్ తీసివేయండి"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"ఈ పరికరాన్ని ఛార్జ్ చేయడంలో సమస్య ఉంది. పవర్ అడాప్టర్ను ప్లగ్ నుండి తీసివేసి, కేబుల్ ఏమైనా వేడిగా అయితే తగిన జాగ్రత్తలు తీసుకోండి."</string> + <string name="high_temp_alarm_title" msgid="8654754369605452169">"మీ పరికరాన్ని అన్ప్లగ్ చేయండి"</string> + <string name="high_temp_alarm_notify_message" msgid="3917622943609118956">"ఛార్జింగ్ పోర్ట్ దగ్గర ఉంచినప్పుడు మీ పరికరం వేడెక్కుతోంది. ఇది ఛార్జర్ లేదా USB యాక్సెసరీకి కనెక్ట్ చేసి ఉంటే, దాన్ని అన్ప్లగ్ చేసి, కేబుల్ వేడెక్కే అవకాశం కూడా ఉన్నందున జాగ్రత్త వహించండి."</string> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"తీసుకోవాల్సిన జాగ్రత్తలు ఏమిటో చూడండి"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"ఎడమవైపు షార్ట్కట్"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"కుడివైపు షార్ట్కట్"</string> diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml index 2575939c2bb0..3e8de0de323c 100644 --- a/packages/SystemUI/res/values-th/strings.xml +++ b/packages/SystemUI/res/values-th/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"ไม่รู้จักใบหน้า ใช้ลายนิ้วมือแทน"</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"ไม่รู้จักใบหน้า"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"ใช้ลายนิ้วมือแทน"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"เชื่อมต่อบลูทูธแล้ว"</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"ไม่ทราบเปอร์เซ็นต์แบตเตอรี่"</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"เชื่อมต่อกับ <xliff:g id="BLUETOOTH">%s</xliff:g> แล้ว"</string> @@ -600,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"เปิด"</string> <string name="switch_bar_off" msgid="5669805115416379556">"ปิด"</string> <string name="tile_unavailable" msgid="3095879009136616920">"ไม่พร้อมใช้งาน"</string> - <string name="tile_disabled" msgid="373212051546573069">"ปิดใช้"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"ดูข้อมูลเพิ่มเติม"</string> <string name="nav_bar" msgid="4642708685386136807">"แถบนำทาง"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"การจัดวาง"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"ประเภทปุ่มทางซ้ายเพิ่มเติม"</string> @@ -673,8 +671,10 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"ฟีเจอร์บางอย่างจะใช้งานได้จำกัดขณะโทรศัพท์เย็นลง\nแตะเพื่อดูข้อมูลเพิ่มเติม"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"โทรศัพท์จะพยายามลดอุณหภูมิลงโดยอัตโนมัติ คุณยังสามารถใช้โทรศัพท์ได้ แต่โทรศัพท์อาจทำงานช้าลง\n\nโทรศัพท์จะทำงานตามปกติเมื่อเย็นลงแล้ว"</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"ดูขั้นตอนในการดูแลรักษา"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"ถอดปลั๊กที่ชาร์จ"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"พบปัญหาในการชาร์จอุปกรณ์นี้ ถอดปลั๊กอะแดปเตอร์ด้วยความระมัดระวังเพราะสายอาจร้อน"</string> + <!-- no translation found for high_temp_alarm_title (8654754369605452169) --> + <skip /> + <!-- no translation found for high_temp_alarm_notify_message (3917622943609118956) --> + <skip /> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"ดูขั้นตอนในการดูแลรักษา"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"ทางลัดทางซ้าย"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"ทางลัดทางขวา"</string> diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml index a45c6732774d..c32aa99159ce 100644 --- a/packages/SystemUI/res/values-tl/strings.xml +++ b/packages/SystemUI/res/values-tl/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Hindi makilala ang mukha. Gumamit ng fingerprint."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"Hindi makilala ang mukha"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Gumamit ng fingerprint"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Nakakonekta ang Bluetooth."</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Hindi alam ang porsyento ng baterya."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Nakakonekta sa <xliff:g id="BLUETOOTH">%s</xliff:g>."</string> @@ -423,10 +421,8 @@ <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Overlay ng mga caption"</string> <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"i-enable"</string> <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"i-disable"</string> - <!-- no translation found for sound_settings (8874581353127418308) --> - <skip /> - <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) --> - <skip /> + <string name="sound_settings" msgid="8874581353127418308">"Tunog at pag-vibrate"</string> + <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Mga Setting"</string> <string name="screen_pinning_title" msgid="9058007390337841305">"Naka-pin ang app"</string> <string name="screen_pinning_description" msgid="8699395373875667743">"Pinapanatili nitong nakikita ito hanggang sa mag-unpin ka. Pindutin nang matagal ang Bumalik at Overview upang mag-unpin."</string> <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Pinapanatili nitong nakikita ito hanggang sa mag-unpin ka. Pindutin nang matagal ang Bumalik at Home upang mag-unpin."</string> @@ -602,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"I-on"</string> <string name="switch_bar_off" msgid="5669805115416379556">"I-off"</string> <string name="tile_unavailable" msgid="3095879009136616920">"Hindi available"</string> - <string name="tile_disabled" msgid="373212051546573069">"Naka-disable"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"matuto pa"</string> <string name="nav_bar" msgid="4642708685386136807">"Navigation bar"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"Layout"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Uri ng extra na button ng kaliwa"</string> @@ -675,8 +671,8 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Limitado ang ilang feature habang nagku-cool down ang telepono.\nMag-tap para sa higit pang impormasyon"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"Awtomatikong susubukan ng iyong telepono na mag-cool down. Magagamit mo pa rin ang iyong telepono, ngunit maaaring mas mabagal ang paggana nito.\n\nKapag nakapag-cool down na ang iyong telepono, gagana na ito nang normal."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Tingnan ang mga hakbang sa pangangalaga"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Hugutin ang charger"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"May isyu sa pag-charge ng device na ito. Hugutin ang power adapter at mag-ingat dahil maaaring mainit ang cable."</string> + <string name="high_temp_alarm_title" msgid="8654754369605452169">"Bunutin sa saksakan ang device"</string> + <string name="high_temp_alarm_notify_message" msgid="3917622943609118956">"Umiinit ang iyong device malapit sa charging port. Kung nakakonekta ito sa charger o USB accessory, bunutin ito sa saksakan, at mag-ingat dahil posibleng mainit din ang cable."</string> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"Tingnan ang mga hakbang sa pangangalaga"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Kaliwang shortcut"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"Kanang shortcut"</string> diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml index 6d9d0f230bdf..217dc21e66fb 100644 --- a/packages/SystemUI/res/values-tr/strings.xml +++ b/packages/SystemUI/res/values-tr/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Yüz tanınamadı. Bunun yerine parmak izi kullanın."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"Yüz tanınamadı"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Bunun yerine parmak izi kullanın"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth bağlandı."</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Pil yüzdesi bilinmiyor."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> ile bağlı."</string> @@ -423,10 +421,8 @@ <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Altyazı yer paylaşımı"</string> <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"etkinleştir"</string> <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"devre dışı bırak"</string> - <!-- no translation found for sound_settings (8874581353127418308) --> - <skip /> - <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) --> - <skip /> + <string name="sound_settings" msgid="8874581353127418308">"Ses ve titreşim"</string> + <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Ayarlar"</string> <string name="screen_pinning_title" msgid="9058007390337841305">"Uygulama sabitlendi"</string> <string name="screen_pinning_description" msgid="8699395373875667743">"Bu işlem, siz sabitlemeyi kaldırana kadar ekranı görünür durumda tutar. Sabitlemeyi kaldırmak için Geri\'ye ve Genel Bakış\'a dokunup basılı tutun."</string> <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Bu işlem, siz sabitlemeyi kaldırana kadar ekranı görünür durumda tutar. Sabitlemeyi kaldırmak için Geri\'ye ve Ana sayfaya dokunup basılı tutun."</string> @@ -602,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"Açık"</string> <string name="switch_bar_off" msgid="5669805115416379556">"Kapalı"</string> <string name="tile_unavailable" msgid="3095879009136616920">"Kullanılamıyor"</string> - <string name="tile_disabled" msgid="373212051546573069">"Devre dışı bırakıldı"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"daha fazla bilgi"</string> <string name="nav_bar" msgid="4642708685386136807">"Gezinme çubuğu"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"Düzen"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Ekstra sol düğme türü"</string> @@ -675,8 +671,10 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Telefon soğurken bazı özellikler sınırlı olarak kullanılabilir.\nDaha fazla bilgi için dokunun"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"Telefonunuz otomatik olarak soğumaya çalışacak. Bu sırada telefonunuzu kullanmaya devam edebilirsiniz ancak uygulamalar daha yavaş çalışabilir.\n\nTelefonunuz soğuduktan sonra normal şekilde çalışacaktır."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Bakımla ilgili adımlara bakın"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Şarj cihazını çıkarın"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"Bu cihaz şarj edilirken bir sorun oluştu. Güç adaptörünün fişini çekin. Kablo sıcak olabileceğinden fişi çekerken dikkatli olun."</string> + <!-- no translation found for high_temp_alarm_title (8654754369605452169) --> + <skip /> + <!-- no translation found for high_temp_alarm_notify_message (3917622943609118956) --> + <skip /> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"Bakımla ilgili adımlara bakın"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Sol kısayol"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"Sağ kısayol"</string> diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml index 6e796b43c900..128098fb4b7e 100644 --- a/packages/SystemUI/res/values-uk/strings.xml +++ b/packages/SystemUI/res/values-uk/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Обличчя не розпізнано. Скористайтеся відбитком пальця."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"Обличчя не розпізнано"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Скористайтеся відбитком"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth під’єднано."</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Відсоток заряду акумулятора невідомий."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Підключено до <xliff:g id="BLUETOOTH">%s</xliff:g>."</string> @@ -423,10 +421,8 @@ <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"Накласти субтитри"</string> <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"увімкнути"</string> <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"вимкнути"</string> - <!-- no translation found for sound_settings (8874581353127418308) --> - <skip /> - <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) --> - <skip /> + <string name="sound_settings" msgid="8874581353127418308">"Звук і вібрація"</string> + <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"Налаштування"</string> <string name="screen_pinning_title" msgid="9058007390337841305">"Додаток закріплено"</string> <string name="screen_pinning_description" msgid="8699395373875667743">"Ви постійно бачитимете екран, доки не відкріпите його. Щоб відкріпити екран, натисніть і втримуйте кнопки \"Назад\" та \"Огляд\"."</string> <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"Ви бачитимете цей екран, доки не відкріпите його. Для цього натисніть і утримуйте кнопки \"Назад\" та \"Головний екран\"."</string> @@ -602,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"Увімкнено"</string> <string name="switch_bar_off" msgid="5669805115416379556">"Вимкнено"</string> <string name="tile_unavailable" msgid="3095879009136616920">"Недоступно"</string> - <string name="tile_disabled" msgid="373212051546573069">"Вимкнено"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"дізнатися більше"</string> <string name="nav_bar" msgid="4642708685386136807">"Панель навігації"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"Макет"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Додатковий тип кнопки ліворуч"</string> @@ -675,8 +671,10 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Під час охолодження деякі функції обмежуються.\nНатисніть, щоб дізнатися більше"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"Ваш телефон охолоджуватиметься автоматично. Ви можете далі користуватися телефоном, але він може працювати повільніше.\n\nКоли телефон охолоне, він працюватиме належним чином."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Переглянути запобіжні заходи"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Відключіть зарядний пристрій"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"Виникла проблема із заряджанням пристрою. Відключіть адаптер живлення, однак будьте обережні, оскільки кабель може бути гарячим."</string> + <!-- no translation found for high_temp_alarm_title (8654754369605452169) --> + <skip /> + <!-- no translation found for high_temp_alarm_notify_message (3917622943609118956) --> + <skip /> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"Переглянути застереження"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Комбінація клавіш ліворуч"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"Комбінація клавіш праворуч"</string> diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml index c722f6938b32..d8007f2cc000 100644 --- a/packages/SystemUI/res/values-ur/strings.xml +++ b/packages/SystemUI/res/values-ur/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"چہرے کی شناخت نہیں ہو سکی۔ اس کے بجائے فنگر پرنٹ استعمال کریں۔"</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"چہرے کی پہچان نہیں ہو سکی"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"اس کے بجائے فنگر پرنٹ استعمال کریں"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"بلوٹوتھ مربوط ہے۔"</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"بیٹری کی فیصد نامعلوم ہے۔"</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g> سے منسلک ہیں۔"</string> @@ -423,10 +421,8 @@ <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"کیپشنز کا اوورلے"</string> <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"فعال کریں"</string> <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"غیر فعال کریں"</string> - <!-- no translation found for sound_settings (8874581353127418308) --> - <skip /> - <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) --> - <skip /> + <string name="sound_settings" msgid="8874581353127418308">"آواز اور وائبریشن"</string> + <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"ترتیبات"</string> <string name="screen_pinning_title" msgid="9058007390337841305">"ایپ کو پن کر دیا گیا ہے"</string> <string name="screen_pinning_description" msgid="8699395373875667743">"اس سے یہ اس وقت تک منظر میں رہتی ہے جب تک آپ اس سے پن ہٹا نہیں دیتے۔ پن ہٹانے کیلئے پیچھے اور مجموعی جائزہ کے بٹنز کو ٹچ کریں اور دبائے رکھیں۔"</string> <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"اس سے یہ اس وقت تک منظر میں رہتی ہے جب تک آپ اس سے پن نہیں ہٹا دیتے۔ پن ہٹانے کیلئے \"پیچھے\" اور \"ہوم\" بٹنز کو ٹچ کریں اور دبائے رکھیں۔"</string> @@ -602,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"آن"</string> <string name="switch_bar_off" msgid="5669805115416379556">"آف"</string> <string name="tile_unavailable" msgid="3095879009136616920">"غیر دستیاب ہے"</string> - <string name="tile_disabled" msgid="373212051546573069">"غیر فعال ہے"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"مزید جانیں"</string> <string name="nav_bar" msgid="4642708685386136807">"نیویگیشن بار"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"لے آؤٹ"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"بائيں جانب کی اضافی بٹن کی قسم"</string> @@ -675,8 +671,10 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"فون کے ٹھنڈے ہو جانے تک کچھ خصوصیات محدود ہیں۔\nمزید معلومات کیلئے تھپتھپائیں"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"آپ کا فون خودکار طور پر ٹھنڈا ہونے کی کوشش کرے گا۔ آپ ابھی بھی اپنا فون استعمال کر سکتے ہیں، مگر ہو سکتا ہے یہ سست چلے۔\n\nایک بار آپ کا فون ٹھنڈا ہوجائے تو یہ معمول کے مطابق چلے گا۔"</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"نگہداشت کے اقدامات ملاحظہ کریں"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"چارجر ان پلگ کریں"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"اس آلہ کو چارج کرنے میں ایک مسئلہ ہے۔ پاور ایڈاپٹر کو ان پلگ کریں اور دھیان دیں کیونکہ تار گرم ہو سکتا ہے۔"</string> + <!-- no translation found for high_temp_alarm_title (8654754369605452169) --> + <skip /> + <!-- no translation found for high_temp_alarm_notify_message (3917622943609118956) --> + <skip /> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"نگہداشت کے اقدامات ملاحظہ کریں"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"بائيں جانب کا شارٹ کٹ"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"دائیں جانب کا شارٹ کٹ"</string> diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml index 19f9a66a55d9..0102c3cbf67c 100644 --- a/packages/SystemUI/res/values-uz/strings.xml +++ b/packages/SystemUI/res/values-uz/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Bu yuz notanish. Barmoq izi orqali urining."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"Yuz aniqlanmadi"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Barmoq izi orqali urining"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth ulandi."</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Batareya quvvati foizi nomaʼlum."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Ulangan: <xliff:g id="BLUETOOTH">%s</xliff:g>."</string> @@ -600,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"Yoniq"</string> <string name="switch_bar_off" msgid="5669805115416379556">"Yoqilmagan"</string> <string name="tile_unavailable" msgid="3095879009136616920">"Mavjud emas"</string> - <string name="tile_disabled" msgid="373212051546573069">"Faolsizlantirilgan"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"batafsil"</string> <string name="nav_bar" msgid="4642708685386136807">"Navigatsiya paneli"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"Tugmalar joylashuvi"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Qo‘shimcha Chapga tugmasi turi"</string> @@ -673,8 +671,8 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Telefon sovib qolganda ayrim funksiyalari ishlamasligi mumkin.\nBatafsil axborot uchun bosing"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"Telefon avtomatik ravishda o‘zini sovitadi. Telefoningizdan foydalanishda davom etishingiz mumkin, lekin u sekinroq ishlashi mumkin.\n\nTelefon sovishi bilan normal holatda ishlashni boshlaydi."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Batafsil axborot"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Quvvatlash moslamasini uzing"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"Bu qurilmani quvvatlashda muammo bor. Quvvat adapteri va kabelni tarmoqdan uzing, ular qizib ketgan boʻlishi mumkin."</string> + <string name="high_temp_alarm_title" msgid="8654754369605452169">"Qurilmani uzing"</string> + <string name="high_temp_alarm_notify_message" msgid="3917622943609118956">"Qurilmangiz quvvatlash porti yaqinida qizib ketmoqda. Agar quvvatlagich yoki USB aksessuarga ulangan boʻlsa, kabel qizib ketmasidan uni darhol uzing."</string> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"Batafsil axborot"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Chapga yorlig‘i"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"O‘ngga yorlig‘i"</string> diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml index 288831e4df42..d6172602c3e2 100644 --- a/packages/SystemUI/res/values-vi/strings.xml +++ b/packages/SystemUI/res/values-vi/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Không thể nhận dạng khuôn mặt. Hãy dùng vân tay."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"Không nhận ra khuôn mặt"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Hãy dùng vân tay"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Đã kết nối bluetooth."</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Tỷ lệ phần trăm pin không xác định."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Đã kết nối với <xliff:g id="BLUETOOTH">%s</xliff:g>."</string> @@ -600,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"Đang bật"</string> <string name="switch_bar_off" msgid="5669805115416379556">"Đang tắt"</string> <string name="tile_unavailable" msgid="3095879009136616920">"Không có sẵn"</string> - <string name="tile_disabled" msgid="373212051546573069">"Đã tắt"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"tìm hiểu thêm"</string> <string name="nav_bar" msgid="4642708685386136807">"Thanh điều hướng"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"Bố cục"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Loại nút bổ sung bên trái"</string> @@ -673,8 +671,10 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Một số tính năng bị hạn chế trong khi điện thoại nguội dần.\nHãy nhấn để biết thêm thông tin"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"Điện thoại của bạn sẽ tự động nguội dần. Bạn vẫn có thể sử dụng điện thoại, nhưng điện thoại có thể chạy chậm hơn. \n\nSau khi đã nguội, điện thoại sẽ chạy bình thường."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Xem các bước chăm sóc"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Rút phích cắm bộ sạc"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"Đã xảy ra sự cố khi sạc thiết bị này. Hãy rút phích cắm bộ chuyển đổi điện và cẩn thận vì dây cáp có thể nóng."</string> + <!-- no translation found for high_temp_alarm_title (8654754369605452169) --> + <skip /> + <!-- no translation found for high_temp_alarm_notify_message (3917622943609118956) --> + <skip /> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"Xem các bước chăm sóc"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Lối tắt bên trái"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"Lối tắt bên phải"</string> diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml index 27fb0bdb6885..5cb91978517c 100644 --- a/packages/SystemUI/res/values-zh-rCN/strings.xml +++ b/packages/SystemUI/res/values-zh-rCN/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"无法识别人脸。请改用指纹。"</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"人脸识别失败"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"改用指纹"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"蓝牙已连接。"</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"电池电量百分比未知。"</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"已连接到<xliff:g id="BLUETOOTH">%s</xliff:g>。"</string> @@ -423,10 +421,8 @@ <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"字幕重叠显示"</string> <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"启用"</string> <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"停用"</string> - <!-- no translation found for sound_settings (8874581353127418308) --> - <skip /> - <!-- no translation found for volume_panel_dialog_settings_button (2513228491513390310) --> - <skip /> + <string name="sound_settings" msgid="8874581353127418308">"提示音和振动"</string> + <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"设置"</string> <string name="screen_pinning_title" msgid="9058007390337841305">"应用已固定"</string> <string name="screen_pinning_description" msgid="8699395373875667743">"这将会固定显示此屏幕,直到您取消固定为止。触摸并按住“返回”和“概览”即可取消固定屏幕。"</string> <string name="screen_pinning_description_recents_invisible" msgid="4564466648700390037">"这将会固定显示此屏幕,直到您取消固定为止。触摸并按住“返回”和“主屏幕”即可取消固定屏幕。"</string> @@ -602,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"开启"</string> <string name="switch_bar_off" msgid="5669805115416379556">"关闭"</string> <string name="tile_unavailable" msgid="3095879009136616920">"不可用"</string> - <string name="tile_disabled" msgid="373212051546573069">"已停用"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"了解详情"</string> <string name="nav_bar" msgid="4642708685386136807">"导航栏"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"布局"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"其他向左按钮类型"</string> @@ -675,8 +671,8 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"手机降温时,部分功能的使用会受限制。\n点按即可了解详情"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"您的手机将自动尝试降温。您依然可以使用您的手机,但是手机运行速度可能会更慢。\n\n手机降温后,就会恢复正常的运行速度。"</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"查看处理步骤"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"拔下充电器"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"为此设备充电时出现问题。这可能是由数据线太热所导致,请拔下电源适配器并采取相应的处理措施。"</string> + <string name="high_temp_alarm_title" msgid="8654754369605452169">"拔出设备"</string> + <string name="high_temp_alarm_notify_message" msgid="3917622943609118956">"设备的充电接口附近在发热。如果该设备已连接到充电器或 USB 配件,请立即拔掉,并注意充电线也可能会发热。"</string> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"查看处理步骤"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"向左快捷方式"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"向右快捷方式"</string> diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml index 241550557d26..37f2bd1e48d7 100644 --- a/packages/SystemUI/res/values-zh-rHK/strings.xml +++ b/packages/SystemUI/res/values-zh-rHK/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"無法辨識面孔,請改用指紋完成驗證。"</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"無法辨識面孔"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"請改用指紋"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"藍牙連線已建立。"</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"電量百分比不明。"</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"已連線至<xliff:g id="BLUETOOTH">%s</xliff:g>。"</string> @@ -423,7 +421,7 @@ <string name="volume_odi_captions_content_description" msgid="4172765742046013630">"字幕重疊"</string> <string name="volume_odi_captions_hint_enable" msgid="2073091194012843195">"啟用"</string> <string name="volume_odi_captions_hint_disable" msgid="2518846326748183407">"停用"</string> - <string name="sound_settings" msgid="8874581353127418308">"音效與震動"</string> + <string name="sound_settings" msgid="8874581353127418308">"音效和震動"</string> <string name="volume_panel_dialog_settings_button" msgid="2513228491513390310">"設定"</string> <string name="screen_pinning_title" msgid="9058007390337841305">"已固定應用程式"</string> <string name="screen_pinning_description" msgid="8699395373875667743">"應用程式將會固定在螢幕上顯示,直至您取消固定為止。按住「返回」和「概覽」按鈕即可取消固定。"</string> @@ -600,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"開啟"</string> <string name="switch_bar_off" msgid="5669805115416379556">"關閉"</string> <string name="tile_unavailable" msgid="3095879009136616920">"無法使用"</string> - <string name="tile_disabled" msgid="373212051546573069">"已停用"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"瞭解詳情"</string> <string name="nav_bar" msgid="4642708685386136807">"導覽列"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"配置"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"其他向左按鈕類型"</string> @@ -673,8 +671,8 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"手機降溫時,部分功能會受限制。\n輕按即可瞭解詳情"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"手機會自動嘗試降溫。您仍可以使用手機,但手機的運作速度可能較慢。\n\n手機降溫後便會恢復正常。"</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"查看保養步驟"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"拔下充電器"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"為此裝置充電時發生問題。請拔除電源適配器並注意安全,因為連接線可能會發熱。"</string> + <string name="high_temp_alarm_title" msgid="8654754369605452169">"拔除裝置"</string> + <string name="high_temp_alarm_notify_message" msgid="3917622943609118956">"裝置的充電埠附近越來越熱。如果裝置已連接充電器或 USB 配件,請立即拔除。此外,電線也可能會變熱,請特別留意。"</string> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"查看保養步驟"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"向左捷徑"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"向右捷徑"</string> diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml index 2b6372a9c857..696b2d389be5 100644 --- a/packages/SystemUI/res/values-zh-rTW/strings.xml +++ b/packages/SystemUI/res/values-zh-rTW/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"無法辨識臉孔,請改用指紋完成驗證。"</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"無法辨識臉孔"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"請改用指紋"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"藍牙連線已建立。"</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"電池電量不明。"</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"已連線至<xliff:g id="BLUETOOTH">%s</xliff:g>。"</string> @@ -600,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"開啟"</string> <string name="switch_bar_off" msgid="5669805115416379556">"關閉"</string> <string name="tile_unavailable" msgid="3095879009136616920">"無法使用"</string> - <string name="tile_disabled" msgid="373212051546573069">"已停用"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"瞭解詳情"</string> <string name="nav_bar" msgid="4642708685386136807">"導覽列"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"配置"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"其他向左按鈕類型"</string> @@ -673,8 +671,8 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"手機降溫時,某些功能會受限。\n輕觸即可瞭解詳情"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"手機會自動嘗試降溫。你仍可繼續使用手機,但是手機的運作速度可能會較慢。\n\n手機降溫完畢後,就會恢復正常的運作速度。"</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"查看處理步驟"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"拔除充電器"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"為這個裝置充電時發生問題。這可能是因為傳輸線過熱所致,請拔除電源變壓器並採取處理措施。"</string> + <string name="high_temp_alarm_title" msgid="8654754369605452169">"拔除裝置"</string> + <string name="high_temp_alarm_notify_message" msgid="3917622943609118956">"裝置的充電埠附近越來越熱。如果裝置已連接充電器或 USB 配件,請立即拔除。此外,電線也可能會變熱,請特別留意。"</string> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"查看處理步驟"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"向左快速鍵"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"向右快速鍵"</string> diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml index 9a4d8491aaad..751a45f04951 100644 --- a/packages/SystemUI/res/values-zu/strings.xml +++ b/packages/SystemUI/res/values-zu/strings.xml @@ -161,10 +161,8 @@ <string name="fingerprint_dialog_use_fingerprint_instead" msgid="6178228876763024452">"Ayibazi ubuso. Sebenzisa izigxivizo zeminwe kunalokho."</string> <!-- no translation found for keyguard_face_failed_use_fp (7140293906176164263) --> <skip /> - <!-- no translation found for keyguard_face_failed (9044619102286917151) --> - <skip /> - <!-- no translation found for keyguard_suggest_fingerprint (8742015961962702960) --> - <skip /> + <string name="keyguard_face_failed" msgid="9044619102286917151">"Ayikwazi ukubona ubuso"</string> + <string name="keyguard_suggest_fingerprint" msgid="8742015961962702960">"Kunalokho sebenzisa isigxivizo somunwe"</string> <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"Bluetooth ixhunyiwe"</string> <string name="accessibility_battery_unknown" msgid="1807789554617976440">"Iphesenti lebhethri alaziwa."</string> <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"Xhuma ku-<xliff:g id="BLUETOOTH">%s</xliff:g>."</string> @@ -600,7 +598,7 @@ <string name="switch_bar_on" msgid="1770868129120096114">"Vuliwe"</string> <string name="switch_bar_off" msgid="5669805115416379556">"Valiwe"</string> <string name="tile_unavailable" msgid="3095879009136616920">"Akutholakali"</string> - <string name="tile_disabled" msgid="373212051546573069">"Kukhutshaziwe"</string> + <string name="accessibility_tile_disabled_by_policy_action_description" msgid="6958422730461646926">"funda kabanzi"</string> <string name="nav_bar" msgid="4642708685386136807">"Ibha yokuzula"</string> <string name="nav_bar_layout" msgid="4716392484772899544">"Isakhiwo"</string> <string name="left_nav_bar_button_type" msgid="2634852842345192790">"Uhlobo lwenkinobho engakwesokunxele engeziwe"</string> @@ -673,8 +671,8 @@ <string name="high_temp_notif_message" msgid="1277346543068257549">"Ezinye izici zikhawulelwe ngenkathi ifoni iphola.\nThepha mayelana nolwazi olwengeziwe"</string> <string name="high_temp_dialog_message" msgid="3793606072661253968">"Ifoni yakho izozama ngokuzenzakalela ukuphola. Ungasasebenzisa ifoni yakho, kodwa ingasebenza ngokungasheshi.\n\nUma ifoni yakho isipholile, izosebenza ngokuvamile."</string> <string name="high_temp_dialog_help_text" msgid="7380171287943345858">"Bona izinyathelo zokunakekelwa"</string> - <string name="high_temp_alarm_title" msgid="2359958549570161495">"Khipha ishaja"</string> - <string name="high_temp_alarm_notify_message" msgid="7186272817783835089">"Kukhona inkinga yokushaja le divayisi. Khipha i-adaptha yamandla, uphinde unakekele njengoba ikhebuli kungenzeka lifudumele."</string> + <string name="high_temp_alarm_title" msgid="8654754369605452169">"Khipha idivayisi yakho"</string> + <string name="high_temp_alarm_notify_message" msgid="3917622943609118956">"Idivayisi yakho iqala ukufudumala eduze kwembobo yokushaja. Uma ixhunywe kushaja noma insiza ye-USB, yikhiphe, futhi uqaphele njengoba ikhebuli ingase ifudumale."</string> <string name="high_temp_alarm_help_care_steps" msgid="5017002218341329566">"Bona izinyathelo zokunakekelwa"</string> <string name="lockscreen_shortcut_left" msgid="1238765178956067599">"Isinqamuleli sangakwesokunxele"</string> <string name="lockscreen_shortcut_right" msgid="4138414674531853719">"Isinqamuleli sangakwesokudla"</string> diff --git a/packages/SystemUI/res/values/bools.xml b/packages/SystemUI/res/values/bools.xml index 499e24e6ecbd..c67ac8d34aa6 100644 --- a/packages/SystemUI/res/values/bools.xml +++ b/packages/SystemUI/res/values/bools.xml @@ -18,4 +18,6 @@ <resources> <!-- Whether to show the user switcher in quick settings when only a single user is present. --> <bool name="qs_show_user_switcher_for_single_user">false</bool> + <!-- Whether to show a custom biometric prompt size--> + <bool name="use_custom_bp_size">false</bool> </resources> diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml index db2ac436229f..75baeeff6025 100644 --- a/packages/SystemUI/res/values/colors.xml +++ b/packages/SystemUI/res/values/colors.xml @@ -182,7 +182,7 @@ <color name="media_dialog_item_main_content">@color/material_dynamic_primary20</color> <color name="media_dialog_item_background">@color/material_dynamic_secondary95</color> <color name="media_dialog_connected_item_background">@color/material_dynamic_primary90</color> - <color name="media_dialog_seekbar_progress">@color/material_dynamic_secondary40</color> + <color name="media_dialog_seekbar_progress">@android:color/system_accent1_200</color> <color name="media_dialog_button_background">@color/material_dynamic_primary40</color> <color name="media_dialog_solid_button_text">@color/material_dynamic_neutral95</color> @@ -241,6 +241,10 @@ <color name="dream_overlay_aqi_very_unhealthy">#AD1457</color> <color name="dream_overlay_aqi_hazardous">#880E4F</color> <color name="dream_overlay_aqi_unknown">#BDC1C6</color> + + <!-- Dream overlay text shadows --> <color name="dream_overlay_clock_key_text_shadow_color">#4D000000</color> <color name="dream_overlay_clock_ambient_text_shadow_color">#4D000000</color> + <color name="dream_overlay_status_bar_key_text_shadow_color">#66000000</color> + <color name="dream_overlay_status_bar_ambient_text_shadow_color">#59000000</color> </resources> diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index ec22c609b0b9..37549c927a90 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -587,9 +587,6 @@ when the double-press power gesture is used. Ignored if empty. --> <string translatable="false" name="config_cameraGesturePackage"></string> - <!-- Determines whether to allow the nav bar handle to be forced to be opaque. --> - <bool name="allow_force_nav_bar_handle_opaque">true</bool> - <!-- Whether a transition of ACTIVITY_TYPE_DREAM to the home app should play a home sound effect --> <bool name="config_playHomeSoundAfterDream">false</bool> @@ -614,11 +611,39 @@ 2 - Override the setting to never bypass keyguard --> <integer name="config_face_unlock_bypass_override">0</integer> + <!-- Messages that should NOT be shown to the user during face authentication on keyguard. + This includes both lockscreen and bouncer. This should be used to hide messages that may be + too chatty or messages that the user can't do much about. Entries are defined in + android.hardware.biometrics.face@1.0 types.hal. + + Although not visibly shown to the user, these acquired messages (sent per face auth frame) + are still counted towards the total frames to determine whether a deferred message + (see config_face_help_msgs_defer_until_timeout) meets the threshold % of frames to show on + face timeout. --> + <integer-array name="config_face_acquire_device_entry_ignorelist" translatable="false" > + </integer-array> + + <!-- Which face help messages to defer until face auth times out. If face auth is cancelled + or ends on another error, then the message is never surfaced. May also never surface + if it doesn't meet a threshold % of authentication frames specified by. + config_face_help_msgs_defer_until_timeout_threshold. --> + <integer-array name="config_face_help_msgs_defer_until_timeout"> + </integer-array> + + <!-- Percentage of face auth frames received required to show a deferred message at + FACE_ERROR_TIMEOUT. See config_face_help_msgs_defer_until_timeout for messages + that are deferred.--> + <item name="config_face_help_msgs_defer_until_timeout_threshold" + translatable="false" format="float" type="dimen"> + .75 + </item> + <!-- Which face help messages to surface when fingerprint is also enrolled. Message ids correspond with the acquired ids in BiometricFaceConstants --> <integer-array name="config_face_help_msgs_when_fingerprint_enrolled"> - <item>25</item> - <item>26</item> + <item>3</item> <!-- TOO_DARK --> + <item>25</item> <!-- DARK_GLASSES --> + <item>26</item> <!-- MOUTH_COVERING_DETECTED --> </integer-array> <!-- Whether the communal service should be enabled --> @@ -629,11 +654,15 @@ <!-- This value is used when calculating whether the device is in ambient light mode. It is light mode when the light sensor sample value exceeds above this value. --> - <integer name="config_ambientLightModeThreshold">10</integer> + <item name="config_ambientLightModeThreshold" translatable="false" format="float" type="dimen"> + 0.8 + </item> <!-- This value is used when calculating whether the device is in ambient dark mode. It is dark mode when the light sensor sample value drops below this value. --> - <integer name="config_ambientDarkModeThreshold">5</integer> + <item name="config_ambientDarkModeThreshold" translatable="false" format="float" type="dimen"> + 0.4 + </item> <!-- This value is used when calculating whether the device is in ambient light mode. Each sample contains light sensor events from this span of time duration. --> diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index 4136b04f7196..eb6c45747924 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -520,7 +520,7 @@ <dimen name="qs_tile_margin_vertical">@dimen/qs_tile_margin_horizontal</dimen> <dimen name="qs_tile_margin_top_bottom">4dp</dimen> <dimen name="qs_brightness_margin_top">8dp</dimen> - <dimen name="qs_brightness_margin_bottom">24dp</dimen> + <dimen name="qs_brightness_margin_bottom">16dp</dimen> <dimen name="qqs_layout_margin_top">16dp</dimen> <dimen name="qqs_layout_padding_bottom">24dp</dimen> @@ -945,6 +945,8 @@ <dimen name="biometric_dialog_medium_to_large_translation_offset">100dp</dimen> <!-- Y translation for credential contents when animating in --> <dimen name="biometric_dialog_credential_translation_offset">60dp</dimen> + <dimen name="biometric_dialog_width">240dp</dimen> + <dimen name="biometric_dialog_height">240dp</dimen> <!-- Starting text size in sp of batteryLevel for wireless charging animation --> <item name="wireless_charging_anim_battery_level_text_size_start" format="float" type="dimen"> @@ -1210,6 +1212,17 @@ fade and expand. --> <dimen name="lockscreen_shade_qs_transition_distance">@dimen/lockscreen_shade_full_transition_distance</dimen> + <!-- Distance delay for the QS transition to start during the lockscreen shade expansion. --> + <dimen name="lockscreen_shade_qs_transition_delay">0dp</dimen> + + <!-- Distance that it takes to complete the QS "squish" transition during the lockscreen shade + expansion. --> + <dimen name="lockscreen_shade_qs_squish_transition_distance">@dimen/lockscreen_shade_qs_transition_distance</dimen> + + <!-- The fraction at which the QS "squish" transition should start during the lockscreen shade + expansion. 0 is fully collapsed, 1 is fully expanded. --> + <item type="dimen" format="float" name="lockscreen_shade_qs_squish_start_fraction">0</item> + <!-- Distance that the full shade transition takes in order for depth of the wallpaper to fully change. --> <dimen name="lockscreen_shade_depth_controller_transition_distance">@dimen/lockscreen_shade_full_transition_distance</dimen> @@ -1451,7 +1464,7 @@ <dimen name="dream_overlay_camera_mic_off_indicator_size">8dp</dimen> <dimen name="dream_overlay_notification_indicator_size">6dp</dimen> <dimen name="dream_overlay_grey_chip_width">56dp</dimen> - <dimen name="dream_overlay_status_bar_extra_margin">16dp</dimen> + <dimen name="dream_overlay_status_bar_extra_margin">8dp</dimen> <!-- Dream overlay complications related dimensions --> <dimen name="dream_overlay_complication_clock_time_text_size">86sp</dimen> @@ -1534,10 +1547,20 @@ <dimen name="broadcast_dialog_btn_text_size">16sp</dimen> <dimen name="broadcast_dialog_btn_minHeight">44dp</dimen> <dimen name="broadcast_dialog_margin">16dp</dimen> + + <!-- Shadow for dream overlay clock complication --> <dimen name="dream_overlay_clock_key_text_shadow_dx">0dp</dimen> <dimen name="dream_overlay_clock_key_text_shadow_dy">0dp</dimen> - <dimen name="dream_overlay_clock_key_text_shadow_radius">5dp</dimen> + <dimen name="dream_overlay_clock_key_text_shadow_radius">3dp</dimen> <dimen name="dream_overlay_clock_ambient_text_shadow_dx">0dp</dimen> <dimen name="dream_overlay_clock_ambient_text_shadow_dy">0dp</dimen> <dimen name="dream_overlay_clock_ambient_text_shadow_radius">1dp</dimen> + + <!-- Shadow for dream overlay status bar complications --> + <dimen name="dream_overlay_status_bar_key_text_shadow_dx">0.5dp</dimen> + <dimen name="dream_overlay_status_bar_key_text_shadow_dy">0.5dp</dimen> + <dimen name="dream_overlay_status_bar_key_text_shadow_radius">1dp</dimen> + <dimen name="dream_overlay_status_bar_ambient_text_shadow_dx">0.5dp</dimen> + <dimen name="dream_overlay_status_bar_ambient_text_shadow_dy">0.5dp</dimen> + <dimen name="dream_overlay_status_bar_ambient_text_shadow_radius">2dp</dimen> </resources> diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml index a36a51878acf..ac3eb7e18539 100644 --- a/packages/SystemUI/res/values/styles.xml +++ b/packages/SystemUI/res/values/styles.xml @@ -573,6 +573,7 @@ </style> <style name="MediaPlayer.ProgressBar" parent="@android:style/Widget.ProgressBar.Horizontal"> + <item name="android:thumb">@drawable/media_seekbar_thumb</item> <item name="android:thumbTint">?android:attr/textColorPrimary</item> <item name="android:progressDrawable">@drawable/media_squiggly_progress</item> <item name="android:progressTint">?android:attr/textColorPrimary</item> diff --git a/packages/SystemUI/screenshot/src/com/android/systemui/testing/screenshot/SystemUIGoldenImagePathManager.kt b/packages/SystemUI/screenshot/src/com/android/systemui/testing/screenshot/SystemUIGoldenImagePathManager.kt index cbab0a75061e..fafc7744f439 100644 --- a/packages/SystemUI/screenshot/src/com/android/systemui/testing/screenshot/SystemUIGoldenImagePathManager.kt +++ b/packages/SystemUI/screenshot/src/com/android/systemui/testing/screenshot/SystemUIGoldenImagePathManager.kt @@ -23,9 +23,11 @@ import platform.test.screenshot.PathConfig /** A [GoldenImagePathManager] that should be used for all SystemUI screenshot tests. */ class SystemUIGoldenImagePathManager( pathConfig: PathConfig, + override val assetsPathRelativeToRepo: String = "tests/screenshot/assets" ) : GoldenImagePathManager( appContext = InstrumentationRegistry.getInstrumentation().context, + assetsPathRelativeToRepo = assetsPathRelativeToRepo, deviceLocalPath = InstrumentationRegistry.getInstrumentation() .targetContext diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/AnimatableClockView.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/AnimatableClockView.kt index b3b75f68e71e..34e2e83d7643 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/AnimatableClockView.kt +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/AnimatableClockView.kt @@ -151,8 +151,6 @@ class AnimatableClockView @JvmOverloads constructor( // relayout if the text didn't actually change. if (!TextUtils.equals(text, formattedText)) { text = formattedText - lastTextUpdate = getTimestamp() - // Because the TextLayout may mutate under the hood as a result of the new text, we // notify the TextAnimator that it may have changed and request a measure/layout. A // crash will occur on the next invocation of setTextStyle if the layout is mutated @@ -161,6 +159,7 @@ class AnimatableClockView @JvmOverloads constructor( textAnimator?.updateLayout(layout) } requestLayout() + lastTextUpdate = getTimestamp() } } diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt b/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt index b5e57667fbb8..19ac2e479bcb 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/clocks/DefaultClockProvider.kt @@ -90,6 +90,9 @@ class DefaultClock( override lateinit var animations: ClockAnimations private set + private var smallRegionDarkness = false + private var largeRegionDarkness = false + init { val parent = FrameLayout(ctx) @@ -148,8 +151,14 @@ class DefaultClock( smallClockIsDark: Boolean, largeClockIsDark: Boolean ) { - updateClockColor(smallClock, smallClockIsDark) - updateClockColor(largeClock, largeClockIsDark) + if (smallRegionDarkness != smallClockIsDark) { + smallRegionDarkness = smallClockIsDark + updateClockColor(smallClock, smallClockIsDark) + } + if (largeRegionDarkness != largeClockIsDark) { + largeRegionDarkness = largeClockIsDark + updateClockColor(largeClock, largeClockIsDark) + } } override fun onLocaleChanged(locale: Locale) { diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl index a030bf629507..e77c65079456 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl @@ -42,13 +42,6 @@ interface ISystemUiProxy { void onOverviewShown(boolean fromHome) = 6; /** - * Control the {@param alpha} of the option nav bar button (back-button in 2 button mode - * and home handle & background in gestural mode). The {@param animate} is currently only - * supported for 2 button mode. - */ - void setNavBarButtonAlpha(float alpha, boolean animate) = 19; - - /** * Proxies motion events from the homescreen UI to the status bar. Only called when * swipe down is detected on WORKSPACE. The sender guarantees the following order of events on * the tracking pointer. diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java index 07733473f298..0b0df833e916 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/model/ThumbnailData.java @@ -17,11 +17,10 @@ package com.android.systemui.shared.recents.model; import static android.app.WindowConfiguration.ROTATION_UNDEFINED; +import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; import static android.content.res.Configuration.ORIENTATION_UNDEFINED; import static android.graphics.Bitmap.Config.ARGB_8888; -import static com.android.systemui.shared.system.WindowManagerWrapper.WINDOWING_MODE_UNDEFINED; - import android.graphics.Bitmap; import android.graphics.Color; import android.graphics.Point; diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityCompat.java deleted file mode 100644 index 0f937bdfe449..000000000000 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityCompat.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2018 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.shared.system; - -import android.app.Activity; -import android.view.View; -import android.view.ViewHierarchyEncoder; - -import java.io.ByteArrayOutputStream; - -public class ActivityCompat { - private final Activity mWrapped; - - public ActivityCompat(Activity activity) { - mWrapped = activity; - } - - /** - * @see Activity#registerRemoteAnimations - */ - public void registerRemoteAnimations(RemoteAnimationDefinitionCompat definition) { - mWrapped.registerRemoteAnimations(definition.getWrapped()); - } - - /** - * @see Activity#unregisterRemoteAnimations - */ - public void unregisterRemoteAnimations() { - mWrapped.unregisterRemoteAnimations(); - } -} diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityOptionsCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityOptionsCompat.java deleted file mode 100644 index be99b270c09a..000000000000 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ActivityOptionsCompat.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2017 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.shared.system; - -import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; - -import android.app.ActivityOptions; -import android.content.Context; -import android.os.Handler; - -/** - * Wrapper around internal ActivityOptions creation. - */ -public abstract class ActivityOptionsCompat { - - /** - * @return ActivityOptions for starting a task in freeform. - */ - public static ActivityOptions makeFreeformOptions() { - final ActivityOptions options = ActivityOptions.makeBasic(); - options.setLaunchWindowingMode(WINDOWING_MODE_FREEFORM); - return options; - } - - public static ActivityOptions makeRemoteAnimation( - RemoteAnimationAdapterCompat remoteAnimationAdapter) { - return ActivityOptions.makeRemoteAnimation(remoteAnimationAdapter.getWrapped(), - remoteAnimationAdapter.getRemoteTransition().getTransition()); - } - - /** - * Constructs an ActivityOptions object that will delegate its transition handling to a - * `remoteTransition`. - */ - public static ActivityOptions makeRemoteTransition(RemoteTransitionCompat remoteTransition) { - return ActivityOptions.makeRemoteTransition(remoteTransition.getTransition()); - } - - /** - * Returns ActivityOptions for overriding task transition animation. - */ - public static ActivityOptions makeCustomAnimation(Context context, int enterResId, - int exitResId, final Runnable callback, final Handler callbackHandler) { - return ActivityOptions.makeCustomTaskAnimation(context, enterResId, exitResId, - callbackHandler, - new ActivityOptions.OnAnimationStartedListener() { - @Override - public void onAnimationStarted(long elapsedRealTime) { - if (callback != null) { - callbackHandler.post(callback); - } - } - }, null /* finishedListener */); - } - - /** - * Sets the flag to freeze the recents task list reordering as a part of launching the activity. - */ - public static ActivityOptions setFreezeRecentTasksList(ActivityOptions opts) { - opts.setFreezeRecentTasksReordering(); - return opts; - } - - /** - * Sets the launch event time from launcher. - */ - public static ActivityOptions setLauncherSourceInfo(ActivityOptions opts, long uptimeMillis) { - opts.setSourceInfo(ActivityOptions.SourceInfo.TYPE_LAUNCHER, uptimeMillis); - return opts; - } -} diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationAdapterCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationAdapterCompat.java index 33e8e3555eba..09cf7c57c08a 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationAdapterCompat.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationAdapterCompat.java @@ -58,7 +58,7 @@ public class RemoteAnimationAdapterCompat { mRemoteTransition = buildRemoteTransition(runner, appThread); } - RemoteAnimationAdapter getWrapped() { + public RemoteAnimationAdapter getWrapped() { return mWrapped; } diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationDefinitionCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationDefinitionCompat.java index 098698aa1c5c..ab55037159ef 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationDefinitionCompat.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationDefinitionCompat.java @@ -34,7 +34,7 @@ public class RemoteAnimationDefinitionCompat { mWrapped.addRemoteAnimation(transition, activityTypeFilter, adapter.getWrapped()); } - RemoteAnimationDefinition getWrapped() { + public RemoteAnimationDefinition getWrapped() { return mWrapped; } } diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ViewTreeObserverWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/ViewTreeObserverWrapper.java deleted file mode 100644 index cfb23f9e4f9c..000000000000 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ViewTreeObserverWrapper.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (C) 2020 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.shared.system; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.graphics.Rect; -import android.graphics.Region; -import android.view.ViewTreeObserver; -import android.view.ViewTreeObserver.OnComputeInternalInsetsListener; - -import java.util.HashMap; - -public class ViewTreeObserverWrapper { - - private static final HashMap<OnComputeInsetsListener, ViewTreeObserver> - sListenerObserverMap = new HashMap<>(); - private static final HashMap<OnComputeInsetsListener, OnComputeInternalInsetsListener> - sListenerInternalListenerMap = new HashMap<>(); - - /** - * Register a callback to be invoked when the invoked when it is time to compute the window's - * insets. - * - * @param observer The observer to be added - * @param listener The callback to add - * @throws IllegalStateException If {@link ViewTreeObserver#isAlive()} returns false - */ - public static void addOnComputeInsetsListener( - @NonNull ViewTreeObserver observer, @NonNull OnComputeInsetsListener listener) { - final OnComputeInternalInsetsListener internalListener = internalInOutInfo -> { - final InsetsInfo inOutInfo = new InsetsInfo(); - inOutInfo.contentInsets.set(internalInOutInfo.contentInsets); - inOutInfo.visibleInsets.set(internalInOutInfo.visibleInsets); - inOutInfo.touchableRegion.set(internalInOutInfo.touchableRegion); - listener.onComputeInsets(inOutInfo); - internalInOutInfo.contentInsets.set(inOutInfo.contentInsets); - internalInOutInfo.visibleInsets.set(inOutInfo.visibleInsets); - internalInOutInfo.touchableRegion.set(inOutInfo.touchableRegion); - internalInOutInfo.setTouchableInsets(inOutInfo.mTouchableInsets); - }; - sListenerObserverMap.put(listener, observer); - sListenerInternalListenerMap.put(listener, internalListener); - observer.addOnComputeInternalInsetsListener(internalListener); - } - - /** - * Remove a previously installed insets computation callback. - * - * @param victim The callback to remove - * @throws IllegalStateException If {@link ViewTreeObserver#isAlive()} returns false - * @see #addOnComputeInsetsListener(ViewTreeObserver, OnComputeInsetsListener) - */ - public static void removeOnComputeInsetsListener(@NonNull OnComputeInsetsListener victim) { - final ViewTreeObserver observer = sListenerObserverMap.get(victim); - final OnComputeInternalInsetsListener listener = sListenerInternalListenerMap.get(victim); - if (observer != null && listener != null) { - observer.removeOnComputeInternalInsetsListener(listener); - } - sListenerObserverMap.remove(victim); - sListenerInternalListenerMap.remove(victim); - } - - /** - * Interface definition for a callback to be invoked when layout has - * completed and the client can compute its interior insets. - */ - public interface OnComputeInsetsListener { - /** - * Callback method to be invoked when layout has completed and the - * client can compute its interior insets. - * - * @param inoutInfo Should be filled in by the implementation with - * the information about the insets of the window. This is called - * with whatever values the previous OnComputeInsetsListener - * returned, if there are multiple such listeners in the window. - */ - void onComputeInsets(InsetsInfo inoutInfo); - } - - /** - * Parameters used with OnComputeInsetsListener. - */ - public final static class InsetsInfo { - - /** - * Offsets from the frame of the window at which the content of - * windows behind it should be placed. - */ - public final Rect contentInsets = new Rect(); - - /** - * Offsets from the frame of the window at which windows behind it - * are visible. - */ - public final Rect visibleInsets = new Rect(); - - /** - * Touchable region defined relative to the origin of the frame of the window. - * Only used when {@link #setTouchableInsets(int)} is called with - * the option {@link #TOUCHABLE_INSETS_REGION}. - */ - public final Region touchableRegion = new Region(); - - /** - * Option for {@link #setTouchableInsets(int)}: the entire window frame - * can be touched. - */ - public static final int TOUCHABLE_INSETS_FRAME = - ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME; - - /** - * Option for {@link #setTouchableInsets(int)}: the area inside of - * the content insets can be touched. - */ - public static final int TOUCHABLE_INSETS_CONTENT = - ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT; - - /** - * Option for {@link #setTouchableInsets(int)}: the area inside of - * the visible insets can be touched. - */ - public static final int TOUCHABLE_INSETS_VISIBLE = - ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_VISIBLE; - - /** - * Option for {@link #setTouchableInsets(int)}: the area inside of - * the provided touchable region in {@link #touchableRegion} can be touched. - */ - public static final int TOUCHABLE_INSETS_REGION = - ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION; - - /** - * Set which parts of the window can be touched: either - * {@link #TOUCHABLE_INSETS_FRAME}, {@link #TOUCHABLE_INSETS_CONTENT}, - * {@link #TOUCHABLE_INSETS_VISIBLE}, or {@link #TOUCHABLE_INSETS_REGION}. - */ - public void setTouchableInsets(int val) { - mTouchableInsets = val; - } - - int mTouchableInsets; - - @Override - public int hashCode() { - int result = contentInsets.hashCode(); - result = 31 * result + visibleInsets.hashCode(); - result = 31 * result + touchableRegion.hashCode(); - result = 31 * result + mTouchableInsets; - return result; - } - - @Override - public boolean equals(@Nullable Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - final InsetsInfo other = (InsetsInfo) o; - return mTouchableInsets == other.mTouchableInsets && - contentInsets.equals(other.contentInsets) && - visibleInsets.equals(other.visibleInsets) && - touchableRegion.equals(other.touchableRegion); - } - } -} diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java deleted file mode 100644 index 5577513f4c3c..000000000000 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/WindowManagerWrapper.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (C) 2017 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.shared.system; - -import static android.view.Display.DEFAULT_DISPLAY; -import static android.view.WindowManagerPolicyConstants.NAV_BAR_BOTTOM; -import static android.view.WindowManagerPolicyConstants.NAV_BAR_INVALID; -import static android.view.WindowManagerPolicyConstants.NAV_BAR_LEFT; -import static android.view.WindowManagerPolicyConstants.NAV_BAR_RIGHT; - -import android.app.WindowConfiguration; -import android.graphics.Rect; -import android.os.Handler; -import android.os.RemoteException; -import android.util.Log; -import android.view.InsetsController; -import android.view.InsetsFrameProvider; -import android.view.InsetsState; -import android.view.SurfaceControl; -import android.view.WindowManager; -import android.view.WindowManagerGlobal; -import android.view.animation.Interpolator; - -import com.android.systemui.shared.recents.view.AppTransitionAnimationSpecsFuture; -import com.android.systemui.shared.recents.view.RecentsTransition; - -public class WindowManagerWrapper { - - private static final String TAG = "WindowManagerWrapper"; - - public static final int TRANSIT_UNSET = WindowManager.TRANSIT_OLD_UNSET; - public static final int TRANSIT_NONE = WindowManager.TRANSIT_OLD_NONE; - public static final int TRANSIT_ACTIVITY_OPEN = WindowManager.TRANSIT_OLD_ACTIVITY_OPEN; - public static final int TRANSIT_ACTIVITY_CLOSE = WindowManager.TRANSIT_OLD_ACTIVITY_CLOSE; - public static final int TRANSIT_TASK_OPEN = WindowManager.TRANSIT_OLD_TASK_OPEN; - public static final int TRANSIT_TASK_CLOSE = WindowManager.TRANSIT_OLD_TASK_CLOSE; - public static final int TRANSIT_TASK_TO_FRONT = WindowManager.TRANSIT_OLD_TASK_TO_FRONT; - public static final int TRANSIT_TASK_TO_BACK = WindowManager.TRANSIT_OLD_TASK_TO_BACK; - public static final int TRANSIT_WALLPAPER_CLOSE = WindowManager.TRANSIT_OLD_WALLPAPER_CLOSE; - public static final int TRANSIT_WALLPAPER_OPEN = WindowManager.TRANSIT_OLD_WALLPAPER_OPEN; - public static final int TRANSIT_WALLPAPER_INTRA_OPEN = - WindowManager.TRANSIT_OLD_WALLPAPER_INTRA_OPEN; - public static final int TRANSIT_WALLPAPER_INTRA_CLOSE = - WindowManager.TRANSIT_OLD_WALLPAPER_INTRA_CLOSE; - public static final int TRANSIT_TASK_OPEN_BEHIND = WindowManager.TRANSIT_OLD_TASK_OPEN_BEHIND; - public static final int TRANSIT_ACTIVITY_RELAUNCH = WindowManager.TRANSIT_OLD_ACTIVITY_RELAUNCH; - public static final int TRANSIT_KEYGUARD_GOING_AWAY = - WindowManager.TRANSIT_OLD_KEYGUARD_GOING_AWAY; - public static final int TRANSIT_KEYGUARD_GOING_AWAY_ON_WALLPAPER = - WindowManager.TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER; - public static final int TRANSIT_KEYGUARD_OCCLUDE = WindowManager.TRANSIT_OLD_KEYGUARD_OCCLUDE; - public static final int TRANSIT_KEYGUARD_UNOCCLUDE = - WindowManager.TRANSIT_OLD_KEYGUARD_UNOCCLUDE; - - public static final int NAV_BAR_POS_INVALID = NAV_BAR_INVALID; - public static final int NAV_BAR_POS_LEFT = NAV_BAR_LEFT; - public static final int NAV_BAR_POS_RIGHT = NAV_BAR_RIGHT; - public static final int NAV_BAR_POS_BOTTOM = NAV_BAR_BOTTOM; - - public static final int ACTIVITY_TYPE_STANDARD = WindowConfiguration.ACTIVITY_TYPE_STANDARD; - - public static final int WINDOWING_MODE_UNDEFINED = WindowConfiguration.WINDOWING_MODE_UNDEFINED; - public static final int WINDOWING_MODE_FULLSCREEN = - WindowConfiguration.WINDOWING_MODE_FULLSCREEN; - public static final int WINDOWING_MODE_MULTI_WINDOW = - WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; - - public static final int WINDOWING_MODE_FREEFORM = WindowConfiguration.WINDOWING_MODE_FREEFORM; - - public static final int ITYPE_EXTRA_NAVIGATION_BAR = InsetsState.ITYPE_EXTRA_NAVIGATION_BAR; - public static final int ITYPE_LEFT_TAPPABLE_ELEMENT = InsetsState.ITYPE_LEFT_TAPPABLE_ELEMENT; - public static final int ITYPE_TOP_TAPPABLE_ELEMENT = InsetsState.ITYPE_TOP_TAPPABLE_ELEMENT; - public static final int ITYPE_RIGHT_TAPPABLE_ELEMENT = InsetsState.ITYPE_RIGHT_TAPPABLE_ELEMENT; - public static final int ITYPE_BOTTOM_TAPPABLE_ELEMENT = - InsetsState.ITYPE_BOTTOM_TAPPABLE_ELEMENT; - public static final int ITYPE_SIZE = InsetsState.SIZE; - - public static final int ANIMATION_DURATION_RESIZE = InsetsController.ANIMATION_DURATION_RESIZE; - public static final Interpolator RESIZE_INTERPOLATOR = InsetsController.RESIZE_INTERPOLATOR; - - private static final WindowManagerWrapper sInstance = new WindowManagerWrapper(); - - public static WindowManagerWrapper getInstance() { - return sInstance; - } - - - /** - * Sets {@param providesInsetsTypes} as the inset types provided by {@param params}. - * @param params The window layout params. - * @param providesInsetsTypes The inset types we would like this layout params to provide. - */ - public void setProvidesInsetsTypes(WindowManager.LayoutParams params, - int[] providesInsetsTypes) { - final int length = providesInsetsTypes.length; - params.providedInsets = new InsetsFrameProvider[length]; - for (int i = 0; i < length; i++) { - params.providedInsets[i] = new InsetsFrameProvider(providesInsetsTypes[i]); - } - } - - /** - * Overrides a pending app transition. - */ - public void overridePendingAppTransitionMultiThumbFuture( - AppTransitionAnimationSpecsFuture animationSpecFuture, Runnable animStartedCallback, - Handler animStartedCallbackHandler, boolean scaleUp, int displayId) { - try { - WindowManagerGlobal.getWindowManagerService() - .overridePendingAppTransitionMultiThumbFuture(animationSpecFuture.getFuture(), - RecentsTransition.wrapStartedListener(animStartedCallbackHandler, - animStartedCallback), scaleUp, displayId); - } catch (RemoteException e) { - Log.w(TAG, "Failed to override pending app transition (multi-thumbnail future): ", e); - } - } - - /** - * Enable or disable haptic feedback on the navigation bar buttons. - */ - public void setNavBarVirtualKeyHapticFeedbackEnabled(boolean enabled) { - try { - WindowManagerGlobal.getWindowManagerService() - .setNavBarVirtualKeyHapticFeedbackEnabled(enabled); - } catch (RemoteException e) { - Log.w(TAG, "Failed to enable or disable navigation bar button haptics: ", e); - } - } - - /** - * @param displayId the id of display to check if there is a software navigation bar. - * - * @return whether there is a soft nav bar on specific display. - */ - public boolean hasSoftNavigationBar(int displayId) { - try { - return WindowManagerGlobal.getWindowManagerService().hasNavigationBar(displayId); - } catch (RemoteException e) { - return false; - } - } - - /** - * Mirrors a specified display. The SurfaceControl returned is the root of the mirrored - * hierarchy. - * - * @param displayId The id of the display to mirror - * @return The SurfaceControl for the root of the mirrored hierarchy. - */ - public SurfaceControl mirrorDisplay(final int displayId) { - try { - SurfaceControl outSurfaceControl = new SurfaceControl(); - WindowManagerGlobal.getWindowManagerService().mirrorDisplay(displayId, - outSurfaceControl); - return outSurfaceControl; - } catch (RemoteException e) { - Log.e(TAG, "Unable to reach window manager", e); - } - return null; - } -} diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/KeyguardManagerCompat.java b/packages/SystemUI/src/com/android/keyguard/AuthKeyguardMessageArea.kt index c42e7e3fd216..82ce1ca3bbb4 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/KeyguardManagerCompat.java +++ b/packages/SystemUI/src/com/android/keyguard/AuthKeyguardMessageArea.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 The Android Open Source Project + * 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. @@ -14,19 +14,20 @@ * limitations under the License */ -package com.android.systemui.shared.system; +package com.android.keyguard -import android.app.KeyguardManager; -import android.content.Context; +import android.content.Context +import android.content.res.ColorStateList +import android.graphics.Color +import android.util.AttributeSet -public class KeyguardManagerCompat { - private final KeyguardManager mKeyguardManager; - - public KeyguardManagerCompat(Context context) { - mKeyguardManager = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE); - } - - public boolean isDeviceLocked(int userId) { - return mKeyguardManager.isDeviceLocked(userId); +/** + * Displays security messages for auth outside of the security method (pin, password, pattern), like + * biometric auth. + */ +class AuthKeyguardMessageArea(context: Context?, attrs: AttributeSet?) : + KeyguardMessageArea(context, attrs) { + override fun updateTextColor() { + setTextColor(ColorStateList.valueOf(Color.WHITE)) } } diff --git a/packages/SystemUI/src/com/android/keyguard/BouncerKeyguardMessageArea.kt b/packages/SystemUI/src/com/android/keyguard/BouncerKeyguardMessageArea.kt new file mode 100644 index 000000000000..0075ddd73cd3 --- /dev/null +++ b/packages/SystemUI/src/com/android/keyguard/BouncerKeyguardMessageArea.kt @@ -0,0 +1,61 @@ +/* + * 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.keyguard + +import android.content.Context +import android.content.res.ColorStateList +import android.content.res.TypedArray +import android.graphics.Color +import android.util.AttributeSet +import com.android.settingslib.Utils + +/** Displays security messages for the keyguard bouncer. */ +class BouncerKeyguardMessageArea(context: Context?, attrs: AttributeSet?) : + KeyguardMessageArea(context, attrs) { + private val DEFAULT_COLOR = -1 + private var mDefaultColorState: ColorStateList? = null + private var mNextMessageColorState: ColorStateList? = ColorStateList.valueOf(DEFAULT_COLOR) + + override fun updateTextColor() { + var colorState = mDefaultColorState + mNextMessageColorState?.defaultColor?.let { color -> + if (color != DEFAULT_COLOR) { + colorState = mNextMessageColorState + mNextMessageColorState = ColorStateList.valueOf(DEFAULT_COLOR) + } + } + setTextColor(colorState) + } + + override fun setNextMessageColor(colorState: ColorStateList?) { + mNextMessageColorState = colorState + } + + override fun onThemeChanged() { + val array: TypedArray = + mContext.obtainStyledAttributes(intArrayOf(android.R.attr.textColorPrimary)) + val newTextColors: ColorStateList = ColorStateList.valueOf(array.getColor(0, Color.RED)) + array.recycle() + mDefaultColorState = newTextColors + super.onThemeChanged() + } + + override fun reloadColor() { + mDefaultColorState = Utils.getColorAttr(context, android.R.attr.textColorPrimary) + super.reloadColor() + } +} diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java index b8fcb103402d..92ba619e7eb9 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardAbsKeyInputViewController.java @@ -50,7 +50,6 @@ public abstract class KeyguardAbsKeyInputViewController<T extends KeyguardAbsKey private final FalsingCollector mFalsingCollector; private final EmergencyButtonController mEmergencyButtonController; private CountDownTimer mCountdownTimer; - protected KeyguardMessageAreaController mMessageAreaController; private boolean mDismissing; protected AsyncTask<?, ?, ?> mPendingLockCheck; protected boolean mResumed; @@ -80,14 +79,13 @@ public abstract class KeyguardAbsKeyInputViewController<T extends KeyguardAbsKey KeyguardMessageAreaController.Factory messageAreaControllerFactory, LatencyTracker latencyTracker, FalsingCollector falsingCollector, EmergencyButtonController emergencyButtonController) { - super(view, securityMode, keyguardSecurityCallback, emergencyButtonController); + super(view, securityMode, keyguardSecurityCallback, emergencyButtonController, + messageAreaControllerFactory); mKeyguardUpdateMonitor = keyguardUpdateMonitor; mLockPatternUtils = lockPatternUtils; mLatencyTracker = latencyTracker; mFalsingCollector = falsingCollector; mEmergencyButtonController = emergencyButtonController; - KeyguardMessageArea kma = KeyguardMessageArea.findSecurityMessageDisplay(mView); - mMessageAreaController = messageAreaControllerFactory.create(kma); } abstract void resetState(); @@ -95,7 +93,6 @@ public abstract class KeyguardAbsKeyInputViewController<T extends KeyguardAbsKey @Override public void onInit() { super.onInit(); - mMessageAreaController.init(); } @Override @@ -134,6 +131,10 @@ public abstract class KeyguardAbsKeyInputViewController<T extends KeyguardAbsKey @Override public void showMessage(CharSequence message, ColorStateList colorState) { + if (mMessageAreaController == null) { + return; + } + if (colorState != null) { mMessageAreaController.setNextMessageColor(colorState); } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java index 87300c3f0504..f26b9057dc7c 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardInputViewController.java @@ -17,9 +17,11 @@ package com.android.keyguard; import android.annotation.CallSuper; +import android.annotation.Nullable; import android.content.res.ColorStateList; import android.content.res.Resources; import android.telephony.TelephonyManager; +import android.util.Log; import android.view.inputmethod.InputMethodManager; import com.android.internal.util.LatencyTracker; @@ -44,7 +46,7 @@ public abstract class KeyguardInputViewController<T extends KeyguardInputView> private final EmergencyButton mEmergencyButton; private final EmergencyButtonController mEmergencyButtonController; private boolean mPaused; - + protected KeyguardMessageAreaController<BouncerKeyguardMessageArea> mMessageAreaController; // The following is used to ignore callbacks from SecurityViews that are no longer current // (e.g. face unlock). This avoids unwanted asynchronous events from messing with the @@ -72,12 +74,24 @@ public abstract class KeyguardInputViewController<T extends KeyguardInputView> protected KeyguardInputViewController(T view, SecurityMode securityMode, KeyguardSecurityCallback keyguardSecurityCallback, - EmergencyButtonController emergencyButtonController) { + EmergencyButtonController emergencyButtonController, + @Nullable KeyguardMessageAreaController.Factory messageAreaControllerFactory) { super(view); mSecurityMode = securityMode; mKeyguardSecurityCallback = keyguardSecurityCallback; mEmergencyButton = view == null ? null : view.findViewById(R.id.emergency_call_button); mEmergencyButtonController = emergencyButtonController; + if (messageAreaControllerFactory != null) { + try { + BouncerKeyguardMessageArea kma = view.requireViewById(R.id.bouncer_message_area); + mMessageAreaController = messageAreaControllerFactory.create(kma); + mMessageAreaController.init(); + mMessageAreaController.setIsVisible(true); + } catch (IllegalArgumentException exception) { + Log.e("KeyguardInputViewController", + "Ensure that a BouncerKeyguardMessageArea is included in the layout"); + } + } } @Override diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt b/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt index 919b71bbf879..f82e7dbd5d12 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt @@ -55,6 +55,8 @@ data class KeyguardFaceListenModel( val bouncerIsOrWillShow: Boolean, val faceAuthenticated: Boolean, val faceDisabled: Boolean, + val faceLockedOut: Boolean, + val fpLockedOut: Boolean, val goingToSleep: Boolean, val keyguardAwakeExcludingBouncerShowing: Boolean, val keyguardGoingAway: Boolean, @@ -65,7 +67,7 @@ data class KeyguardFaceListenModel( val scanningAllowedByStrongAuth: Boolean, val secureCameraLaunched: Boolean, val switchingUser: Boolean, - val udfpsBouncerShowing: Boolean + val udfpsBouncerShowing: Boolean, ) : KeyguardListenModel() /** * Verbose debug information associated with [KeyguardUpdateMonitor.shouldTriggerActiveUnlock]. diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardMessageArea.java b/packages/SystemUI/src/com/android/keyguard/KeyguardMessageArea.java index 5ab2fd0aff09..c79fc2c27f0e 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardMessageArea.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardMessageArea.java @@ -17,9 +17,7 @@ package com.android.keyguard; import android.content.Context; -import android.content.res.ColorStateList; import android.content.res.TypedArray; -import android.graphics.Color; import android.os.Handler; import android.os.Looper; import android.os.SystemClock; @@ -33,7 +31,6 @@ import android.widget.TextView; import androidx.annotation.Nullable; import com.android.internal.policy.SystemBarUtils; -import com.android.settingslib.Utils; import com.android.systemui.R; import java.lang.ref.WeakReference; @@ -41,7 +38,7 @@ import java.lang.ref.WeakReference; /*** * Manages a number of views inside of the given layout. See below for a list of widgets. */ -public class KeyguardMessageArea extends TextView implements SecurityMessageDisplay { +public abstract class KeyguardMessageArea extends TextView implements SecurityMessageDisplay { /** Handler token posted with accessibility announcement runnables. */ private static final Object ANNOUNCE_TOKEN = new Object(); @@ -50,15 +47,11 @@ public class KeyguardMessageArea extends TextView implements SecurityMessageDisp * lift-to-type from interrupting itself. */ private static final long ANNOUNCEMENT_DELAY = 250; - private static final int DEFAULT_COLOR = -1; private final Handler mHandler; - private ColorStateList mDefaultColorState; private CharSequence mMessage; - private ColorStateList mNextMessageColorState = ColorStateList.valueOf(DEFAULT_COLOR); - private boolean mBouncerShowing; - private boolean mAltBouncerShowing; + private boolean mIsVisible; /** * Container that wraps the KeyguardMessageArea - may be null if current view hierarchy doesn't * contain {@link R.id.keyguard_message_area_container}. @@ -96,23 +89,11 @@ public class KeyguardMessageArea extends TextView implements SecurityMessageDisp mContainer.setLayoutParams(lp); } - @Override - public void setNextMessageColor(ColorStateList colorState) { - mNextMessageColorState = colorState; - } - - void onThemeChanged() { - TypedArray array = mContext.obtainStyledAttributes(new int[] { - android.R.attr.textColorPrimary - }); - ColorStateList newTextColors = ColorStateList.valueOf(array.getColor(0, Color.RED)); - array.recycle(); - mDefaultColorState = newTextColors; + protected void onThemeChanged() { update(); } - void reloadColor() { - mDefaultColorState = Utils.getColorAttr(getContext(), android.R.attr.textColorPrimary); + protected void reloadColor() { update(); } @@ -151,17 +132,6 @@ public class KeyguardMessageArea extends TextView implements SecurityMessageDisp setMessage(message); } - public static KeyguardMessageArea findSecurityMessageDisplay(View v) { - KeyguardMessageArea messageArea = v.findViewById(R.id.keyguard_message_area); - if (messageArea == null) { - messageArea = v.getRootView().findViewById(R.id.keyguard_message_area); - } - if (messageArea == null) { - throw new RuntimeException("Can't find keyguard_message_area in " + v.getClass()); - } - return messageArea; - } - private void securityMessageChanged(CharSequence message) { mMessage = message; update(); @@ -177,40 +147,23 @@ public class KeyguardMessageArea extends TextView implements SecurityMessageDisp void update() { CharSequence status = mMessage; - setVisibility(TextUtils.isEmpty(status) || (!mBouncerShowing && !mAltBouncerShowing) - ? INVISIBLE : VISIBLE); + setVisibility(TextUtils.isEmpty(status) || (!mIsVisible) ? INVISIBLE : VISIBLE); setText(status); - ColorStateList colorState = mDefaultColorState; - if (mNextMessageColorState.getDefaultColor() != DEFAULT_COLOR) { - colorState = mNextMessageColorState; - mNextMessageColorState = ColorStateList.valueOf(DEFAULT_COLOR); - } - if (mAltBouncerShowing) { - // alt bouncer has a black scrim, so always show the text in white - colorState = ColorStateList.valueOf(Color.WHITE); - } - setTextColor(colorState); + updateTextColor(); } /** * Set whether the bouncer is fully showing */ - public void setBouncerShowing(boolean bouncerShowing) { - if (mBouncerShowing != bouncerShowing) { - mBouncerShowing = bouncerShowing; + public void setIsVisible(boolean isVisible) { + if (mIsVisible != isVisible) { + mIsVisible = isVisible; update(); } } - /** - * Set whether the alt bouncer is showing - */ - void setAltBouncerShowing(boolean showing) { - if (mAltBouncerShowing != showing) { - mAltBouncerShowing = showing; - update(); - } - } + /** Set the text color */ + protected abstract void updateTextColor(); /** * Runnable used to delay accessibility announcements. diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardMessageAreaController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardMessageAreaController.java index 3ec8ce918a4d..c2802f7b6843 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardMessageAreaController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardMessageAreaController.java @@ -26,11 +26,14 @@ import com.android.systemui.util.ViewController; import javax.inject.Inject; -/** Controller for a {@link KeyguardMessageAreaController}. */ -public class KeyguardMessageAreaController extends ViewController<KeyguardMessageArea> { +/** + * Controller for a {@link KeyguardMessageAreaController}. + * @param <T> A subclass of KeyguardMessageArea. + */ +public class KeyguardMessageAreaController<T extends KeyguardMessageArea> + extends ViewController<T> { private final KeyguardUpdateMonitor mKeyguardUpdateMonitor; private final ConfigurationController mConfigurationController; - private boolean mAltBouncerShowing; private KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() { public void onFinishedGoingToSleep(int why) { @@ -59,7 +62,7 @@ public class KeyguardMessageAreaController extends ViewController<KeyguardMessag } }; - private KeyguardMessageAreaController(KeyguardMessageArea view, + protected KeyguardMessageAreaController(T view, KeyguardUpdateMonitor keyguardUpdateMonitor, ConfigurationController configurationController) { super(view); @@ -83,17 +86,10 @@ public class KeyguardMessageAreaController extends ViewController<KeyguardMessag } /** - * Set whether alt bouncer is showing - */ - public void setAltBouncerShowing(boolean showing) { - mView.setAltBouncerShowing(showing); - } - - /** - * Set bouncer is fully showing + * Indicate that view is visible and can display messages. */ - public void setBouncerShowing(boolean showing) { - mView.setBouncerShowing(showing); + public void setIsVisible(boolean isVisible) { + mView.setIsVisible(isVisible); } public void setMessage(CharSequence s) { diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java index 6844b655629a..453072bc42da 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPINView.java @@ -16,23 +16,25 @@ package com.android.keyguard; -import static com.android.internal.jank.InteractionJankMonitor.CUJ_LOCKSCREEN_PIN_APPEAR; import static com.android.internal.jank.InteractionJankMonitor.CUJ_LOCKSCREEN_PIN_DISAPPEAR; import static com.android.systemui.statusbar.policy.DevicePostureController.DEVICE_POSTURE_HALF_OPENED; import static com.android.systemui.statusbar.policy.DevicePostureController.DEVICE_POSTURE_UNKNOWN; +import android.animation.ValueAnimator; import android.content.Context; import android.content.res.Configuration; import android.util.AttributeSet; +import android.util.MathUtils; import android.view.View; import android.view.animation.AnimationUtils; +import android.view.animation.Interpolator; import androidx.constraintlayout.widget.ConstraintLayout; import androidx.constraintlayout.widget.ConstraintSet; -import com.android.settingslib.animation.AppearAnimationUtils; import com.android.settingslib.animation.DisappearAnimationUtils; import com.android.systemui.R; +import com.android.systemui.animation.Interpolators; import com.android.systemui.statusbar.policy.DevicePostureController.DevicePostureInt; /** @@ -40,12 +42,15 @@ import com.android.systemui.statusbar.policy.DevicePostureController.DevicePostu */ public class KeyguardPINView extends KeyguardPinBasedInputView { - private final AppearAnimationUtils mAppearAnimationUtils; + ValueAnimator mAppearAnimator = ValueAnimator.ofFloat(0f, 1f); private final DisappearAnimationUtils mDisappearAnimationUtils; private final DisappearAnimationUtils mDisappearAnimationUtilsLocked; private ConstraintLayout mContainer; private int mDisappearYTranslation; private View[][] mViews; + private int mYTrans; + private int mYTransOffset; + private View mBouncerMessageView; @DevicePostureInt private int mLastDevicePosture = DEVICE_POSTURE_UNKNOWN; public KeyguardPINView(Context context) { @@ -54,7 +59,6 @@ public class KeyguardPINView extends KeyguardPinBasedInputView { public KeyguardPINView(Context context, AttributeSet attrs) { super(context, attrs); - mAppearAnimationUtils = new AppearAnimationUtils(context); mDisappearAnimationUtils = new DisappearAnimationUtils(context, 125, 0.6f /* translationScale */, 0.45f /* delayScale */, AnimationUtils.loadInterpolator( @@ -66,6 +70,8 @@ public class KeyguardPINView extends KeyguardPinBasedInputView { mContext, android.R.interpolator.fast_out_linear_in)); mDisappearYTranslation = getResources().getDimensionPixelSize( R.dimen.disappear_y_translation); + mYTrans = getResources().getDimensionPixelSize(R.dimen.pin_view_trans_y_entry); + mYTransOffset = getResources().getDimensionPixelSize(R.dimen.pin_view_trans_y_entry_offset); } @Override @@ -137,6 +143,7 @@ public class KeyguardPINView extends KeyguardPinBasedInputView { super.onFinishInflate(); mContainer = findViewById(R.id.pin_container); + mBouncerMessageView = findViewById(R.id.bouncer_message_area); mViews = new View[][]{ new View[]{ findViewById(R.id.row0), null, null @@ -169,25 +176,20 @@ public class KeyguardPINView extends KeyguardPinBasedInputView { @Override public void startAppearAnimation() { - enableClipping(false); - setAlpha(1f); - setTranslationY(mAppearAnimationUtils.getStartTranslation()); - AppearAnimationUtils.startTranslationYAnimation(this, 0 /* delay */, 500 /* duration */, - 0, mAppearAnimationUtils.getInterpolator(), - getAnimationListener(CUJ_LOCKSCREEN_PIN_APPEAR)); - mAppearAnimationUtils.startAnimation2d(mViews, - new Runnable() { - @Override - public void run() { - enableClipping(true); - } - }); + if (mAppearAnimator.isRunning()) { + mAppearAnimator.cancel(); + } + mAppearAnimator.setDuration(650); + mAppearAnimator.addUpdateListener(animation -> animate(animation.getAnimatedFraction())); + mAppearAnimator.start(); } public boolean startDisappearAnimation(boolean needsSlowUnlockTransition, final Runnable finishRunnable) { + if (mAppearAnimator.isRunning()) { + mAppearAnimator.cancel(); + } - enableClipping(false); setTranslationY(0); DisappearAnimationUtils disappearAnimationUtils = needsSlowUnlockTransition ? mDisappearAnimationUtilsLocked @@ -195,7 +197,6 @@ public class KeyguardPINView extends KeyguardPinBasedInputView { disappearAnimationUtils.createAnimation( this, 0, 200, mDisappearYTranslation, false, mDisappearAnimationUtils.getInterpolator(), () -> { - enableClipping(true); if (finishRunnable != null) { finishRunnable.run(); } @@ -204,14 +205,39 @@ public class KeyguardPINView extends KeyguardPinBasedInputView { return true; } - private void enableClipping(boolean enable) { - mContainer.setClipToPadding(enable); - mContainer.setClipChildren(enable); - setClipChildren(enable); - } - @Override public boolean hasOverlappingRendering() { return false; } + + /** Animate subviews according to expansion or time. */ + private void animate(float progress) { + Interpolator standardDecelerate = Interpolators.STANDARD_DECELERATE; + Interpolator legacyDecelerate = Interpolators.LEGACY_DECELERATE; + + mBouncerMessageView.setTranslationY( + mYTrans - mYTrans * standardDecelerate.getInterpolation(progress)); + + for (int i = 0; i < mViews.length; i++) { + View[] row = mViews[i]; + for (View view : row) { + if (view == null) { + continue; + } + + float scaledProgress = legacyDecelerate.getInterpolation(MathUtils.constrain( + (progress - 0.075f * i) / (1f - 0.075f * mViews.length), + 0f, + 1f + )); + view.setAlpha(scaledProgress); + int yDistance = mYTrans + mYTransOffset * i; + view.setTranslationY( + yDistance - (yDistance * standardDecelerate.getInterpolation(progress))); + if (view instanceof NumPadAnimationListener) { + ((NumPadAnimationListener) view).setProgress(scaledProgress); + } + } + } + } } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java index 1862fc7f6603..afc25909ca91 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternView.java @@ -71,7 +71,7 @@ public class KeyguardPatternView extends KeyguardInputView */ private long mLastPokeTime = -UNLOCK_PATTERN_WAKE_INTERVAL_MS; - KeyguardMessageArea mSecurityMessageDisplay; + BouncerKeyguardMessageArea mSecurityMessageDisplay; private View mEcaView; private ConstraintLayout mContainer; @@ -120,7 +120,7 @@ public class KeyguardPatternView extends KeyguardInputView @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); - mSecurityMessageDisplay = KeyguardMessageArea.findSecurityMessageDisplay(this); + mSecurityMessageDisplay = findViewById(R.id.bouncer_message_area); } @Override diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java index 9aa6f0320f50..987164557a7a 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPatternViewController.java @@ -59,12 +59,9 @@ public class KeyguardPatternViewController private final LatencyTracker mLatencyTracker; private final FalsingCollector mFalsingCollector; private final EmergencyButtonController mEmergencyButtonController; - private final KeyguardMessageAreaController.Factory mMessageAreaControllerFactory; private final DevicePostureController mPostureController; private final DevicePostureController.Callback mPostureCallback = posture -> mView.onDevicePostureChanged(posture); - - private KeyguardMessageAreaController mMessageAreaController; private LockPatternView mLockPatternView; private CountDownTimer mCountdownTimer; private AsyncTask<?, ?, ?> mPendingLockCheck; @@ -201,15 +198,13 @@ public class KeyguardPatternViewController EmergencyButtonController emergencyButtonController, KeyguardMessageAreaController.Factory messageAreaControllerFactory, DevicePostureController postureController) { - super(view, securityMode, keyguardSecurityCallback, emergencyButtonController); + super(view, securityMode, keyguardSecurityCallback, emergencyButtonController, + messageAreaControllerFactory); mKeyguardUpdateMonitor = keyguardUpdateMonitor; mLockPatternUtils = lockPatternUtils; mLatencyTracker = latencyTracker; mFalsingCollector = falsingCollector; mEmergencyButtonController = emergencyButtonController; - mMessageAreaControllerFactory = messageAreaControllerFactory; - KeyguardMessageArea kma = KeyguardMessageArea.findSecurityMessageDisplay(mView); - mMessageAreaController = mMessageAreaControllerFactory.create(kma); mLockPatternView = mView.findViewById(R.id.lockPatternView); mPostureController = postureController; } @@ -217,7 +212,6 @@ public class KeyguardPatternViewController @Override public void onInit() { super.onInit(); - mMessageAreaController.init(); } @Override @@ -346,6 +340,9 @@ public class KeyguardPatternViewController @Override public void showMessage(CharSequence message, ColorStateList colorState) { + if (mMessageAreaController == null) { + return; + } if (colorState != null) { mMessageAreaController.setNextMessageColor(colorState); } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java index 9f4585fb1a92..89fcc47caf57 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPinViewController.java @@ -82,6 +82,12 @@ public class KeyguardPinViewController } @Override + public void startAppearAnimation() { + mMessageAreaController.setMessageIfEmpty(R.string.keyguard_enter_your_pin); + super.startAppearAnimation(); + } + + @Override public boolean startDisappearAnimation(Runnable finishRunnable) { return mView.startDisappearAnimation( mKeyguardUpdateMonitor.needsSlowUnlockTransition(), finishRunnable); diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java index d0baf3dad79d..f73c98e4971b 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java @@ -665,7 +665,8 @@ public class KeyguardSecurityContainer extends FrameLayout { // When using EXACTLY spec, measure will use the layout width if > 0. Set before // measuring the child lp.width = MeasureSpec.getSize(updatedWidthMeasureSpec); - measureChildWithMargins(view, updatedWidthMeasureSpec, 0, heightMeasureSpec, 0); + measureChildWithMargins(view, updatedWidthMeasureSpec, 0, + heightMeasureSpec, 0); maxWidth = Math.max(maxWidth, view.getMeasuredWidth() + lp.leftMargin + lp.rightMargin); @@ -1306,7 +1307,6 @@ public class KeyguardSecurityContainer extends FrameLayout { int yTrans = mResources.getDimensionPixelSize(R.dimen.bouncer_user_switcher_y_trans); if (mResources.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { mUserSwitcherViewGroup.setTranslationY(yTrans); - mViewFlipper.setTranslationY(-yTrans); } else { // Attempt to reposition a bit higher to make up for this frame being a bit lower // on the device diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipperController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipperController.java index 3aa5ada0794d..bddf4b09ebb3 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipperController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityViewFlipperController.java @@ -146,7 +146,8 @@ public class KeyguardSecurityViewFlipperController protected NullKeyguardInputViewController(SecurityMode securityMode, KeyguardSecurityCallback keyguardSecurityCallback, EmergencyButtonController emergencyButtonController) { - super(null, securityMode, keyguardSecurityCallback, emergencyButtonController); + super(null, securityMode, keyguardSecurityCallback, emergencyButtonController, + null); } @Override @@ -156,7 +157,6 @@ public class KeyguardSecurityViewFlipperController @Override public void onStartingToHide() { - } } } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimInputView.kt b/packages/SystemUI/src/com/android/keyguard/KeyguardSimInputView.kt new file mode 100644 index 000000000000..b4bfca1185f4 --- /dev/null +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimInputView.kt @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.keyguard + +import android.content.Context +import android.util.AttributeSet +import android.widget.ImageView +import androidx.core.graphics.drawable.DrawableCompat +import com.android.systemui.R + +abstract class KeyguardSimInputView(context: Context, attrs: AttributeSet) : + KeyguardPinBasedInputView(context, attrs) { + private var simImageView: ImageView? = null + private var disableESimButton: KeyguardEsimArea? = null + + override fun onFinishInflate() { + simImageView = findViewById(R.id.keyguard_sim) + disableESimButton = findViewById(R.id.keyguard_esim_area) + super.onFinishInflate() + } + + /** Set UI state based on whether there is a locked eSim card */ + fun setESimLocked(isESimLocked: Boolean, subId: Int) { + disableESimButton?.setSubscriptionId(subId) + disableESimButton?.visibility = if (isESimLocked) VISIBLE else GONE + simImageView?.visibility = if (isESimLocked) GONE else VISIBLE + } + + override fun reloadColors() { + super.reloadColors() + val customAttrs = intArrayOf(android.R.attr.textColorSecondary) + val a = context.obtainStyledAttributes(customAttrs) + val imageColor = a.getColor(0, 0) + a.recycle() + simImageView?.let { + val wrappedDrawable = DrawableCompat.wrap(it.drawable) + DrawableCompat.setTint(wrappedDrawable, imageColor) + } + } +} diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java index ae9d3dfec3b2..9d170150a709 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinView.java @@ -18,21 +18,14 @@ package com.android.keyguard; import android.content.Context; import android.content.res.Configuration; -import android.content.res.TypedArray; -import android.graphics.drawable.Drawable; import android.util.AttributeSet; -import android.view.View; -import android.widget.ImageView; - -import androidx.core.graphics.drawable.DrawableCompat; import com.android.systemui.R; /** * Displays a PIN pad for unlocking. */ -public class KeyguardSimPinView extends KeyguardPinBasedInputView { - private ImageView mSimImageView; +public class KeyguardSimPinView extends KeyguardSimInputView { public static final String TAG = "KeyguardSimPinView"; public KeyguardSimPinView(Context context) { @@ -43,12 +36,6 @@ public class KeyguardSimPinView extends KeyguardPinBasedInputView { super(context, attrs); } - public void setEsimLocked(boolean locked, int subscriptionId) { - KeyguardEsimArea esimButton = findViewById(R.id.keyguard_esim_area); - esimButton.setSubscriptionId(subscriptionId); - esimButton.setVisibility(locked ? View.VISIBLE : View.GONE); - } - @Override protected void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); @@ -68,7 +55,6 @@ public class KeyguardSimPinView extends KeyguardPinBasedInputView { @Override protected void onFinishInflate() { - mSimImageView = findViewById(R.id.keyguard_sim); super.onFinishInflate(); if (mEcaView instanceof EmergencyCarrierArea) { @@ -86,17 +72,4 @@ public class KeyguardSimPinView extends KeyguardPinBasedInputView { return getContext().getString( com.android.internal.R.string.keyguard_accessibility_sim_pin_unlock); } - - @Override - public void reloadColors() { - super.reloadColors(); - - int[] customAttrs = {android.R.attr.textColorSecondary}; - TypedArray a = getContext().obtainStyledAttributes(customAttrs); - int imageColor = a.getColor(0, 0); - a.recycle(); - Drawable wrappedDrawable = DrawableCompat.wrap(mSimImageView.getDrawable()); - DrawableCompat.setTint(wrappedDrawable, imageColor); - } } - diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java index ecd88e6fe90c..76f7d785071d 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPinViewController.java @@ -105,7 +105,7 @@ public class KeyguardSimPinViewController showDefaultMessage(); } - mView.setEsimLocked(KeyguardEsimArea.isEsimLocked(mView.getContext(), mSubId), mSubId); + mView.setESimLocked(KeyguardEsimArea.isEsimLocked(mView.getContext(), mSubId), mSubId); } @Override diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java index c0971bf8c16d..5f45fe31a779 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukView.java @@ -19,13 +19,8 @@ package com.android.keyguard; import static com.android.systemui.util.PluralMessageFormaterKt.icuMessageFormat; import android.content.Context; -import android.content.res.TypedArray; -import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.util.Log; -import android.widget.ImageView; - -import androidx.core.graphics.drawable.DrawableCompat; import com.android.systemui.R; @@ -33,8 +28,7 @@ import com.android.systemui.R; /** * Displays a PIN pad for entering a PUK (Pin Unlock Kode) provided by a carrier. */ -public class KeyguardSimPukView extends KeyguardPinBasedInputView { - private ImageView mSimImageView; +public class KeyguardSimPukView extends KeyguardSimInputView { private static final boolean DEBUG = KeyguardConstants.DEBUG; public static final String TAG = "KeyguardSimPukView"; @@ -86,7 +80,6 @@ public class KeyguardSimPukView extends KeyguardPinBasedInputView { @Override protected void onFinishInflate() { - mSimImageView = findViewById(R.id.keyguard_sim); super.onFinishInflate(); if (mEcaView instanceof EmergencyCarrierArea) { @@ -104,18 +97,4 @@ public class KeyguardSimPukView extends KeyguardPinBasedInputView { return getContext().getString( com.android.internal.R.string.keyguard_accessibility_sim_puk_unlock); } - - @Override - public void reloadColors() { - super.reloadColors(); - - int[] customAttrs = {android.R.attr.textColorSecondary}; - TypedArray a = getContext().obtainStyledAttributes(customAttrs); - int imageColor = a.getColor(0, 0); - a.recycle(); - Drawable wrappedDrawable = DrawableCompat.wrap(mSimImageView.getDrawable()); - DrawableCompat.setTint(wrappedDrawable, imageColor); - } } - - diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukViewController.java index 203f9b660536..d8cffd7984ba 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukViewController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSimPukViewController.java @@ -30,7 +30,6 @@ import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.util.Log; -import android.view.View; import android.view.WindowManager; import android.widget.ImageView; @@ -173,11 +172,9 @@ public class KeyguardSimPukViewController if (mShowDefaultMessage) { showDefaultMessage(); } - boolean isEsimLocked = KeyguardEsimArea.isEsimLocked(mView.getContext(), mSubId); - KeyguardEsimArea esimButton = mView.findViewById(R.id.keyguard_esim_area); - esimButton.setSubscriptionId(mSubId); - esimButton.setVisibility(isEsimLocked ? View.VISIBLE : View.GONE); + mView.setESimLocked(KeyguardEsimArea.isEsimLocked(mView.getContext(), mSubId), mSubId); + mPasswordEntry.requestFocus(); } } diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUnfoldTransition.kt b/packages/SystemUI/src/com/android/keyguard/KeyguardUnfoldTransition.kt index acbea1beeae3..7d6f377d5287 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUnfoldTransition.kt +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUnfoldTransition.kt @@ -50,12 +50,10 @@ constructor( viewsIdToTranslate = setOf( ViewIdToTranslate(R.id.keyguard_status_area, LEFT, filterNever), - ViewIdToTranslate(R.id.controls_button, LEFT, filterNever), ViewIdToTranslate(R.id.lockscreen_clock_view_large, LEFT, filterSplitShadeOnly), ViewIdToTranslate(R.id.lockscreen_clock_view, LEFT, filterNever), ViewIdToTranslate( R.id.notification_stack_scroller, RIGHT, filterSplitShadeOnly), - ViewIdToTranslate(R.id.wallet_button, RIGHT, filterNever), ViewIdToTranslate(R.id.start_button, LEFT, filterNever), ViewIdToTranslate(R.id.end_button, RIGHT, filterNever)), progressProvider = unfoldProgressProvider) diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index 49843008af9f..32c1cf9802ab 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -26,6 +26,7 @@ import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_LOCKOUT_N import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_LOCKOUT_PERMANENT; import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_LOCKOUT_TIMED; import static android.hardware.biometrics.BiometricConstants.LockoutMode; +import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_START; import static android.os.BatteryManager.BATTERY_STATUS_UNKNOWN; import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT; @@ -104,8 +105,10 @@ import android.os.Handler; import android.os.IRemoteCallback; import android.os.Looper; import android.os.Message; +import android.os.PowerManager; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.SystemClock; import android.os.Trace; import android.os.UserHandle; import android.os.UserManager; @@ -154,6 +157,7 @@ import com.google.android.collect.Lists; import java.io.PrintWriter; import java.lang.ref.WeakReference; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -164,6 +168,7 @@ import java.util.Set; import java.util.TimeZone; import java.util.concurrent.Executor; import java.util.function.Consumer; +import java.util.stream.Collectors; import javax.inject.Inject; import javax.inject.Provider; @@ -278,6 +283,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab private final AuthController mAuthController; private final StatusBarStateController mStatusBarStateController; private final UiEventLogger mUiEventLogger; + private final Set<Integer> mFaceAcquiredInfoIgnoreList; private int mStatusBarState; private final StatusBarStateController.StateListener mStatusBarStateControllerListener = new StatusBarStateController.StateListener() { @@ -356,6 +362,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab private final Executor mBackgroundExecutor; private SensorPrivacyManager mSensorPrivacyManager; private final ActiveUnlockConfig mActiveUnlockConfig; + private final PowerManager mPowerManager; + private final boolean mWakeOnFingerprintAcquiredStart; /** * Short delay before restarting fingerprint authentication after a successful try. This should @@ -466,6 +474,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab FACE_AUTH_TRIGGERED_TRUST_DISABLED); } + mLogger.logTrustChanged(wasTrusted, enabled, userId); for (int i = 0; i < mCallbacks.size(); i++) { KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); if (cb != null) { @@ -481,12 +490,16 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab final boolean userHasTrust = getUserHasTrust(userId); if (userHasTrust && trustGrantedMessages != null) { for (String msg : trustGrantedMessages) { - if (!TextUtils.isEmpty(msg)) { - message = msg; + message = msg; + if (!TextUtils.isEmpty(message)) { break; } } } + + if (message != null) { + mLogger.logShowTrustGrantedMessage(message.toString()); + } for (int i = 0; i < mCallbacks.size(); i++) { KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); if (cb != null) { @@ -743,6 +756,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab mFingerprintCancelSignal = null; updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE, FACE_AUTH_UPDATED_FP_AUTHENTICATED); + mLogger.d("onFingerprintAuthenticated"); for (int i = 0; i < mCallbacks.size(); i++) { KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); if (cb != null) { @@ -799,6 +813,11 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab private void handleFingerprintAcquired( @BiometricFingerprintConstants.FingerprintAcquired int acquireInfo) { Assert.isMainThread(); + if (mWakeOnFingerprintAcquiredStart && acquireInfo == FINGERPRINT_ACQUIRED_START) { + mPowerManager.wakeUp( + SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE, + "com.android.systemui.keyguard:FINGERPRINT_ACQUIRED_START"); + } for (int i = 0; i < mCallbacks.size(); i++) { KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); if (cb != null) { @@ -986,6 +1005,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab mFaceCancelSignal = null; updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE, FACE_AUTH_UPDATED_ON_FACE_AUTHENTICATED); + mLogger.d("onFaceAuthenticated"); for (int i = 0; i < mCallbacks.size(); i++) { KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); if (cb != null) { @@ -1006,6 +1026,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab private void handleFaceAuthFailed() { Assert.isMainThread(); + mLogger.d("onFaceAuthFailed"); mFaceCancelSignal = null; setFaceRunningState(BIOMETRIC_STATE_STOPPED); for (int i = 0; i < mCallbacks.size(); i++) { @@ -1622,6 +1643,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab @Override public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) { + if (mFaceAcquiredInfoIgnoreList.contains(helpMsgId)) { + return; + } handleFaceHelp(helpMsgId, helpString.toString()); } @@ -1888,7 +1912,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab KeyguardUpdateMonitorLogger logger, UiEventLogger uiEventLogger, // This has to be a provider because SessionTracker depends on KeyguardUpdateMonitor :( - Provider<SessionTracker> sessionTrackerProvider) { + Provider<SessionTracker> sessionTrackerProvider, + PowerManager powerManager) { mContext = context; mSubscriptionManager = SubscriptionManager.from(context); mTelephonyListenerManager = telephonyListenerManager; @@ -1909,7 +1934,15 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab mLogger = logger; mUiEventLogger = uiEventLogger; mSessionTrackerProvider = sessionTrackerProvider; + mPowerManager = powerManager; mActiveUnlockConfig.setKeyguardUpdateMonitor(this); + mWakeOnFingerprintAcquiredStart = context.getResources() + .getBoolean(com.android.internal.R.bool.kg_wake_on_acquire_start); + mFaceAcquiredInfoIgnoreList = Arrays.stream( + mContext.getResources().getIntArray( + R.array.config_face_acquire_device_entry_ignorelist)) + .boxed() + .collect(Collectors.toSet()); mHandler = new Handler(mainLooper) { @Override @@ -2605,6 +2638,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab final boolean biometricEnabledForUser = mBiometricEnabledForUser.get(user); final boolean shouldListenForFaceAssistant = shouldListenForFaceAssistant(); final boolean onlyFaceEnrolled = isOnlyFaceEnrolled(); + final boolean fpOrFaceIsLockedOut = isFaceLockedOut() || fpLockedout; // Only listen if this KeyguardUpdateMonitor belongs to the primary user. There is an // instance of KeyguardUpdateMonitor for each user but KeyguardUpdateMonitor is user-aware. @@ -2621,7 +2655,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab && strongAuthAllowsScanning && mIsPrimaryUser && (!mSecureCameraLaunched || mOccludingAppRequestingFace) && !faceAuthenticated - && !fpLockedout; + && !fpOrFaceIsLockedOut; // Aggregate relevant fields for debug logging. maybeLogListenerModelData( @@ -2636,6 +2670,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab mBouncerIsOrWillBeShowing, faceAuthenticated, faceDisabledForUser, + isFaceLockedOut(), + fpLockedout, mGoingToSleep, awakeKeyguardExcludingBouncerShowing, mKeyguardGoingAway, @@ -3445,6 +3481,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab mUserFaceAuthenticated.clear(); mTrustManager.clearAllBiometricRecognized(BiometricSourceType.FINGERPRINT, unlockedUser); mTrustManager.clearAllBiometricRecognized(BiometricSourceType.FACE, unlockedUser); + mLogger.d("clearBiometricRecognized"); for (int i = 0; i < mCallbacks.size(); i++) { KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); @@ -3694,6 +3731,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab @Override public void dump(PrintWriter pw, String[] args) { pw.println("KeyguardUpdateMonitor state:"); + pw.println(" getUserHasTrust()=" + getUserHasTrust(getCurrentUser())); + pw.println(" getUserUnlockedWithBiometric()=" + + getUserUnlockedWithBiometric(getCurrentUser())); + pw.println(" mWakeOnFingerprintAcquiredStart=" + mWakeOnFingerprintAcquiredStart); pw.println(" SIM States:"); for (SimData data : mSimDatas.values()) { pw.println(" " + data.toString()); diff --git a/packages/SystemUI/src/com/android/keyguard/NumPadAnimationListener.kt b/packages/SystemUI/src/com/android/keyguard/NumPadAnimationListener.kt new file mode 100644 index 000000000000..f449edf8e894 --- /dev/null +++ b/packages/SystemUI/src/com/android/keyguard/NumPadAnimationListener.kt @@ -0,0 +1,23 @@ +/* + * 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.keyguard + +/** Interface for classes to track animation progress. */ +interface NumPadAnimationListener { + /** Track the progress of the animation. */ + fun setProgress(progress: Float) +} diff --git a/packages/SystemUI/src/com/android/keyguard/NumPadAnimator.java b/packages/SystemUI/src/com/android/keyguard/NumPadAnimator.java index c91c8992780c..41111e3d3c6c 100644 --- a/packages/SystemUI/src/com/android/keyguard/NumPadAnimator.java +++ b/packages/SystemUI/src/com/android/keyguard/NumPadAnimator.java @@ -48,6 +48,10 @@ class NumPadAnimator { private int mTextColorPrimary; private int mTextColorPressed; private int mStyle; + private float mStartRadius; + private float mEndRadius; + private int mHeight; + private static final int EXPAND_ANIMATION_MS = 100; private static final int EXPAND_COLOR_ANIMATION_MS = 50; private static final int CONTRACT_ANIMATION_DELAY_MS = 33; @@ -80,12 +84,20 @@ class NumPadAnimator { mContractAnimatorSet.start(); } + public void setProgress(float progress) { + mBackground.setCornerRadius(mEndRadius + (mStartRadius - mEndRadius) * progress); + int height = (int) (mHeight * 0.7f + mHeight * 0.3 * progress); + int difference = mHeight - height; + mBackground.setBounds(0, difference / 2, mHeight, mHeight - difference / 2); + } + void onLayout(int height) { - float startRadius = height / 2f; - float endRadius = height / 4f; - mBackground.setCornerRadius(startRadius); - mExpandAnimator.setFloatValues(startRadius, endRadius); - mContractAnimator.setFloatValues(endRadius, startRadius); + mHeight = height; + mStartRadius = height / 2f; + mEndRadius = height / 4f; + mBackground.setCornerRadius(mStartRadius); + mExpandAnimator.setFloatValues(mStartRadius, mEndRadius); + mContractAnimator.setFloatValues(mEndRadius, mStartRadius); } /** diff --git a/packages/SystemUI/src/com/android/keyguard/NumPadButton.java b/packages/SystemUI/src/com/android/keyguard/NumPadButton.java index 8099f75ed7d4..37060987cb21 100644 --- a/packages/SystemUI/src/com/android/keyguard/NumPadButton.java +++ b/packages/SystemUI/src/com/android/keyguard/NumPadButton.java @@ -30,7 +30,7 @@ import androidx.annotation.Nullable; /** * Similar to the {@link NumPadKey}, but displays an image. */ -public class NumPadButton extends AlphaOptimizedImageButton { +public class NumPadButton extends AlphaOptimizedImageButton implements NumPadAnimationListener { @Nullable private NumPadAnimator mAnimator; @@ -104,4 +104,11 @@ public class NumPadButton extends AlphaOptimizedImageButton { a.recycle(); ((VectorDrawable) getDrawable()).setTintList(ColorStateList.valueOf(imageColor)); } + + @Override + public void setProgress(float progress) { + if (mAnimator != null) { + mAnimator.setProgress(progress); + } + } } diff --git a/packages/SystemUI/src/com/android/keyguard/NumPadKey.java b/packages/SystemUI/src/com/android/keyguard/NumPadKey.java index 4aed2513d4f2..0a4880e1ce66 100644 --- a/packages/SystemUI/src/com/android/keyguard/NumPadKey.java +++ b/packages/SystemUI/src/com/android/keyguard/NumPadKey.java @@ -37,7 +37,10 @@ import com.android.internal.widget.LockPatternUtils; import com.android.settingslib.Utils; import com.android.systemui.R; -public class NumPadKey extends ViewGroup { +/** + * Viewgroup for the bouncer numpad button, specifically for digits. + */ +public class NumPadKey extends ViewGroup implements NumPadAnimationListener { // list of "ABC", etc per digit, starting with '0' static String sKlondike[]; @@ -221,4 +224,11 @@ public class NumPadKey extends ViewGroup { performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY, HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING); } + + @Override + public void setProgress(float progress) { + if (mAnimator != null) { + mAnimator.setProgress(progress); + } + } } diff --git a/packages/SystemUI/src/com/android/keyguard/SecurityMessageDisplay.java b/packages/SystemUI/src/com/android/keyguard/SecurityMessageDisplay.java index 7c86a1dfb797..777bd19864bf 100644 --- a/packages/SystemUI/src/com/android/keyguard/SecurityMessageDisplay.java +++ b/packages/SystemUI/src/com/android/keyguard/SecurityMessageDisplay.java @@ -20,7 +20,8 @@ import android.content.res.ColorStateList; public interface SecurityMessageDisplay { - void setNextMessageColor(ColorStateList colorState); + /** Set text color for the next security message. */ + default void setNextMessageColor(ColorStateList colorState) {} void setMessage(CharSequence msg); diff --git a/packages/SystemUI/src/com/android/keyguard/logging/BiometricMessageDeferralLogger.kt b/packages/SystemUI/src/com/android/keyguard/logging/BiometricMessageDeferralLogger.kt new file mode 100644 index 000000000000..2c2ab7b39161 --- /dev/null +++ b/packages/SystemUI/src/com/android/keyguard/logging/BiometricMessageDeferralLogger.kt @@ -0,0 +1,71 @@ +/* + * 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.keyguard.logging + +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.log.LogBuffer +import com.android.systemui.log.LogLevel.DEBUG +import com.android.systemui.log.dagger.BiometricMessagesLog +import javax.inject.Inject + +/** Helper class for logging for [com.android.systemui.biometrics.FaceHelpMessageDeferral] */ +@SysUISingleton +class FaceMessageDeferralLogger +@Inject +constructor(@BiometricMessagesLog private val logBuffer: LogBuffer) : + BiometricMessageDeferralLogger(logBuffer, "FaceMessageDeferralLogger") + +open class BiometricMessageDeferralLogger( + private val logBuffer: LogBuffer, + private val tag: String +) { + fun reset() { + logBuffer.log(tag, DEBUG, "reset") + } + + fun logUpdateMessage(acquiredInfo: Int, helpString: String) { + logBuffer.log( + tag, + DEBUG, + { + int1 = acquiredInfo + str1 = helpString + }, + { "updateMessage acquiredInfo=$int1 helpString=$str1" } + ) + } + + fun logFrameProcessed( + acquiredInfo: Int, + totalFrames: Int, + mostFrequentAcquiredInfoToDefer: String? // may not meet the threshold + ) { + logBuffer.log( + tag, + DEBUG, + { + int1 = acquiredInfo + int2 = totalFrames + str1 = mostFrequentAcquiredInfoToDefer + }, + { + "frameProcessed acquiredInfo=$int1 totalFrames=$int2 " + + "messageToShowOnTimeout=$str1" + } + ) + } +} diff --git a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt index 2bc98f1a535c..7a00cd930f2a 100644 --- a/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt +++ b/packages/SystemUI/src/com/android/keyguard/logging/KeyguardUpdateMonitorLogger.kt @@ -340,4 +340,40 @@ class KeyguardUpdateMonitorLogger @Inject constructor( bool1 = dismissKeyguard }, { "reportUserRequestedUnlock origin=$str1 reason=$str2 dismissKeyguard=$bool1" }) } + + fun logShowTrustGrantedMessage( + message: String + ) { + logBuffer.log(TAG, DEBUG, { + str1 = message + }, { "showTrustGrantedMessage message$str1" }) + } + + fun logTrustChanged( + wasTrusted: Boolean, + isNowTrusted: Boolean, + userId: Int + ) { + logBuffer.log(TAG, DEBUG, { + bool1 = wasTrusted + bool2 = isNowTrusted + int1 = userId + }, { "onTrustChanged[user=$int1] wasTrusted=$bool1 isNowTrusted=$bool2" }) + } + + fun logKeyguardStateUpdate( + secure: Boolean, + canDismissLockScreen: Boolean, + trusted: Boolean, + trustManaged: Boolean + + ) { + logBuffer.log("KeyguardState", DEBUG, { + bool1 = secure + bool2 = canDismissLockScreen + bool3 = trusted + bool4 = trustManaged + }, { "#update secure=$bool1 canDismissKeyguard=$bool2" + + " trusted=$bool3 trustManaged=$bool4" }) + } } diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java index a1428f3120c8..ae73e34f5fda 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/WindowMagnificationController.java @@ -69,7 +69,6 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.graphics.SfVsyncFrameCallbackProvider; import com.android.systemui.R; import com.android.systemui.model.SysUiState; -import com.android.systemui.shared.system.WindowManagerWrapper; import java.io.PrintWriter; import java.text.NumberFormat; @@ -634,7 +633,7 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold * child of the surfaceView. */ private void createMirror() { - mMirrorSurface = WindowManagerWrapper.getInstance().mirrorDisplay(mDisplayId); + mMirrorSurface = mirrorDisplay(mDisplayId); if (!mMirrorSurface.isValid()) { return; } @@ -643,6 +642,25 @@ class WindowMagnificationController implements View.OnTouchListener, SurfaceHold modifyWindowMagnification(false); } + /** + * Mirrors a specified display. The SurfaceControl returned is the root of the mirrored + * hierarchy. + * + * @param displayId The id of the display to mirror + * @return The SurfaceControl for the root of the mirrored hierarchy. + */ + private SurfaceControl mirrorDisplay(final int displayId) { + try { + SurfaceControl outSurfaceControl = new SurfaceControl(); + WindowManagerGlobal.getWindowManagerService().mirrorDisplay(displayId, + outSurfaceControl); + return outSurfaceControl; + } catch (RemoteException e) { + Log.e(TAG, "Unable to reach window manager", e); + } + return null; + } + private void addDragTouchListeners() { mDragView = mMirrorView.findViewById(R.id.drag_handle); mLeftDrag = mMirrorView.findViewById(R.id.left_handle); diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintAndFaceIconController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintAndFaceIconController.kt index 40d1eff2a887..e4c197ff940e 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintAndFaceIconController.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintAndFaceIconController.kt @@ -29,8 +29,9 @@ import com.android.systemui.biometrics.AuthBiometricView.STATE_PENDING_CONFIRMAT /** Face/Fingerprint combined icon animator for BiometricPrompt. */ class AuthBiometricFingerprintAndFaceIconController( context: Context, - iconView: LottieAnimationView -) : AuthBiometricFingerprintIconController(context, iconView) { + iconView: LottieAnimationView, + iconViewOverlay: LottieAnimationView +) : AuthBiometricFingerprintIconController(context, iconView, iconViewOverlay) { override val actsAsConfirmButton: Boolean = true diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintAndFaceView.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintAndFaceView.kt index 7371442bdd07..7f5a67f8c327 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintAndFaceView.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintAndFaceView.kt @@ -39,5 +39,5 @@ class AuthBiometricFingerprintAndFaceView( override fun onPointerDown(failedModalities: Set<Int>) = failedModalities.contains(TYPE_FACE) override fun createIconController(): AuthIconController = - AuthBiometricFingerprintAndFaceIconController(mContext, mIconView) + AuthBiometricFingerprintAndFaceIconController(mContext, mIconView, mIconViewOverlay) } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt index 9b5f54a0a91d..b40b3560f9db 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintIconController.kt @@ -18,7 +18,12 @@ package com.android.systemui.biometrics import android.annotation.RawRes import android.content.Context +import android.hardware.fingerprint.FingerprintManager +import android.view.DisplayInfo +import android.view.Surface +import android.view.View import com.airbnb.lottie.LottieAnimationView +import com.android.settingslib.widget.LottieColorUtils import com.android.systemui.R import com.android.systemui.biometrics.AuthBiometricView.BiometricState import com.android.systemui.biometrics.AuthBiometricView.STATE_AUTHENTICATED @@ -32,14 +37,18 @@ import com.android.systemui.biometrics.AuthBiometricView.STATE_PENDING_CONFIRMAT /** Fingerprint only icon animator for BiometricPrompt. */ open class AuthBiometricFingerprintIconController( context: Context, - iconView: LottieAnimationView + iconView: LottieAnimationView, + protected val iconViewOverlay: LottieAnimationView ) : AuthIconController(context, iconView) { + private val isSideFps: Boolean var iconLayoutParamSize: Pair<Int, Int> = Pair(1, 1) set(value) { if (field == value) { return } + iconViewOverlay.layoutParams.width = value.first + iconViewOverlay.layoutParams.height = value.second iconView.layoutParams.width = value.first iconView.layoutParams.height = value.second field = value @@ -50,9 +59,53 @@ open class AuthBiometricFingerprintIconController( R.dimen.biometric_dialog_fingerprint_icon_width), context.resources.getDimensionPixelSize( R.dimen.biometric_dialog_fingerprint_icon_height)) + var sideFps = false + (context.getSystemService(Context.FINGERPRINT_SERVICE) + as FingerprintManager?)?.let { fpm -> + for (prop in fpm.sensorPropertiesInternal) { + if (prop.isAnySidefpsType) { + sideFps = true + } + } + } + isSideFps = sideFps + val displayInfo = DisplayInfo() + context.display?.getDisplayInfo(displayInfo) + if (isSideFps && displayInfo.rotation == Surface.ROTATION_180) { + iconView.rotation = 180f + } } - override fun updateIcon(@BiometricState lastState: Int, @BiometricState newState: Int) { + private fun updateIconSideFps(@BiometricState lastState: Int, @BiometricState newState: Int) { + val displayInfo = DisplayInfo() + context.display?.getDisplayInfo(displayInfo) + val rotation = displayInfo.rotation + val iconAnimation = getSideFpsAnimationForTransition(rotation) + val iconViewOverlayAnimation = + getSideFpsOverlayAnimationForTransition(lastState, newState, rotation) ?: return + + if (!(lastState == STATE_AUTHENTICATING_ANIMATING_IN && newState == STATE_AUTHENTICATING)) { + iconView.setAnimation(iconAnimation) + iconViewOverlay.setAnimation(iconViewOverlayAnimation) + } + + val iconContentDescription = getIconContentDescription(newState) + if (iconContentDescription != null) { + iconView.contentDescription = iconContentDescription + iconViewOverlay.contentDescription = iconContentDescription + } + + iconView.frame = 0 + iconViewOverlay.frame = 0 + if (shouldAnimateForTransition(lastState, newState)) { + iconView.playAnimation() + iconViewOverlay.playAnimation() + } + LottieColorUtils.applyDynamicColors(context, iconView) + LottieColorUtils.applyDynamicColors(context, iconViewOverlay) + } + + private fun updateIconNormal(@BiometricState lastState: Int, @BiometricState newState: Int) { val icon = getAnimationForTransition(lastState, newState) ?: return if (!(lastState == STATE_AUTHENTICATING_ANIMATING_IN && newState == STATE_AUTHENTICATING)) { @@ -68,6 +121,16 @@ open class AuthBiometricFingerprintIconController( if (shouldAnimateForTransition(lastState, newState)) { iconView.playAnimation() } + LottieColorUtils.applyDynamicColors(context, iconView) + } + + override fun updateIcon(@BiometricState lastState: Int, @BiometricState newState: Int) { + if (isSideFps) { + updateIconSideFps(lastState, newState) + } else { + iconViewOverlay.visibility = View.GONE + updateIconNormal(lastState, newState) + } } private fun getIconContentDescription(@BiometricState newState: Int): CharSequence? { @@ -125,4 +188,89 @@ open class AuthBiometricFingerprintIconController( } return if (id != null) return id else null } + + @RawRes + private fun getSideFpsAnimationForTransition(rotation: Int): Int = when (rotation) { + Surface.ROTATION_0 -> R.raw.biometricprompt_landscape_base + Surface.ROTATION_90 -> R.raw.biometricprompt_portrait_base_topleft + Surface.ROTATION_180 -> R.raw.biometricprompt_landscape_base + Surface.ROTATION_270 -> R.raw.biometricprompt_portrait_base_bottomright + else -> R.raw.biometricprompt_landscape_base + } + + @RawRes + private fun getSideFpsOverlayAnimationForTransition( + @BiometricState oldState: Int, + @BiometricState newState: Int, + rotation: Int + ): Int? = when (newState) { + STATE_HELP, + STATE_ERROR -> { + when (rotation) { + Surface.ROTATION_0 -> R.raw.biometricprompt_fingerprint_to_error_landscape + Surface.ROTATION_90 -> + R.raw.biometricprompt_symbol_fingerprint_to_error_portrait_topleft + Surface.ROTATION_180 -> + R.raw.biometricprompt_fingerprint_to_error_landscape + Surface.ROTATION_270 -> + R.raw.biometricprompt_symbol_fingerprint_to_error_portrait_bottomright + else -> R.raw.biometricprompt_fingerprint_to_error_landscape + } + } + STATE_AUTHENTICATING_ANIMATING_IN, + STATE_AUTHENTICATING -> { + if (oldState == STATE_ERROR || oldState == STATE_HELP) { + when (rotation) { + Surface.ROTATION_0 -> + R.raw.biometricprompt_symbol_error_to_fingerprint_landscape + Surface.ROTATION_90 -> + R.raw.biometricprompt_symbol_error_to_fingerprint_portrait_topleft + Surface.ROTATION_180 -> + R.raw.biometricprompt_symbol_error_to_fingerprint_landscape + Surface.ROTATION_270 -> + R.raw.biometricprompt_symbol_error_to_fingerprint_portrait_bottomright + else -> R.raw.biometricprompt_symbol_error_to_fingerprint_landscape + } + } else { + when (rotation) { + Surface.ROTATION_0 -> R.raw.biometricprompt_fingerprint_to_error_landscape + Surface.ROTATION_90 -> + R.raw.biometricprompt_symbol_fingerprint_to_error_portrait_topleft + Surface.ROTATION_180 -> + R.raw.biometricprompt_fingerprint_to_error_landscape + Surface.ROTATION_270 -> + R.raw.biometricprompt_symbol_fingerprint_to_error_portrait_bottomright + else -> R.raw.biometricprompt_fingerprint_to_error_landscape + } + } + } + STATE_AUTHENTICATED -> { + if (oldState == STATE_ERROR || oldState == STATE_HELP) { + when (rotation) { + Surface.ROTATION_0 -> + R.raw.biometricprompt_symbol_error_to_success_landscape + Surface.ROTATION_90 -> + R.raw.biometricprompt_symbol_error_to_success_portrait_topleft + Surface.ROTATION_180 -> + R.raw.biometricprompt_symbol_error_to_success_landscape + Surface.ROTATION_270 -> + R.raw.biometricprompt_symbol_error_to_success_portrait_bottomright + else -> R.raw.biometricprompt_symbol_error_to_success_landscape + } + } else { + when (rotation) { + Surface.ROTATION_0 -> + R.raw.biometricprompt_symbol_fingerprint_to_success_landscape + Surface.ROTATION_90 -> + R.raw.biometricprompt_symbol_fingerprint_to_success_portrait_topleft + Surface.ROTATION_180 -> + R.raw.biometricprompt_symbol_fingerprint_to_success_landscape + Surface.ROTATION_270 -> + R.raw.biometricprompt_symbol_fingerprint_to_success_portrait_bottomright + else -> R.raw.biometricprompt_symbol_fingerprint_to_success_landscape + } + } + } + else -> null + } } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintView.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintView.kt index 9cce066afe9d..20666344ade8 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintView.kt +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricFingerprintView.kt @@ -86,7 +86,7 @@ open class AuthBiometricFingerprintView( override fun supportsSmallDialog() = false override fun createIconController(): AuthIconController = - AuthBiometricFingerprintIconController(mContext, mIconView) + AuthBiometricFingerprintIconController(mContext, mIconView, mIconViewOverlay) fun updateOverrideIconLayoutParamsSize() { udfpsAdapter?.let { diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java index fc5cf9f005ed..0ac71c462e21 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthBiometricView.java @@ -133,6 +133,7 @@ public abstract class AuthBiometricView extends LinearLayout { private TextView mSubtitleView; private TextView mDescriptionView; private View mIconHolderView; + protected LottieAnimationView mIconViewOverlay; protected LottieAnimationView mIconView; protected TextView mIndicatorView; @@ -168,6 +169,10 @@ public abstract class AuthBiometricView extends LinearLayout { private Animator.AnimatorListener mJankListener; + private final boolean mUseCustomBpSize; + private final int mCustomBpWidth; + private final int mCustomBpHeight; + private final OnClickListener mBackgroundClickListener = (view) -> { if (mState == STATE_AUTHENTICATED) { Log.w(TAG, "Ignoring background click after authenticated"); @@ -208,6 +213,10 @@ public abstract class AuthBiometricView extends LinearLayout { handleResetAfterHelp(); Utils.notifyAccessibilityContentChanged(mAccessibilityManager, this); }; + + mUseCustomBpSize = getResources().getBoolean(R.bool.use_custom_bp_size); + mCustomBpWidth = getResources().getDimensionPixelSize(R.dimen.biometric_dialog_width); + mCustomBpHeight = getResources().getDimensionPixelSize(R.dimen.biometric_dialog_height); } /** Delay after authentication is confirmed, before the dialog should be animated away. */ @@ -651,6 +660,7 @@ public abstract class AuthBiometricView extends LinearLayout { mTitleView = findViewById(R.id.title); mSubtitleView = findViewById(R.id.subtitle); mDescriptionView = findViewById(R.id.description); + mIconViewOverlay = findViewById(R.id.biometric_icon_overlay); mIconView = findViewById(R.id.biometric_icon); mIconHolderView = findViewById(R.id.biometric_icon_frame); mIndicatorView = findViewById(R.id.indicator); @@ -689,6 +699,11 @@ public abstract class AuthBiometricView extends LinearLayout { mIconController = createIconController(); if (mIconController.getActsAsConfirmButton()) { + mIconViewOverlay.setOnClickListener((view)->{ + if (mState == STATE_PENDING_CONFIRMATION) { + updateState(STATE_AUTHENTICATED); + } + }); mIconView.setOnClickListener((view) -> { if (mState == STATE_PENDING_CONFIRMATION) { updateState(STATE_AUTHENTICATED); @@ -827,14 +842,17 @@ public abstract class AuthBiometricView extends LinearLayout { @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - final int width = MeasureSpec.getSize(widthMeasureSpec); - final int height = MeasureSpec.getSize(heightMeasureSpec); + int width = MeasureSpec.getSize(widthMeasureSpec); + int height = MeasureSpec.getSize(heightMeasureSpec); - final int newWidth = Math.min(width, height); + if (mUseCustomBpSize) { + width = mCustomBpWidth; + height = mCustomBpHeight; + } else { + width = Math.min(width, height); + } - // Use "newWidth" instead, so the landscape dialog width is the same as the portrait - // width. - mLayoutParams = onMeasureInternal(newWidth, height); + mLayoutParams = onMeasureInternal(width, height); setMeasuredDimension(mLayoutParams.mMediumWidth, mLayoutParams.mMediumHeight); } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/FaceHelpMessageDeferral.kt b/packages/SystemUI/src/com/android/systemui/biometrics/FaceHelpMessageDeferral.kt new file mode 100644 index 000000000000..fabc1c1bb908 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/biometrics/FaceHelpMessageDeferral.kt @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.biometrics + +import android.content.res.Resources +import com.android.keyguard.logging.BiometricMessageDeferralLogger +import com.android.keyguard.logging.FaceMessageDeferralLogger +import com.android.systemui.Dumpable +import com.android.systemui.R +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.dagger.qualifiers.Main +import com.android.systemui.dump.DumpManager +import java.io.PrintWriter +import java.util.* +import javax.inject.Inject + +/** + * Provides whether a face acquired help message should be shown immediately when its received or + * should be shown when face auth times out. See [updateMessage] and [getDeferredMessage]. + */ +@SysUISingleton +class FaceHelpMessageDeferral +@Inject +constructor( + @Main resources: Resources, + logBuffer: FaceMessageDeferralLogger, + dumpManager: DumpManager +) : + BiometricMessageDeferral( + resources.getIntArray(R.array.config_face_help_msgs_defer_until_timeout).toHashSet(), + resources.getFloat(R.dimen.config_face_help_msgs_defer_until_timeout_threshold), + logBuffer, + dumpManager + ) + +/** + * @property messagesToDefer messages that shouldn't show immediately when received, but may be + * shown later if the message is the most frequent acquiredInfo processed and meets [threshold] + * percentage of all passed acquired frames. + */ +open class BiometricMessageDeferral( + private val messagesToDefer: Set<Int>, + private val threshold: Float, + private val logBuffer: BiometricMessageDeferralLogger, + dumpManager: DumpManager +) : Dumpable { + private val acquiredInfoToFrequency: MutableMap<Int, Int> = HashMap() + private val acquiredInfoToHelpString: MutableMap<Int, String> = HashMap() + private var mostFrequentAcquiredInfoToDefer: Int? = null + private var totalFrames = 0 + + init { + dumpManager.registerDumpable(this.javaClass.name, this) + } + + override fun dump(pw: PrintWriter, args: Array<out String>) { + pw.println("messagesToDefer=$messagesToDefer") + pw.println("totalFrames=$totalFrames") + pw.println("threshold=$threshold") + } + + /** Reset all saved counts. */ + fun reset() { + totalFrames = 0 + mostFrequentAcquiredInfoToDefer = null + acquiredInfoToFrequency.clear() + acquiredInfoToHelpString.clear() + logBuffer.reset() + } + + /** Updates the message associated with the acquiredInfo if it's a message we may defer. */ + fun updateMessage(acquiredInfo: Int, helpString: String) { + if (!messagesToDefer.contains(acquiredInfo)) { + return + } + if (!Objects.equals(acquiredInfoToHelpString[acquiredInfo], helpString)) { + logBuffer.logUpdateMessage(acquiredInfo, helpString) + acquiredInfoToHelpString[acquiredInfo] = helpString + } + } + + /** Whether the given message should be deferred instead of being shown immediately. */ + fun shouldDefer(acquiredMsgId: Int): Boolean { + return messagesToDefer.contains(acquiredMsgId) + } + + /** Adds the acquiredInfo frame to the counts. We account for all frames. */ + fun processFrame(acquiredInfo: Int) { + if (messagesToDefer.isEmpty()) { + return + } + + totalFrames++ + + val newAcquiredInfoCount = acquiredInfoToFrequency.getOrDefault(acquiredInfo, 0) + 1 + acquiredInfoToFrequency[acquiredInfo] = newAcquiredInfoCount + if ( + messagesToDefer.contains(acquiredInfo) && + (mostFrequentAcquiredInfoToDefer == null || + newAcquiredInfoCount > + acquiredInfoToFrequency.getOrDefault(mostFrequentAcquiredInfoToDefer!!, 0)) + ) { + mostFrequentAcquiredInfoToDefer = acquiredInfo + } + + logBuffer.logFrameProcessed( + acquiredInfo, + totalFrames, + mostFrequentAcquiredInfoToDefer?.toString() + ) + } + + /** + * Get the most frequent deferred message that meets the [threshold] percentage of processed + * frames. + * @return null if no acquiredInfo have been deferred OR deferred messages didn't meet the + * [threshold] percentage. + */ + fun getDeferredMessage(): CharSequence? { + mostFrequentAcquiredInfoToDefer?.let { + if (acquiredInfoToFrequency.getOrDefault(it, 0) > (threshold * totalFrames)) { + return acquiredInfoToHelpString[it] + } + } + return null + } +} diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollProgressBarDrawable.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollProgressBarDrawable.java index d96476fbf087..49e378e4a76f 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollProgressBarDrawable.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollProgressBarDrawable.java @@ -99,11 +99,12 @@ public class UdfpsEnrollProgressBarDrawable extends Drawable { mProgressColor = context.getColor(R.color.udfps_enroll_progress); final AccessibilityManager am = context.getSystemService(AccessibilityManager.class); mIsAccessibilityEnabled = am.isTouchExplorationEnabled(); - mOnFirstBucketFailedColor = context.getColor(R.color.udfps_moving_target_fill_error); if (!mIsAccessibilityEnabled) { mHelpColor = context.getColor(R.color.udfps_enroll_progress_help); + mOnFirstBucketFailedColor = context.getColor(R.color.udfps_moving_target_fill_error); } else { mHelpColor = context.getColor(R.color.udfps_enroll_progress_help_with_talkback); + mOnFirstBucketFailedColor = mHelpColor; } mCheckmarkDrawable = context.getDrawable(R.drawable.udfps_enroll_checkmark); mCheckmarkDrawable.mutate(); @@ -166,8 +167,7 @@ public class UdfpsEnrollProgressBarDrawable extends Drawable { } private void updateProgress(int remainingSteps, int totalSteps, boolean showingHelp) { - if (mRemainingSteps == remainingSteps && mTotalSteps == totalSteps - && mShowingHelp == showingHelp) { + if (mRemainingSteps == remainingSteps && mTotalSteps == totalSteps) { return; } @@ -197,7 +197,6 @@ public class UdfpsEnrollProgressBarDrawable extends Drawable { } } - mShowingHelp = showingHelp; mRemainingSteps = remainingSteps; mTotalSteps = totalSteps; diff --git a/packages/SystemUI/src/com/android/systemui/bluetooth/BluetoothLogger.kt b/packages/SystemUI/src/com/android/systemui/bluetooth/BluetoothLogger.kt new file mode 100644 index 000000000000..96af42bfda22 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/bluetooth/BluetoothLogger.kt @@ -0,0 +1,102 @@ +/* + * 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.bluetooth + +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.log.LogBuffer +import com.android.systemui.log.LogLevel +import com.android.systemui.log.dagger.BluetoothLog +import javax.inject.Inject + +/** Helper class for logging bluetooth events. */ +@SysUISingleton +class BluetoothLogger @Inject constructor(@BluetoothLog private val logBuffer: LogBuffer) { + fun logActiveDeviceChanged(address: String?, profileId: Int) = + logBuffer.log( + TAG, + LogLevel.DEBUG, + { + str1 = address + int1 = profileId + }, + { "ActiveDeviceChanged. address=$str1 profileId=$int1" } + ) + + fun logDeviceConnectionStateChanged(address: String?, state: String) = + logBuffer.log( + TAG, + LogLevel.DEBUG, + { + str1 = address + str2 = state + }, + { "DeviceConnectionStateChanged. address=$str1 state=$str2" } + ) + + fun logAclConnectionStateChanged(address: String, state: String) = + logBuffer.log( + TAG, + LogLevel.DEBUG, + { + str1 = address + str2 = state + }, + { "AclConnectionStateChanged. address=$str1 state=$str2" } + ) + + fun logProfileConnectionStateChanged(address: String?, state: String, profileId: Int) = + logBuffer.log( + TAG, + LogLevel.DEBUG, + { + str1 = address + str2 = state + int1 = profileId + }, + { "ProfileConnectionStateChanged. address=$str1 state=$str2 profileId=$int1" } + ) + + fun logStateChange(state: String) = + logBuffer.log( + TAG, + LogLevel.DEBUG, + { str1 = state }, + { "BluetoothStateChanged. state=$str1" } + ) + + fun logBondStateChange(address: String, state: Int) = + logBuffer.log( + TAG, + LogLevel.DEBUG, + { + str1 = address + int1 = state + }, + { "DeviceBondStateChanged. address=$str1 state=$int1" } + ) + + fun logDeviceAdded(address: String) = + logBuffer.log(TAG, LogLevel.DEBUG, { str1 = address }, { "DeviceAdded. address=$str1" }) + + fun logDeviceDeleted(address: String) = + logBuffer.log(TAG, LogLevel.DEBUG, { str1 = address }, { "DeviceDeleted. address=$str1" }) + + fun logDeviceAttributesChanged() = + logBuffer.log(TAG, LogLevel.DEBUG, {}, { "DeviceAttributesChanged." }) +} + +private const val TAG = "BluetoothLog" diff --git a/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java index 31a2134851a2..bfbf37a5d3e9 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java @@ -291,7 +291,7 @@ public class BrightLineFalsingManager implements FalsingManager { FalsingClassifier.Result.falsed( 0, getClass().getSimpleName(), "bad history")); logDebug("False Single Tap: true (bad history)"); - mFalsingTapListeners.forEach(FalsingTapListener::onDoubleTapRequired); + mFalsingTapListeners.forEach(FalsingTapListener::onAdditionalTapRequired); return true; } else { mPriorResults = getPassedResult(0.1); @@ -321,7 +321,7 @@ public class BrightLineFalsingManager implements FalsingManager { mHistoryTracker.falseBelief(), mHistoryTracker.falseConfidence()); mPriorResults = Collections.singleton(result); - logDebug("False Double Tap: " + result.isFalse()); + logDebug("False Double Tap: " + result.isFalse() + " reason=" + result.getReason()); return result.isFalse(); } diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java index 23d87ff980ca..f5f9655ef24b 100644 --- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java +++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingCollectorImpl.java @@ -303,9 +303,7 @@ class FalsingCollectorImpl implements FalsingCollector { @Override public void onTouchEvent(MotionEvent ev) { - if (!mKeyguardStateController.isShowing() - || (mStatusBarStateController.isDozing() - && !mStatusBarStateController.isPulsing())) { + if (!mKeyguardStateController.isShowing()) { avoidGesture(); return; } diff --git a/packages/SystemUI/src/com/android/systemui/common/shared/model/Icon.kt b/packages/SystemUI/src/com/android/systemui/common/shared/model/Icon.kt index 0b65966ca109..6c45af2a8729 100644 --- a/packages/SystemUI/src/com/android/systemui/common/shared/model/Icon.kt +++ b/packages/SystemUI/src/com/android/systemui/common/shared/model/Icon.kt @@ -24,11 +24,15 @@ import android.graphics.drawable.Drawable * [Icon.Resource] to a resource. */ sealed class Icon { + abstract val contentDescription: ContentDescription? + data class Loaded( val drawable: Drawable, + override val contentDescription: ContentDescription?, ) : Icon() data class Resource( @DrawableRes val res: Int, + override val contentDescription: ContentDescription?, ) : Icon() } diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/LatencyTrackerCompat.java b/packages/SystemUI/src/com/android/systemui/common/shared/model/Text.kt index e6ae19eebc72..5d0e08ffc307 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/LatencyTrackerCompat.java +++ b/packages/SystemUI/src/com/android/systemui/common/shared/model/Text.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018 The Android Open Source Project + * 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. @@ -11,23 +11,24 @@ * 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 + * limitations under the License. + * */ -package com.android.systemui.shared.system; - -import android.content.Context; +package com.android.systemui.common.shared.model -import com.android.internal.util.LatencyTracker; +import android.annotation.StringRes /** - * @see LatencyTracker + * Models a text, that can either be already [loaded][Text.Loaded] or be a [reference] + * [Text.Resource] to a resource. */ -public class LatencyTrackerCompat { +sealed class Text { + data class Loaded( + val text: String?, + ) : Text() - /** @see LatencyTracker */ - public static void logToggleRecents(Context context, int duration) { - LatencyTracker.getInstance(context).logAction(LatencyTracker.ACTION_TOGGLE_RECENTS, - duration); - } -}
\ No newline at end of file + data class Resource( + @StringRes val res: Int, + ) : Text() +} diff --git a/packages/SystemUI/src/com/android/systemui/common/ui/binder/ContentDescriptionViewBinder.kt b/packages/SystemUI/src/com/android/systemui/common/ui/binder/ContentDescriptionViewBinder.kt index d6433aae9845..93ae637c7182 100644 --- a/packages/SystemUI/src/com/android/systemui/common/ui/binder/ContentDescriptionViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/common/ui/binder/ContentDescriptionViewBinder.kt @@ -21,14 +21,16 @@ import com.android.systemui.common.shared.model.ContentDescription object ContentDescriptionViewBinder { fun bind( - contentDescription: ContentDescription, + contentDescription: ContentDescription?, view: View, ) { - when (contentDescription) { - is ContentDescription.Loaded -> view.contentDescription = contentDescription.description - is ContentDescription.Resource -> { - view.contentDescription = view.context.resources.getString(contentDescription.res) + view.contentDescription = + when (contentDescription) { + null -> null + is ContentDescription.Loaded -> contentDescription.description + is ContentDescription.Resource -> { + view.context.resources.getString(contentDescription.res) + } } - } } } diff --git a/packages/SystemUI/src/com/android/systemui/common/ui/binder/IconViewBinder.kt b/packages/SystemUI/src/com/android/systemui/common/ui/binder/IconViewBinder.kt index aecee2afc9d2..108e22bc392b 100644 --- a/packages/SystemUI/src/com/android/systemui/common/ui/binder/IconViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/common/ui/binder/IconViewBinder.kt @@ -24,6 +24,7 @@ object IconViewBinder { icon: Icon, view: ImageView, ) { + ContentDescriptionViewBinder.bind(icon.contentDescription, view) when (icon) { is Icon.Loaded -> view.setImageDrawable(icon.drawable) is Icon.Resource -> view.setImageResource(icon.res) diff --git a/packages/SystemUI/src/com/android/systemui/common/ui/binder/TextViewBinder.kt b/packages/SystemUI/src/com/android/systemui/common/ui/binder/TextViewBinder.kt new file mode 100644 index 000000000000..396e8bb5a60d --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/common/ui/binder/TextViewBinder.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.common.ui.binder + +import android.widget.TextView +import com.android.systemui.common.shared.model.Text + +object TextViewBinder { + fun bind(view: TextView, viewModel: Text) { + view.text = + when (viewModel) { + is Text.Resource -> view.context.getString(viewModel.res) + is Text.Loaded -> viewModel.text + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/common/ui/drawable/CircularDrawable.kt b/packages/SystemUI/src/com/android/systemui/common/ui/drawable/CircularDrawable.kt new file mode 100644 index 000000000000..ec71c3824156 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/common/ui/drawable/CircularDrawable.kt @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package com.android.systemui.common.ui.drawable + +import android.graphics.Canvas +import android.graphics.Path +import android.graphics.Rect +import android.graphics.drawable.Drawable +import android.graphics.drawable.DrawableWrapper +import kotlin.math.min + +/** Renders the wrapped [Drawable] as a circle. */ +class CircularDrawable( + drawable: Drawable, +) : DrawableWrapper(drawable) { + private val path: Path by lazy { Path() } + + override fun onBoundsChange(bounds: Rect) { + super.onBoundsChange(bounds) + updateClipPath() + } + + override fun draw(canvas: Canvas) { + canvas.save() + canvas.clipPath(path) + drawable?.draw(canvas) + canvas.restore() + } + + private fun updateClipPath() { + path.reset() + path.addCircle( + bounds.centerX().toFloat(), + bounds.centerY().toFloat(), + min(bounds.width(), bounds.height()) / 2f, + Path.Direction.CW + ) + } +} diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiController.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiController.kt index 91e75f6436c2..822f8f2e6191 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiController.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiController.kt @@ -33,6 +33,12 @@ interface ControlsUiController { fun hide() /** + * Returns the preferred activity to start, depending on if the user has favorited any + * controls. + */ + fun resolveActivity(): Class<*> + + /** * Request all open dialogs be closed. Set [immediately] to true to dismiss without * animations. */ diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt index c1e99f578459..bf7d71635694 100644 --- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt @@ -149,6 +149,19 @@ class ControlsUiControllerImpl @Inject constructor ( } } + override fun resolveActivity(): Class<*> { + val allStructures = controlsController.get().getFavorites() + val selectedStructure = getPreferredStructure(allStructures) + + return if (controlsController.get().addSeedingFavoritesCallback(onSeedingComplete)) { + ControlsActivity::class.java + } else if (selectedStructure.controls.isEmpty() && allStructures.size <= 1) { + ControlsProviderSelectorActivity::class.java + } else { + ControlsActivity::class.java + } + } + override fun show( parent: ViewGroup, onDismiss: Runnable, diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DefaultServiceBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/DefaultServiceBinder.java index e1cbdcdd86c1..92eeace648ad 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/DefaultServiceBinder.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/DefaultServiceBinder.java @@ -18,7 +18,6 @@ package com.android.systemui.dagger; import android.app.Service; -import com.android.systemui.ImageWallpaper; import com.android.systemui.SystemUIService; import com.android.systemui.doze.DozeService; import com.android.systemui.dreams.DreamOverlayService; @@ -26,6 +25,7 @@ import com.android.systemui.dump.SystemUIAuxiliaryDumpService; import com.android.systemui.keyguard.KeyguardService; import com.android.systemui.screenrecord.RecordingService; import com.android.systemui.statusbar.phone.NotificationListenerWithPlugins; +import com.android.systemui.wallpapers.ImageWallpaper; import dagger.Binds; import dagger.Module; diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SharedLibraryModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SharedLibraryModule.java index be156157fb72..6b9d41c41a85 100644 --- a/packages/SystemUI/src/com/android/systemui/dagger/SharedLibraryModule.java +++ b/packages/SystemUI/src/com/android/systemui/dagger/SharedLibraryModule.java @@ -19,7 +19,6 @@ package com.android.systemui.dagger; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.DevicePolicyManagerWrapper; import com.android.systemui.shared.system.TaskStackChangeListeners; -import com.android.systemui.shared.system.WindowManagerWrapper; import dagger.Module; import dagger.Provides; @@ -49,10 +48,4 @@ public class SharedLibraryModule { return TaskStackChangeListeners.getInstance(); } - /** */ - @Provides - public WindowManagerWrapper providesWindowManagerWrapper() { - return WindowManagerWrapper.getInstance(); - } - } diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java b/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java index d89c0be26351..b59855426a3c 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java @@ -101,6 +101,11 @@ public interface DozeHost { * Called when the always on suppression state changes. See {@link #isAlwaysOnSuppressed()}. */ default void onAlwaysOnSuppressedChanged(boolean suppressed) {} + + /** + * Called when the dozing state may have been updated. + */ + default void onDozingChanged(boolean isDozing) {} } interface PulseCallback { diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarView.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarView.java index 823255c38a84..f244cb009ba4 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarView.java +++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarView.java @@ -61,6 +61,7 @@ public class DreamOverlayStatusBarView extends ConstraintLayout { private final Map<Integer, View> mStatusIcons = new HashMap<>(); private ViewGroup mSystemStatusViewGroup; + private ViewGroup mExtraSystemStatusViewGroup; public DreamOverlayStatusBarView(Context context) { this(context, null); @@ -98,7 +99,8 @@ public class DreamOverlayStatusBarView extends ConstraintLayout { mStatusIcons.put(STATUS_ICON_PRIORITY_MODE_ON, fetchStatusIconForResId(R.id.dream_overlay_priority_mode)); - mSystemStatusViewGroup = findViewById(R.id.dream_overlay_extra_items); + mSystemStatusViewGroup = findViewById(R.id.dream_overlay_system_status); + mExtraSystemStatusViewGroup = findViewById(R.id.dream_overlay_extra_items); } void showIcon(@StatusIconType int iconType, boolean show, @Nullable String contentDescription) { @@ -110,11 +112,12 @@ public class DreamOverlayStatusBarView extends ConstraintLayout { icon.setContentDescription(contentDescription); } icon.setVisibility(show ? View.VISIBLE : View.GONE); + mSystemStatusViewGroup.setVisibility(areAnyStatusIconsVisible() ? View.VISIBLE : View.GONE); } void setExtraStatusBarItemViews(List<View> views) { - removeAllStatusBarItemViews(); - views.forEach(view -> mSystemStatusViewGroup.addView(view)); + removeAllExtraStatusBarItemViews(); + views.forEach(view -> mExtraSystemStatusViewGroup.addView(view)); } private View fetchStatusIconForResId(int resId) { @@ -122,7 +125,16 @@ public class DreamOverlayStatusBarView extends ConstraintLayout { return Objects.requireNonNull(statusIcon); } - void removeAllStatusBarItemViews() { - mSystemStatusViewGroup.removeAllViews(); + void removeAllExtraStatusBarItemViews() { + mExtraSystemStatusViewGroup.removeAllViews(); + } + + private boolean areAnyStatusIconsVisible() { + for (int i = 0; i < mSystemStatusViewGroup.getChildCount(); i++) { + if (mSystemStatusViewGroup.getChildAt(i).getVisibility() == View.VISIBLE) { + return true; + } + } + return false; } } diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java index 6f505504b186..aa59cc666caa 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java +++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStatusBarViewController.java @@ -192,7 +192,7 @@ public class DreamOverlayStatusBarViewController extends ViewController<DreamOve mDreamOverlayNotificationCountProvider.ifPresent( provider -> provider.removeCallback(mNotificationCountCallback)); mStatusBarItemsProvider.removeCallback(mStatusBarItemsProviderCallback); - mView.removeAllStatusBarItemViews(); + mView.removeAllExtraStatusBarItemViews(); mTouchInsetSession.clear(); mIsAttached = false; diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/DoubleShadowTextClock.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/DoubleShadowTextClock.java index 653f4dc66200..789ebc517271 100644 --- a/packages/SystemUI/src/com/android/systemui/dreams/complication/DoubleShadowTextClock.java +++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/DoubleShadowTextClock.java @@ -17,24 +17,21 @@ package com.android.systemui.dreams.complication; import android.content.Context; +import android.content.res.Resources; import android.graphics.Canvas; import android.util.AttributeSet; import android.widget.TextClock; import com.android.systemui.R; +import com.android.systemui.dreams.complication.DoubleShadowTextHelper.ShadowInfo; + +import kotlin.Unit; /** * Extension of {@link TextClock} which draws two shadows on the text (ambient and key shadows) */ public class DoubleShadowTextClock extends TextClock { - private final float mAmbientShadowBlur; - private final int mAmbientShadowColor; - private final float mKeyShadowBlur; - private final float mKeyShadowOffsetX; - private final float mKeyShadowOffsetY; - private final int mKeyShadowColor; - private final float mAmbientShadowOffsetX; - private final float mAmbientShadowOffsetY; + private final DoubleShadowTextHelper mShadowHelper; public DoubleShadowTextClock(Context context) { this(context, null); @@ -46,38 +43,28 @@ public class DoubleShadowTextClock extends TextClock { public DoubleShadowTextClock(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); - mKeyShadowBlur = context.getResources() - .getDimensionPixelSize(R.dimen.dream_overlay_clock_key_text_shadow_radius); - mKeyShadowOffsetX = context.getResources() - .getDimensionPixelSize(R.dimen.dream_overlay_clock_key_text_shadow_dx); - mKeyShadowOffsetY = context.getResources() - .getDimensionPixelSize(R.dimen.dream_overlay_clock_key_text_shadow_dy); - mKeyShadowColor = context.getResources().getColor( - R.color.dream_overlay_clock_key_text_shadow_color); - mAmbientShadowBlur = context.getResources() - .getDimensionPixelSize(R.dimen.dream_overlay_clock_ambient_text_shadow_radius); - mAmbientShadowColor = context.getResources().getColor( - R.color.dream_overlay_clock_ambient_text_shadow_color); - mAmbientShadowOffsetX = context.getResources() - .getDimensionPixelSize(R.dimen.dream_overlay_clock_ambient_text_shadow_dx); - mAmbientShadowOffsetY = context.getResources() - .getDimensionPixelSize(R.dimen.dream_overlay_clock_ambient_text_shadow_dy); + + final Resources resources = context.getResources(); + final ShadowInfo keyShadowInfo = new ShadowInfo( + resources.getDimensionPixelSize(R.dimen.dream_overlay_clock_key_text_shadow_radius), + resources.getDimensionPixelSize(R.dimen.dream_overlay_clock_key_text_shadow_dx), + resources.getDimensionPixelSize(R.dimen.dream_overlay_clock_key_text_shadow_dy), + resources.getColor(R.color.dream_overlay_clock_key_text_shadow_color)); + + final ShadowInfo ambientShadowInfo = new ShadowInfo( + resources.getDimensionPixelSize( + R.dimen.dream_overlay_clock_ambient_text_shadow_radius), + resources.getDimensionPixelSize(R.dimen.dream_overlay_clock_ambient_text_shadow_dx), + resources.getDimensionPixelSize(R.dimen.dream_overlay_clock_ambient_text_shadow_dy), + resources.getColor(R.color.dream_overlay_clock_ambient_text_shadow_color)); + mShadowHelper = new DoubleShadowTextHelper(keyShadowInfo, ambientShadowInfo); } @Override public void onDraw(Canvas canvas) { - // We enhance the shadow by drawing the shadow twice - getPaint().setShadowLayer(mAmbientShadowBlur, mAmbientShadowOffsetX, mAmbientShadowOffsetY, - mAmbientShadowColor); - super.onDraw(canvas); - canvas.save(); - canvas.clipRect(getScrollX(), getScrollY() + getExtendedPaddingTop(), - getScrollX() + getWidth(), - getScrollY() + getHeight()); - - getPaint().setShadowLayer( - mKeyShadowBlur, mKeyShadowOffsetX, mKeyShadowOffsetY, mKeyShadowColor); - super.onDraw(canvas); - canvas.restore(); + mShadowHelper.applyShadows(this, canvas, () -> { + super.onDraw(canvas); + return Unit.INSTANCE; + }); } } diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/DoubleShadowTextHelper.kt b/packages/SystemUI/src/com/android/systemui/dreams/complication/DoubleShadowTextHelper.kt new file mode 100644 index 000000000000..b1dc5a2e5dea --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/DoubleShadowTextHelper.kt @@ -0,0 +1,61 @@ +/* + * 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.dreams.complication + +import android.graphics.Canvas +import android.widget.TextView +import androidx.annotation.ColorInt + +class DoubleShadowTextHelper +constructor( + private val keyShadowInfo: ShadowInfo, + private val ambientShadowInfo: ShadowInfo, +) { + data class ShadowInfo( + val blur: Float, + val offsetX: Float = 0f, + val offsetY: Float = 0f, + @ColorInt val color: Int + ) + + fun applyShadows(view: TextView, canvas: Canvas, onDrawCallback: () -> Unit) { + // We enhance the shadow by drawing the shadow twice + view.paint.setShadowLayer( + ambientShadowInfo.blur, + ambientShadowInfo.offsetX, + ambientShadowInfo.offsetY, + ambientShadowInfo.color + ) + onDrawCallback() + canvas.save() + canvas.clipRect( + view.scrollX, + view.scrollY + view.extendedPaddingTop, + view.scrollX + view.width, + view.scrollY + view.height + ) + + view.paint.setShadowLayer( + keyShadowInfo.blur, + keyShadowInfo.offsetX, + keyShadowInfo.offsetY, + keyShadowInfo.color + ) + onDrawCallback() + canvas.restore() + } +} diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/DoubleShadowTextView.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/DoubleShadowTextView.java new file mode 100644 index 000000000000..cf7e3127dedf --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/DoubleShadowTextView.java @@ -0,0 +1,76 @@ +/* + * 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.dreams.complication; + +import android.content.Context; +import android.content.res.Resources; +import android.graphics.Canvas; +import android.util.AttributeSet; +import android.widget.TextView; + +import com.android.systemui.R; + +import kotlin.Unit; + +/** + * Extension of {@link TextView} which draws two shadows on the text (ambient and key shadows} + */ +public class DoubleShadowTextView extends TextView { + private final DoubleShadowTextHelper mShadowHelper; + + public DoubleShadowTextView(Context context) { + this(context, null); + } + + public DoubleShadowTextView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public DoubleShadowTextView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + + final Resources resources = context.getResources(); + final DoubleShadowTextHelper.ShadowInfo + keyShadowInfo = new DoubleShadowTextHelper.ShadowInfo( + resources.getDimensionPixelSize( + R.dimen.dream_overlay_status_bar_key_text_shadow_radius), + resources.getDimensionPixelSize( + R.dimen.dream_overlay_status_bar_key_text_shadow_dx), + resources.getDimensionPixelSize( + R.dimen.dream_overlay_status_bar_key_text_shadow_dy), + resources.getColor(R.color.dream_overlay_status_bar_key_text_shadow_color)); + + final DoubleShadowTextHelper.ShadowInfo + ambientShadowInfo = new DoubleShadowTextHelper.ShadowInfo( + resources.getDimensionPixelSize( + R.dimen.dream_overlay_status_bar_ambient_text_shadow_radius), + resources.getDimensionPixelSize( + R.dimen.dream_overlay_status_bar_ambient_text_shadow_dx), + resources.getDimensionPixelSize( + R.dimen.dream_overlay_status_bar_ambient_text_shadow_dy), + resources.getColor(R.color.dream_overlay_status_bar_ambient_text_shadow_color)); + mShadowHelper = new DoubleShadowTextHelper(keyShadowInfo, ambientShadowInfo); + } + + @Override + public void onDraw(Canvas canvas) { + mShadowHelper.applyShadows(this, canvas, () -> { + super.onDraw(canvas); + return Unit.INSTANCE; + }); + } +} diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.java b/packages/SystemUI/src/com/android/systemui/flags/Flags.java index 14823030b72e..cd6c57aea76b 100644 --- a/packages/SystemUI/src/com/android/systemui/flags/Flags.java +++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.java @@ -66,6 +66,10 @@ public class Flags { public static final UnreleasedFlag FSI_REQUIRES_KEYGUARD = new UnreleasedFlag(110, true); + public static final UnreleasedFlag INSTANT_VOICE_REPLY = new UnreleasedFlag(111, true); + + // next id: 112 + /***************************************/ // 200 - keyguard/lockscreen @@ -88,20 +92,13 @@ public class Flags { public static final ResourceBooleanFlag FACE_SCANNING_ANIM = new ResourceBooleanFlag(205, R.bool.config_enableFaceScanningAnimation); - /** - * Whether the KeyguardBottomArea(View|Controller) should use the modern architecture or the old - * one. - */ - public static final ReleasedFlag MODERN_BOTTOM_AREA = new ReleasedFlag(206, true); - - public static final UnreleasedFlag LOCKSCREEN_CUSTOM_CLOCKS = new UnreleasedFlag(207); /** * Flag to enable the usage of the new bouncer data source. This is a refactor of and * eventual replacement of KeyguardBouncer.java. */ - public static final ReleasedFlag MODERN_BOUNCER = new ReleasedFlag(208); + public static final UnreleasedFlag MODERN_BOUNCER = new UnreleasedFlag(208); /** Whether UserSwitcherActivity should use modern architecture. */ public static final UnreleasedFlag MODERN_USER_SWITCHER_ACTIVITY = @@ -187,6 +184,12 @@ public class Flags { // 801 - region sampling public static final UnreleasedFlag REGION_SAMPLING = new UnreleasedFlag(801); + // 802 - wallpaper rendering + public static final UnreleasedFlag USE_CANVAS_RENDERER = new UnreleasedFlag(802); + + // 803 - screen contents translation + public static final UnreleasedFlag SCREEN_CONTENTS_TRANSLATION = new UnreleasedFlag(803); + /***************************************/ // 900 - media public static final ReleasedFlag MEDIA_TAP_TO_TRANSFER = new ReleasedFlag(900); diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java b/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java index a3dc77993d30..568143c8df71 100644 --- a/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java +++ b/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardUI.java @@ -42,6 +42,8 @@ import android.util.Pair; import android.util.Slog; import android.widget.Toast; +import androidx.annotation.NonNull; + import com.android.settingslib.bluetooth.BluetoothCallback; import com.android.settingslib.bluetooth.BluetoothUtils; import com.android.settingslib.bluetooth.CachedBluetoothDevice; @@ -601,13 +603,14 @@ public class KeyboardUI extends CoreStartable implements InputManager.OnTabletMo private final class BluetoothCallbackHandler implements BluetoothCallback { @Override - public void onBluetoothStateChanged(int bluetoothState) { + public void onBluetoothStateChanged(@BluetoothCallback.AdapterState int bluetoothState) { mHandler.obtainMessage(MSG_ON_BLUETOOTH_STATE_CHANGED, bluetoothState, 0).sendToTarget(); } @Override - public void onDeviceBondStateChanged(CachedBluetoothDevice cachedDevice, int bondState) { + public void onDeviceBondStateChanged( + @NonNull CachedBluetoothDevice cachedDevice, int bondState) { mHandler.obtainMessage(MSG_ON_DEVICE_BOND_STATE_CHANGED, bondState, 0, cachedDevice).sendToTarget(); } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java index 6dfbd426ef30..ddcd0533c588 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java @@ -29,6 +29,7 @@ import static android.view.WindowManager.TRANSIT_KEYGUARD_UNOCCLUDE; import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_GOING_AWAY; import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER; import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_OCCLUDE; +import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_OCCLUDE_BY_DREAM; import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_UNOCCLUDE; import static android.view.WindowManager.TRANSIT_OLD_NONE; import static android.view.WindowManager.TRANSIT_OPEN; @@ -189,6 +190,9 @@ public class KeyguardService extends Service { return apps.length == 0 ? TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER : TRANSIT_OLD_KEYGUARD_GOING_AWAY; } else if (type == TRANSIT_KEYGUARD_OCCLUDE) { + boolean isOccludeByDream = apps.length > 0 && apps[0].taskInfo.topActivityType + == WindowConfiguration.ACTIVITY_TYPE_DREAM; + if (isOccludeByDream) return TRANSIT_OLD_KEYGUARD_OCCLUDE_BY_DREAM; return TRANSIT_OLD_KEYGUARD_OCCLUDE; } else if (type == TRANSIT_KEYGUARD_UNOCCLUDE) { return TRANSIT_OLD_KEYGUARD_UNOCCLUDE; @@ -198,7 +202,8 @@ public class KeyguardService extends Service { } } - // Wrap Keyguard going away animation + // Wrap Keyguard going away animation. + // Note: Also used for wrapping occlude by Dream animation. It works (with some redundancy). private static IRemoteTransition wrap(IRemoteAnimationRunner runner) { return new IRemoteTransition.Stub() { final ArrayMap<IBinder, IRemoteTransitionFinishedCallback> mFinishCallbacks = @@ -303,6 +308,12 @@ public class KeyguardService extends Service { definition.addRemoteAnimation(TRANSIT_OLD_KEYGUARD_OCCLUDE, occludeAnimationAdapter); + final RemoteAnimationAdapter occludeByDreamAnimationAdapter = + new RemoteAnimationAdapter( + mKeyguardViewMediator.getOccludeByDreamAnimationRunner(), 0, 0); + definition.addRemoteAnimation(TRANSIT_OLD_KEYGUARD_OCCLUDE_BY_DREAM, + occludeByDreamAnimationAdapter); + final RemoteAnimationAdapter unoccludeAnimationAdapter = new RemoteAnimationAdapter( mKeyguardViewMediator.getUnoccludeAnimationRunner(), 0, 0); @@ -378,6 +389,27 @@ public class KeyguardService extends Service { f = new TransitionFilter(); f.mTypeSet = new int[]{TRANSIT_KEYGUARD_UNOCCLUDE}; mShellTransitions.registerRemote(f, unoccludeTransition); + + Slog.d(TAG, "KeyguardService registerRemote: TRANSIT_KEYGUARD_OCCLUDE for DREAM"); + // Register for occluding by Dream + f = new TransitionFilter(); + f.mFlags = TRANSIT_FLAG_KEYGUARD_LOCKED; + f.mRequirements = new TransitionFilter.Requirement[]{ + new TransitionFilter.Requirement(), new TransitionFilter.Requirement()}; + // First require at-least one app of type DREAM showing that occludes. + f.mRequirements[0].mActivityType = WindowConfiguration.ACTIVITY_TYPE_DREAM; + f.mRequirements[0].mMustBeIndependent = false; + f.mRequirements[0].mFlags = FLAG_OCCLUDES_KEYGUARD; + f.mRequirements[0].mModes = new int[]{TRANSIT_OPEN, TRANSIT_TO_FRONT}; + // Then require that we aren't closing any occludes (because this would mean a + // regular task->task or activity->activity animation not involving keyguard). + f.mRequirements[1].mNot = true; + f.mRequirements[1].mMustBeIndependent = false; + f.mRequirements[1].mFlags = FLAG_OCCLUDES_KEYGUARD; + f.mRequirements[1].mModes = new int[]{TRANSIT_CLOSE, TRANSIT_TO_BACK}; + mShellTransitions.registerRemote(f, new RemoteTransition( + wrap(mKeyguardViewMediator.getOccludeByDreamAnimationRunner()), + getIApplicationThread())); } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt index c944e509c5f1..6f38f4f53b7c 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt @@ -241,9 +241,8 @@ class KeyguardUnlockAnimationController @Inject constructor( */ @VisibleForTesting var surfaceTransactionApplier: SyncRtSurfaceTransactionApplier? = null - private var surfaceBehindRemoteAnimationTarget: RemoteAnimationTarget? = null + private var surfaceBehindRemoteAnimationTargets: Array<RemoteAnimationTarget>? = null private var surfaceBehindRemoteAnimationStartTime: Long = 0 - private var surfaceBehindParams: SyncRtSurfaceTransactionApplier.SurfaceParams? = null /** * Alpha value applied to [surfaceBehindRemoteAnimationTarget], which is the surface of the @@ -282,7 +281,8 @@ class KeyguardUnlockAnimationController @Inject constructor( * window like any other app. This can be true while [willUnlockWithSmartspaceTransition] is * false, if the smartspace is not available or was not ready in time. */ - private var willUnlockWithInWindowLauncherAnimations: Boolean = false + @VisibleForTesting + var willUnlockWithInWindowLauncherAnimations: Boolean = false /** * Whether we decided in [prepareForInWindowLauncherAnimations] that we are able to and want to @@ -457,7 +457,7 @@ class KeyguardUnlockAnimationController @Inject constructor( * (fingerprint, tap, etc.) and the keyguard is going away. */ fun notifyStartSurfaceBehindRemoteAnimation( - target: RemoteAnimationTarget, + targets: Array<RemoteAnimationTarget>, startTime: Long, requestedShowSurfaceBehindKeyguard: Boolean ) { @@ -466,10 +466,7 @@ class KeyguardUnlockAnimationController @Inject constructor( keyguardViewController.viewRootImpl.view) } - // New animation, new params. - surfaceBehindParams = null - - surfaceBehindRemoteAnimationTarget = target + surfaceBehindRemoteAnimationTargets = targets surfaceBehindRemoteAnimationStartTime = startTime // If we specifically requested that the surface behind be made visible (vs. it being made @@ -484,8 +481,8 @@ class KeyguardUnlockAnimationController @Inject constructor( // surface behind the keyguard to finish unlocking. if (keyguardStateController.isFlingingToDismissKeyguard) { playCannedUnlockAnimation() - } else if (keyguardStateController.isDismissingFromSwipe - && willUnlockWithInWindowLauncherAnimations) { + } else if (keyguardStateController.isDismissingFromSwipe && + willUnlockWithInWindowLauncherAnimations) { // If we're swiping to unlock to the Launcher, and can play in-window animations, // make the launcher surface fully visible and play the in-window unlock animation // on the launcher icons. System UI will remain locked, using the swipe-to-unlock @@ -574,7 +571,7 @@ class KeyguardUnlockAnimationController @Inject constructor( // Now that the Launcher surface (with its smartspace positioned identically to ours) is // visible, hide our smartspace. - lockscreenSmartspace!!.visibility = View.INVISIBLE + lockscreenSmartspace?.visibility = View.INVISIBLE // As soon as the shade has animated out of the way, finish the keyguard exit animation. The // in-window animations in the Launcher window will end on their own. @@ -596,7 +593,7 @@ class KeyguardUnlockAnimationController @Inject constructor( * keyguard dismiss amount and the method of dismissal. */ private fun updateSurfaceBehindAppearAmount() { - if (surfaceBehindRemoteAnimationTarget == null) { + if (surfaceBehindRemoteAnimationTargets == null) { return } @@ -714,63 +711,60 @@ class KeyguardUnlockAnimationController @Inject constructor( * cancelled). */ fun setSurfaceBehindAppearAmount(amount: Float) { - if (surfaceBehindRemoteAnimationTarget == null) { - return - } - - // Otherwise, animate in the surface's scale/transltion. - val surfaceHeight: Int = surfaceBehindRemoteAnimationTarget!!.screenSpaceBounds.height() - - var scaleFactor = (SURFACE_BEHIND_START_SCALE_FACTOR + - (1f - SURFACE_BEHIND_START_SCALE_FACTOR) * - MathUtils.clamp(amount, 0f, 1f)) - - // If we're dismissing via swipe to the Launcher, we'll play in-window scale animations, so - // don't also scale the window. - if (keyguardStateController.isDismissingFromSwipe - && willUnlockWithInWindowLauncherAnimations) { - scaleFactor = 1f - } - - // Scale up from a point at the center-bottom of the surface. - surfaceBehindMatrix.setScale( - scaleFactor, - scaleFactor, - surfaceBehindRemoteAnimationTarget!!.screenSpaceBounds.width() / 2f, - surfaceHeight * SURFACE_BEHIND_SCALE_PIVOT_Y - ) - - // Translate up from the bottom. - surfaceBehindMatrix.postTranslate( - 0f, - surfaceHeight * SURFACE_BEHIND_START_TRANSLATION_Y * (1f - amount) - ) - - // If we're snapping the keyguard back, immediately begin fading it out. - val animationAlpha = - if (keyguardStateController.isSnappingKeyguardBackAfterSwipe) amount - else surfaceBehindAlpha - - // SyncRtSurfaceTransactionApplier cannot apply transaction when the target view is unable - // to draw - val sc: SurfaceControl? = surfaceBehindRemoteAnimationTarget?.leash - if (keyguardViewController.viewRootImpl.view?.visibility != View.VISIBLE && - sc?.isValid == true) { - with(SurfaceControl.Transaction()) { - setMatrix(sc, surfaceBehindMatrix, tmpFloat) - setCornerRadius(sc, roundedCornerRadius) - setAlpha(sc, animationAlpha) - apply() + surfaceBehindRemoteAnimationTargets?.forEach { surfaceBehindRemoteAnimationTarget -> + val surfaceHeight: Int = surfaceBehindRemoteAnimationTarget.screenSpaceBounds.height() + + var scaleFactor = (SURFACE_BEHIND_START_SCALE_FACTOR + + (1f - SURFACE_BEHIND_START_SCALE_FACTOR) * + MathUtils.clamp(amount, 0f, 1f)) + + // If we're dismissing via swipe to the Launcher, we'll play in-window scale animations, + // so don't also scale the window. + if (keyguardStateController.isDismissingFromSwipe && + willUnlockWithInWindowLauncherAnimations) { + scaleFactor = 1f } - } else { - applyParamsToSurface( - SyncRtSurfaceTransactionApplier.SurfaceParams.Builder( - surfaceBehindRemoteAnimationTarget!!.leash) - .withMatrix(surfaceBehindMatrix) - .withCornerRadius(roundedCornerRadius) - .withAlpha(animationAlpha) - .build() + + // Translate up from the bottom. + surfaceBehindMatrix.setTranslate( + surfaceBehindRemoteAnimationTarget.screenSpaceBounds.left.toFloat(), + surfaceHeight * SURFACE_BEHIND_START_TRANSLATION_Y * (1f - amount) ) + + // Scale up from a point at the center-bottom of the surface. + surfaceBehindMatrix.postScale( + scaleFactor, + scaleFactor, + keyguardViewController.viewRootImpl.width / 2f, + surfaceHeight * SURFACE_BEHIND_SCALE_PIVOT_Y + ) + + // If we're snapping the keyguard back, immediately begin fading it out. + val animationAlpha = + if (keyguardStateController.isSnappingKeyguardBackAfterSwipe) amount + else surfaceBehindAlpha + + // SyncRtSurfaceTransactionApplier cannot apply transaction when the target view is + // unable to draw + val sc: SurfaceControl? = surfaceBehindRemoteAnimationTarget.leash + if (keyguardViewController.viewRootImpl.view?.visibility != View.VISIBLE && + sc?.isValid == true) { + with(SurfaceControl.Transaction()) { + setMatrix(sc, surfaceBehindMatrix, tmpFloat) + setCornerRadius(sc, roundedCornerRadius) + setAlpha(sc, animationAlpha) + apply() + } + } else { + applyParamsToSurface( + SyncRtSurfaceTransactionApplier.SurfaceParams.Builder( + surfaceBehindRemoteAnimationTarget.leash) + .withMatrix(surfaceBehindMatrix) + .withCornerRadius(roundedCornerRadius) + .withAlpha(animationAlpha) + .build() + ) + } } } @@ -795,8 +789,7 @@ class KeyguardUnlockAnimationController @Inject constructor( launcherUnlockController?.setUnlockAmount(1f, false /* forceIfAnimating */) // That target is no longer valid since the animation finished, null it out. - surfaceBehindRemoteAnimationTarget = null - surfaceBehindParams = null + surfaceBehindRemoteAnimationTargets = null playingCannedUnlockAnimation = false willUnlockWithInWindowLauncherAnimations = false @@ -828,7 +821,6 @@ class KeyguardUnlockAnimationController @Inject constructor( private fun applyParamsToSurface(params: SyncRtSurfaceTransactionApplier.SurfaceParams) { surfaceTransactionApplier!!.scheduleApply(params) - surfaceBehindParams = params } private fun fadeInSurfaceBehind() { diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java index d4ef4675392d..be1d162e2b08 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java @@ -831,7 +831,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable, public void onLaunchAnimationStart(boolean isExpandingFullyAbove) {} @Override - public void onLaunchAnimationCancelled() { + public void onLaunchAnimationCancelled(@Nullable Boolean newKeyguardOccludedState) { Log.d(TAG, "Occlude launch animation cancelled. Occluded state is now: " + mOccluded); } @@ -887,6 +887,86 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable, private IRemoteAnimationRunner mOccludeAnimationRunner = new OccludeActivityLaunchRemoteAnimationRunner(mOccludeAnimationController); + private final IRemoteAnimationRunner mOccludeByDreamAnimationRunner = + new IRemoteAnimationRunner.Stub() { + @Nullable private ValueAnimator mOccludeByDreamAnimator; + + @Override + public void onAnimationCancelled(boolean isKeyguardOccluded) { + if (mOccludeByDreamAnimator != null) { + mOccludeByDreamAnimator.cancel(); + } + setOccluded(isKeyguardOccluded /* isOccluded */, false /* animate */); + if (DEBUG) { + Log.d(TAG, "Occlude by Dream animation cancelled. Occluded state is now: " + + mOccluded); + } + } + + @Override + public void onAnimationStart(int transit, RemoteAnimationTarget[] apps, + RemoteAnimationTarget[] wallpapers, RemoteAnimationTarget[] nonApps, + IRemoteAnimationFinishedCallback finishedCallback) throws RemoteException { + setOccluded(true /* isOccluded */, true /* animate */); + + if (apps == null || apps.length == 0 || apps[0] == null) { + if (DEBUG) { + Log.d(TAG, "No apps provided to the OccludeByDream runner; " + + "skipping occluding animation."); + } + finishedCallback.onAnimationFinished(); + return; + } + + final RemoteAnimationTarget primary = apps[0]; + final boolean isDream = (apps[0].taskInfo.topActivityType + == WindowConfiguration.ACTIVITY_TYPE_DREAM); + if (!isDream) { + Log.w(TAG, "The occluding app isn't Dream; " + + "finishing up. Please check that the config is correct."); + finishedCallback.onAnimationFinished(); + return; + } + + final SyncRtSurfaceTransactionApplier applier = + new SyncRtSurfaceTransactionApplier( + mKeyguardViewControllerLazy.get().getViewRootImpl().getView()); + + mContext.getMainExecutor().execute(() -> { + if (mOccludeByDreamAnimator != null) { + mOccludeByDreamAnimator.cancel(); + } + + mOccludeByDreamAnimator = ValueAnimator.ofFloat(0f, 1f); + // Use the same duration as for the UNOCCLUDE. + mOccludeByDreamAnimator.setDuration(UNOCCLUDE_ANIMATION_DURATION); + mOccludeByDreamAnimator.setInterpolator(Interpolators.LINEAR); + mOccludeByDreamAnimator.addUpdateListener( + animation -> { + SyncRtSurfaceTransactionApplier.SurfaceParams.Builder + paramsBuilder = + new SyncRtSurfaceTransactionApplier.SurfaceParams + .Builder(primary.leash) + .withAlpha(animation.getAnimatedFraction()); + applier.scheduleApply(paramsBuilder.build()); + }); + mOccludeByDreamAnimator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + try { + finishedCallback.onAnimationFinished(); + mOccludeByDreamAnimator = null; + } catch (RemoteException e) { + e.printStackTrace(); + } + } + }); + + mOccludeByDreamAnimator.start(); + }); + } + }; + /** * Animation controller for activities that unocclude the keyguard. This does not use the * ActivityLaunchAnimator since we're just translating down, rather than emerging from a view @@ -1682,6 +1762,10 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable, return mOccludeAnimationRunner; } + public IRemoteAnimationRunner getOccludeByDreamAnimationRunner() { + return mOccludeByDreamAnimationRunner; + } + public IRemoteAnimationRunner getUnoccludeAnimationRunner() { return mUnoccludeAnimationRunner; } @@ -2503,18 +2587,10 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable, mInteractionJankMonitor.begin( createInteractionJankMonitorConf("DismissPanel")); - // Apply the opening animation on root task if exists - RemoteAnimationTarget aniTarget = apps[0]; - for (RemoteAnimationTarget tmpTarget : apps) { - if (tmpTarget.taskId != -1 && !tmpTarget.hasAnimatingParent) { - aniTarget = tmpTarget; - break; - } - } // Pass the surface and metadata to the unlock animation controller. mKeyguardUnlockAnimationControllerLazy.get() .notifyStartSurfaceBehindRemoteAnimation( - aniTarget, startTime, mSurfaceBehindRemoteAnimationRequested); + apps, startTime, mSurfaceBehindRemoteAnimationRequested); } else { mInteractionJankMonitor.begin( createInteractionJankMonitorConf("RemoteAnimationDisabled")); 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 e52d9ee7b9d4..840a4b20a3f0 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 @@ -20,6 +20,7 @@ import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLoggin import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow import com.android.systemui.common.shared.model.Position import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.doze.DozeHost import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.statusbar.policy.KeyguardStateController import javax.inject.Inject @@ -28,6 +29,7 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.distinctUntilChanged /** Defines interface for classes that encapsulate application state for the keyguard. */ interface KeyguardRepository { @@ -102,6 +104,7 @@ class KeyguardRepositoryImpl constructor( statusBarStateController: StatusBarStateController, keyguardStateController: KeyguardStateController, + dozeHost: DozeHost, ) : KeyguardRepository { private val _animateBottomAreaDozingTransitions = MutableStateFlow(false) override val animateBottomAreaDozingTransitions = @@ -136,19 +139,21 @@ constructor( awaitClose { keyguardStateController.removeCallback(callback) } } - override val isDozing: Flow<Boolean> = conflatedCallbackFlow { - val callback = - object : StatusBarStateController.StateListener { - override fun onDozingChanged(isDozing: Boolean) { - trySendWithFailureLogging(isDozing, TAG, "updated isDozing") - } + override val isDozing: Flow<Boolean> = + conflatedCallbackFlow { + val callback = + object : DozeHost.Callback { + override fun onDozingChanged(isDozing: Boolean) { + trySendWithFailureLogging(isDozing, TAG, "updated isDozing") + } + } + dozeHost.addCallback(callback) + trySendWithFailureLogging(false, TAG, "initial isDozing: false") + + awaitClose { dozeHost.removeCallback(callback) } } + .distinctUntilChanged() - statusBarStateController.addCallback(callback) - trySendWithFailureLogging(statusBarStateController.isDozing, TAG, "initial isDozing") - - awaitClose { statusBarStateController.removeCallback(callback) } - } override val dozeAmount: Flow<Float> = conflatedCallbackFlow { val callback = object : StatusBarStateController.StateListener { diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt index 9a69e26488d9..95acc0b8564e 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt @@ -32,6 +32,7 @@ import javax.inject.Inject import kotlin.reflect.KClass import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.onStart @SysUISingleton class KeyguardQuickAffordanceInteractor @@ -88,7 +89,15 @@ constructor( position: KeyguardQuickAffordancePosition ): Flow<KeyguardQuickAffordanceModel> { val configs = registry.getAll(position) - return combine(configs.map { config -> config.state }) { states -> + return combine( + configs.map { config -> + // We emit an initial "Hidden" value to make sure that there's always an initial + // value and avoid subtle bugs where the downstream isn't receiving any values + // because one config implementation is not emitting an initial value. For example, + // see b/244296596. + config.state.onStart { emit(KeyguardQuickAffordanceConfig.State.Hidden) } + } + ) { states -> val index = states.indexOfFirst { it is KeyguardQuickAffordanceConfig.State.Visible } if (index != -1) { val visibleState = states[index] as KeyguardQuickAffordanceConfig.State.Visible diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/quickaffordance/HomeControlsKeyguardQuickAffordanceConfig.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/quickaffordance/HomeControlsKeyguardQuickAffordanceConfig.kt index 8f32ff9db50c..ac2c9b1d7ff2 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/quickaffordance/HomeControlsKeyguardQuickAffordanceConfig.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/quickaffordance/HomeControlsKeyguardQuickAffordanceConfig.kt @@ -94,6 +94,7 @@ constructor( hasFavorites = favorites?.isNotEmpty() == true, hasServiceInfos = serviceInfos.isNotEmpty(), iconResourceId = component.getTileImageId(), + visibility = component.getVisibility(), ), TAG, ) @@ -110,9 +111,16 @@ constructor( isFeatureEnabled: Boolean, hasFavorites: Boolean, hasServiceInfos: Boolean, + visibility: ControlsComponent.Visibility, @DrawableRes iconResourceId: Int?, ): KeyguardQuickAffordanceConfig.State { - return if (isFeatureEnabled && hasFavorites && hasServiceInfos && iconResourceId != null) { + return if ( + isFeatureEnabled && + hasFavorites && + hasServiceInfos && + iconResourceId != null && + visibility == ControlsComponent.Visibility.AVAILABLE + ) { KeyguardQuickAffordanceConfig.State.Visible( icon = ContainedDrawable.WithResource(iconResourceId), contentDescriptionResourceId = component.getTileTitleId(), diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/BiometricMessagesLog.java b/packages/SystemUI/src/com/android/systemui/log/dagger/BiometricMessagesLog.java new file mode 100644 index 000000000000..7f1ad6d20c16 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/log/dagger/BiometricMessagesLog.java @@ -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.log.dagger; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +import javax.inject.Qualifier; + +/** + * A {@link com.android.systemui.log.LogBuffer} for BiometricMessages processing such as + * {@link com.android.systemui.biometrics.FaceHelpMessageDeferral} + */ +@Qualifier +@Documented +@Retention(RetentionPolicy.RUNTIME) +public @interface BiometricMessagesLog { +} diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/BluetoothLog.kt b/packages/SystemUI/src/com/android/systemui/log/dagger/BluetoothLog.kt new file mode 100644 index 000000000000..4887b6a14658 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/log/dagger/BluetoothLog.kt @@ -0,0 +1,22 @@ +/* + * 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.log.dagger + +import javax.inject.Qualifier + +/** A [com.android.systemui.log.LogBuffer] for bluetooth. */ +@Qualifier @MustBeDocumented @Retention(AnnotationRetention.RUNTIME) annotation class BluetoothLog diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/KeyguardUpdateMonitorLog.kt b/packages/SystemUI/src/com/android/systemui/log/dagger/KeyguardUpdateMonitorLog.kt index 323ee21953ea..b551125fccc7 100644 --- a/packages/SystemUI/src/com/android/systemui/log/dagger/KeyguardUpdateMonitorLog.kt +++ b/packages/SystemUI/src/com/android/systemui/log/dagger/KeyguardUpdateMonitorLog.kt @@ -1,4 +1,9 @@ package com.android.systemui.log.dagger +import javax.inject.Qualifier + /** A [com.android.systemui.log.LogBuffer] for KeyguardUpdateMonitor. */ +@Qualifier +@MustBeDocumented +@Retention(AnnotationRetention.RUNTIME) annotation class KeyguardUpdateMonitorLog diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java index c2a87649adef..5612c22311fb 100644 --- a/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java +++ b/packages/SystemUI/src/com/android/systemui/log/dagger/LogModule.java @@ -287,6 +287,17 @@ public class LogModule { } /** + * Provides a {@link LogBuffer} for use by + * {@link com.android.systemui.biometrics.FaceHelpMessageDeferral}. + */ + @Provides + @SysUISingleton + @BiometricMessagesLog + public static LogBuffer provideBiometricMessagesLogBuffer(LogBufferFactory factory) { + return factory.create("BiometricMessagesLog", 150); + } + + /** * Provides a {@link LogBuffer} for use by the status bar network controller. */ @Provides @@ -305,4 +316,14 @@ public class LogModule { public static LogBuffer provideKeyguardUpdateMonitorLogBuffer(LogBufferFactory factory) { return factory.create("KeyguardUpdateMonitorLog", 200); } + + /** + * Provides a {@link LogBuffer} for bluetooth-related logs. + */ + @Provides + @SysUISingleton + @BluetoothLog + public static LogBuffer providerBluetoothLogBuffer(LogBufferFactory factory) { + return factory.create("BluetoothLog", 50); + } } diff --git a/packages/SystemUI/src/com/android/systemui/log/dagger/StatusBarConnectivityLog.java b/packages/SystemUI/src/com/android/systemui/log/dagger/StatusBarConnectivityLog.java index f03fbcba41b7..b237f2d74483 100644 --- a/packages/SystemUI/src/com/android/systemui/log/dagger/StatusBarConnectivityLog.java +++ b/packages/SystemUI/src/com/android/systemui/log/dagger/StatusBarConnectivityLog.java @@ -19,7 +19,6 @@ package com.android.systemui.log.dagger; import static java.lang.annotation.RetentionPolicy.RUNTIME; import com.android.systemui.log.LogBuffer; -import com.android.systemui.statusbar.pipeline.ConnectivityInfoProcessor; import java.lang.annotation.Documented; import java.lang.annotation.Retention; @@ -27,7 +26,7 @@ import java.lang.annotation.Retention; import javax.inject.Qualifier; /** - * A {@link LogBuffer} for events processed by {@link ConnectivityInfoProcessor} + * A {@link LogBuffer} for status bar connectivity events. */ @Qualifier @Documented diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt index 4c6aa7b4cad9..cc77ed15b5f0 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt @@ -458,6 +458,7 @@ class MediaCarouselController @Inject constructor( val existingPlayer = MediaPlayerData.getMediaPlayer(key) val curVisibleMediaKey = MediaPlayerData.playerKeys() .elementAtOrNull(mediaCarouselScrollHandler.visibleMediaIndex) + val isCurVisibleMediaPlaying = MediaPlayerData.getMediaData(curVisibleMediaKey)?.isPlaying if (existingPlayer == null) { val newPlayer = mediaControlPanelFactory.get() newPlayer.attachPlayer(MediaViewHolder.create( @@ -472,13 +473,23 @@ class MediaCarouselController @Inject constructor( key, data, newPlayer, systemClock, isSsReactivated, debugLogger ) updatePlayerToState(newPlayer, noAnimation = true) - reorderAllPlayers(curVisibleMediaKey) + if (data.active) { + reorderAllPlayers(curVisibleMediaKey) + } else { + needsReordering = true + } } else { existingPlayer.bindPlayer(data, key) MediaPlayerData.addMediaPlayer( key, data, existingPlayer, systemClock, isSsReactivated, debugLogger ) - if (isReorderingAllowed || shouldScrollToActivePlayer) { + // Check the playing status of both current visible and new media players + // To make sure we scroll to the active playing media card. + if (isReorderingAllowed || + shouldScrollToActivePlayer && + data.isPlaying == true && + isCurVisibleMediaPlaying == false + ) { reorderAllPlayers(curVisibleMediaKey) } else { needsReordering = true @@ -1035,6 +1046,15 @@ internal object MediaPlayerData { } } + fun getMediaData(mediaSortKey: MediaSortKey?): MediaData? { + mediaData.forEach { (key, value) -> + if (value == mediaSortKey) { + return mediaData[key]?.data + } + } + return null + } + fun getMediaPlayer(key: String): MediaControlPanel? { return mediaData.get(key)?.let { mediaPlayers.get(it) } } diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt index ae4c7c73a2ea..6baf6e137ab4 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt @@ -41,6 +41,7 @@ import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.dreams.DreamOverlayStateController import com.android.systemui.keyguard.WakefulnessLifecycle +import com.android.systemui.media.dream.MediaDreamComplication import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.shade.NotifPanelEvents import com.android.systemui.statusbar.CrossFadeHelper @@ -401,7 +402,7 @@ class MediaHierarchyManager @Inject constructor( } /** - * Is the doze animation currently Running + * Is the dream overlay currently active */ private var dreamOverlayActive: Boolean = false private set(value) { @@ -412,6 +413,17 @@ class MediaHierarchyManager @Inject constructor( } /** + * Is the dream media complication currently active + */ + private var dreamMediaComplicationActive: Boolean = false + private set(value) { + if (field != value) { + field = value + updateDesiredLocation(forceNoAnimation = true) + } + } + + /** * The current cross fade progress. 0.5f means it's just switching * between the start and the end location and the content is fully faded, while 0.75f means * that we're halfway faded in again in the target state. @@ -500,6 +512,12 @@ class MediaHierarchyManager @Inject constructor( }) dreamOverlayStateController.addCallback(object : DreamOverlayStateController.Callback { + override fun onComplicationsChanged() { + dreamMediaComplicationActive = dreamOverlayStateController.complications.any { + it is MediaDreamComplication + } + } + override fun onStateChanged() { dreamOverlayStateController.isOverlayActive.also { dreamOverlayActive = it } } @@ -1068,7 +1086,7 @@ class MediaHierarchyManager @Inject constructor( val onLockscreen = (!bypassController.bypassEnabled && (statusbarState == StatusBarState.KEYGUARD)) val location = when { - dreamOverlayActive -> LOCATION_DREAM_OVERLAY + dreamOverlayActive && dreamMediaComplicationActive -> LOCATION_DREAM_OVERLAY (qsExpansion > 0.0f || inSplitShade) && !onLockscreen -> LOCATION_QS qsExpansion > 0.4f && onLockscreen -> LOCATION_QS !hasActiveMedia -> LOCATION_QS diff --git a/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java b/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java index 75fa2f181d7c..0b9b32b0d7d7 100644 --- a/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java +++ b/packages/SystemUI/src/com/android/systemui/media/RingtonePlayer.java @@ -96,8 +96,9 @@ public class RingtonePlayer extends CoreStartable { mToken = token; mRingtone = new Ringtone(getContextForUser(user), false); - mRingtone.setAudioAttributes(aa); + mRingtone.setAudioAttributesField(aa); mRingtone.setUri(uri, volumeShaperConfig); + mRingtone.createLocalMediaPlayer(); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/media/SquigglyProgress.kt b/packages/SystemUI/src/com/android/systemui/media/SquigglyProgress.kt index 88f6f3dd9d0e..6bc94cd5f525 100644 --- a/packages/SystemUI/src/com/android/systemui/media/SquigglyProgress.kt +++ b/packages/SystemUI/src/com/android/systemui/media/SquigglyProgress.kt @@ -60,6 +60,8 @@ class SquigglyProgress : Drawable() { linePaint.strokeWidth = value } + // Enables a transition region where the amplitude + // of the wave is reduced linearly across it. var transitionEnabled = true set(value) { field = value @@ -116,44 +118,40 @@ class SquigglyProgress : Drawable() { } val progress = level / 10_000f - val totalProgressPx = bounds.width() * progress - val waveProgressPx = bounds.width() * ( + val totalWidth = bounds.width().toFloat() + val totalProgressPx = totalWidth * progress + val waveProgressPx = totalWidth * ( if (!transitionEnabled || progress > matchedWaveEndpoint) progress else lerp(minWaveEndpoint, matchedWaveEndpoint, lerpInv(0f, matchedWaveEndpoint, progress))) // Build Wiggly Path - val waveStart = -phaseOffset - val waveEnd = waveProgressPx - val transitionLength = if (transitionEnabled) transitionPeriods * waveLength else 0.01f + val waveStart = -phaseOffset - waveLength / 2f + val waveEnd = if (transitionEnabled) totalWidth else waveProgressPx // helper function, computes amplitude for wave segment val computeAmplitude: (Float, Float) -> Float = { x, sign -> - sign * heightFraction * lineAmplitude * - lerpInvSat(waveEnd, waveEnd - transitionLength, x) + if (transitionEnabled) { + val length = transitionPeriods * waveLength + val coeff = lerpInvSat( + waveProgressPx + length / 2f, + waveProgressPx - length / 2f, + x) + sign * heightFraction * lineAmplitude * coeff + } else { + sign * heightFraction * lineAmplitude + } } - var currentX = waveEnd - var waveSign = if (phaseOffset < waveLength / 2) 1f else -1f + // Reset path object to the start path.rewind() + path.moveTo(waveStart, 0f) - // Draw flat line from end to wave endpoint - path.moveTo(bounds.width().toFloat(), 0f) - path.lineTo(waveEnd, 0f) - - // First wave has shortened wavelength - // approx quarter wave gets us to first wave peak - // shouldn't be big enough to notice it's not a sin wave - currentX -= phaseOffset % (waveLength / 2) - val controlRatio = 0.25f + // Build the wave, incrementing by half the wavelength each time + var currentX = waveStart + var waveSign = 1f var currentAmp = computeAmplitude(currentX, waveSign) - path.cubicTo( - waveEnd, currentAmp * controlRatio, - lerp(currentX, waveEnd, controlRatio), currentAmp, - currentX, currentAmp) - - // Other waves have full wavelength - val dist = -1 * waveLength / 2f - while (currentX > waveStart) { + val dist = waveLength / 2f + while (currentX < waveEnd) { waveSign = -waveSign val nextX = currentX + dist val midX = currentX + dist / 2 @@ -166,34 +164,35 @@ class SquigglyProgress : Drawable() { currentX = nextX } - // Draw path; clip to progress position + // translate to the start position of the progress bar for all draw commands + val clipTop = lineAmplitude + strokeWidth canvas.save() canvas.translate(bounds.left.toFloat(), bounds.centerY().toFloat()) - canvas.clipRect( - 0f, - -lineAmplitude - strokeWidth, - totalProgressPx, - lineAmplitude + strokeWidth) - canvas.drawPath(path, wavePaint) - canvas.restore() - // Draw path; clip between progression position & far edge + // Draw path up to progress position canvas.save() - canvas.translate(bounds.left.toFloat(), bounds.centerY().toFloat()) - canvas.clipRect( - totalProgressPx, - -lineAmplitude - strokeWidth, - bounds.width().toFloat(), - lineAmplitude + strokeWidth) - canvas.drawPath(path, linePaint) + canvas.clipRect(0f, -1f * clipTop, totalProgressPx, clipTop) + canvas.drawPath(path, wavePaint) canvas.restore() + if (transitionEnabled) { + // If there's a smooth transition, we draw the rest of the + // path in a different color (using different clip params) + canvas.save() + canvas.clipRect(totalProgressPx, -1f * clipTop, totalWidth, clipTop) + canvas.drawPath(path, linePaint) + canvas.restore() + } else { + // No transition, just draw a flat line to the end of the region. + // The discontinuity is hidden by the progress bar thumb shape. + canvas.drawLine(totalProgressPx, 0f, totalWidth, 0f, linePaint) + } + // Draw round line cap at the beginning of the wave - val startAmp = cos(abs(waveEnd - phaseOffset) / waveLength * TWO_PI) - canvas.drawPoint( - bounds.left.toFloat(), - bounds.centerY() + startAmp * lineAmplitude * heightFraction, - wavePaint) + val startAmp = cos(abs(waveStart) / waveLength * TWO_PI) + canvas.drawPoint(0f, startAmp * lineAmplitude * heightFraction, wavePaint) + + canvas.restore() } override fun getOpacity(): Int { @@ -233,4 +232,4 @@ class SquigglyProgress : Drawable() { linePaint.color = ColorUtils.setAlphaComponent(tintColor, (DISABLED_ALPHA * (alpha / 255f)).toInt()) } -}
\ No newline at end of file +} diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java index e08e33802ce0..85d8f3fdd20a 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java @@ -310,6 +310,7 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements if (icon.getType() != Icon.TYPE_BITMAP && icon.getType() != Icon.TYPE_ADAPTIVE_BITMAP) { // icon doesn't support getBitmap, use default value for color scheme updateButtonBackgroundColorFilter(); + updateDialogBackgroundColor(); } else { Configuration config = mContext.getResources().getConfiguration(); int currentNightMode = config.uiMode & Configuration.UI_MODE_NIGHT_MASK; @@ -319,11 +320,14 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements if (colorSetUpdated) { mAdapter.updateColorScheme(wallpaperColors, isDarkThemeOn); updateButtonBackgroundColorFilter(); + updateDialogBackgroundColor(); } } mHeaderIcon.setVisibility(View.VISIBLE); mHeaderIcon.setImageIcon(icon); } else { + updateButtonBackgroundColorFilter(); + updateDialogBackgroundColor(); mHeaderIcon.setVisibility(View.GONE); } if (appSourceIcon != null) { @@ -381,11 +385,16 @@ public abstract class MediaOutputBaseDialog extends SystemUIDialog implements private void updateButtonBackgroundColorFilter() { ColorFilter buttonColorFilter = new PorterDuffColorFilter( - mAdapter.getController().getColorButtonBackground(), + mMediaOutputController.getColorButtonBackground(), PorterDuff.Mode.SRC_IN); mDoneButton.getBackground().setColorFilter(buttonColorFilter); mStopButton.getBackground().setColorFilter(buttonColorFilter); - mDoneButton.setTextColor(mAdapter.getController().getColorPositiveButtonText()); + mDoneButton.setTextColor(mMediaOutputController.getColorPositiveButtonText()); + } + + private void updateDialogBackgroundColor() { + getDialogView().getBackground().setTint(mMediaOutputController.getColorDialogBackground()); + mDeviceListLayout.setBackgroundColor(mMediaOutputController.getColorDialogBackground()); } private Drawable resizeDrawable(Drawable drawable, int size) { diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java index 8dd843a6f921..7b4ac1214a7c 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java @@ -133,6 +133,7 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, @VisibleForTesting LocalMediaManager mLocalMediaManager; private MediaOutputMetricLogger mMetricLogger; + private int mCurrentState; private int mColorItemContent; private int mColorSeekbarProgress; @@ -140,6 +141,7 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, private int mColorItemBackground; private int mColorConnectedItemBackground; private int mColorPositiveButtonText; + private int mColorDialogBackground; private float mInactiveRadius; private float mActiveRadius; @@ -188,6 +190,8 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, R.dimen.media_output_dialog_background_radius); mActiveRadius = mContext.getResources().getDimension( R.dimen.media_output_dialog_active_background_radius); + mColorDialogBackground = Utils.getColorStateListDefaultColor(mContext, + R.color.media_dialog_background); } void start(@NonNull Callback cb) { @@ -204,6 +208,9 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, if (TextUtils.equals(controller.getPackageName(), mPackageName)) { mMediaController = controller; mMediaController.unregisterCallback(mCb); + if (mMediaController.getPlaybackState() != null) { + mCurrentState = mMediaController.getPlaybackState().getState(); + } mMediaController.registerCallback(mCb); break; } @@ -471,6 +478,7 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, mColorItemBackground = mCurrentColorScheme.getNeutral2().get(9); // N2-800 mColorConnectedItemBackground = mCurrentColorScheme.getAccent2().get(9); // A2-800 mColorPositiveButtonText = mCurrentColorScheme.getAccent2().get(9); // A2-800 + mColorDialogBackground = mCurrentColorScheme.getNeutral1().get(10); // N1-900 } else { mColorItemContent = mCurrentColorScheme.getAccent1().get(9); // A1-800 mColorSeekbarProgress = mCurrentColorScheme.getAccent1().get(4); // A1-300 @@ -478,6 +486,7 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, mColorItemBackground = mCurrentColorScheme.getAccent2().get(1); // A2-50 mColorConnectedItemBackground = mCurrentColorScheme.getAccent1().get(2); // A1-100 mColorPositiveButtonText = mCurrentColorScheme.getNeutral1().get(1); // N1-50 + mColorDialogBackground = mCurrentColorScheme.getBackgroundColor(); } } @@ -497,6 +506,10 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, return mColorPositiveButtonText; } + public int getColorDialogBackground() { + return mColorDialogBackground; + } + public int getColorItemContent() { return mColorItemContent; } @@ -994,10 +1007,16 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback, @Override public void onPlaybackStateChanged(PlaybackState playbackState) { - final int state = playbackState.getState(); - if (state == PlaybackState.STATE_STOPPED || state == PlaybackState.STATE_PAUSED) { + final int newState = + playbackState == null ? PlaybackState.STATE_STOPPED : playbackState.getState(); + if (mCurrentState == newState) { + return; + } + + if (newState == PlaybackState.STATE_STOPPED || newState == PlaybackState.STATE_PAUSED) { mCallback.onMediaStoppedOrPaused(); } + mCurrentState = newState; } }; diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputMetricLogger.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputMetricLogger.java index 6fe06e085556..7d3e82c9d47f 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputMetricLogger.java +++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputMetricLogger.java @@ -107,7 +107,8 @@ public class MediaOutputMetricLogger { SysUiStatsLog.write( SysUiStatsLog.MEDIAOUTPUT_OP_INTERACTION_REPORT, SysUiStatsLog.MEDIA_OUTPUT_OP_INTERACTION_REPORTED__INTERACTION_TYPE__ADJUST_VOLUME, - getInteractionDeviceType(source)); + getInteractionDeviceType(source), + getLoggingPackageName()); } /** @@ -121,7 +122,8 @@ public class MediaOutputMetricLogger { SysUiStatsLog.write( SysUiStatsLog.MEDIAOUTPUT_OP_INTERACTION_REPORT, SysUiStatsLog.MEDIA_OUTPUT_OP_INTERACTION_REPORTED__INTERACTION_TYPE__STOP_CASTING, - SysUiStatsLog.MEDIA_OUTPUT_OP_INTERACTION_REPORTED__TARGET__UNKNOWN_TYPE); + SysUiStatsLog.MEDIA_OUTPUT_OP_INTERACTION_REPORTED__TARGET__UNKNOWN_TYPE, + getLoggingPackageName()); } /** @@ -135,7 +137,8 @@ public class MediaOutputMetricLogger { SysUiStatsLog.write( SysUiStatsLog.MEDIAOUTPUT_OP_INTERACTION_REPORT, SysUiStatsLog.MEDIA_OUTPUT_OP_INTERACTION_REPORTED__INTERACTION_TYPE__EXPANSION, - getInteractionDeviceType(source)); + getInteractionDeviceType(source), + getLoggingPackageName()); } /** diff --git a/packages/SystemUI/src/com/android/systemui/media/dream/MediaDreamSentinel.java b/packages/SystemUI/src/com/android/systemui/media/dream/MediaDreamSentinel.java index acd04f216a98..dc1488eefc4e 100644 --- a/packages/SystemUI/src/com/android/systemui/media/dream/MediaDreamSentinel.java +++ b/packages/SystemUI/src/com/android/systemui/media/dream/MediaDreamSentinel.java @@ -19,6 +19,7 @@ package com.android.systemui.media.dream; import static com.android.systemui.flags.Flags.MEDIA_DREAM_COMPLICATION; import android.content.Context; +import android.util.Log; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -38,6 +39,9 @@ import javax.inject.Inject; * the media complication as appropriate */ public class MediaDreamSentinel extends CoreStartable { + private static final String TAG = "MediaDreamSentinel"; + private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); + private final MediaDataManager.Listener mListener = new MediaDataManager.Listener() { private boolean mAdded; @Override @@ -46,11 +50,17 @@ public class MediaDreamSentinel extends CoreStartable { @Override public void onMediaDataRemoved(@NonNull String key) { + final boolean hasActiveMedia = mMediaDataManager.hasActiveMedia(); + if (DEBUG) { + Log.d(TAG, "onMediaDataRemoved(" + key + "), mAdded=" + mAdded + ", hasActiveMedia=" + + hasActiveMedia); + } + if (!mAdded) { return; } - if (mMediaDataManager.hasActiveMedia()) { + if (hasActiveMedia) { return; } @@ -71,11 +81,24 @@ public class MediaDreamSentinel extends CoreStartable { return; } + final boolean hasActiveMedia = mMediaDataManager.hasActiveMedia(); + if (DEBUG) { + Log.d(TAG, "onMediaDataLoaded(" + key + "), mAdded=" + mAdded + ", hasActiveMedia=" + + hasActiveMedia); + } + + // Media data can become inactive without triggering onMediaDataRemoved. + if (mAdded && !hasActiveMedia) { + mAdded = false; + mDreamOverlayStateController.removeComplication(mMediaEntryComplication); + return; + } + if (mAdded) { return; } - if (!mMediaDataManager.hasActiveMedia()) { + if (!hasActiveMedia) { return; } diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommon.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommon.kt deleted file mode 100644 index 3a0ac1b7d9b0..000000000000 --- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommon.kt +++ /dev/null @@ -1,279 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.systemui.media.taptotransfer.common - -import android.annotation.LayoutRes -import android.annotation.SuppressLint -import android.content.Context -import android.content.pm.PackageManager -import android.graphics.PixelFormat -import android.graphics.drawable.Drawable -import android.os.PowerManager -import android.os.SystemClock -import android.util.Log -import android.view.LayoutInflater -import android.view.ViewGroup -import android.view.WindowManager -import android.view.accessibility.AccessibilityManager -import android.view.accessibility.AccessibilityManager.FLAG_CONTENT_CONTROLS -import android.view.accessibility.AccessibilityManager.FLAG_CONTENT_ICONS -import android.view.accessibility.AccessibilityManager.FLAG_CONTENT_TEXT -import androidx.annotation.CallSuper -import com.android.internal.widget.CachingIconView -import com.android.settingslib.Utils -import com.android.systemui.R -import com.android.systemui.dagger.qualifiers.Main -import com.android.systemui.statusbar.policy.ConfigurationController -import com.android.systemui.util.concurrency.DelayableExecutor -import com.android.systemui.util.view.ViewUtil - -/** - * A superclass controller that provides common functionality for showing chips on the sender device - * and the receiver device. - * - * Subclasses need to override and implement [updateChipView], which is where they can control what - * gets displayed to the user. - * - * The generic type T is expected to contain all the information necessary for the subclasses to - * display the chip in a certain state, since they receive <T> in [updateChipView]. - */ -abstract class MediaTttChipControllerCommon<T : ChipInfoCommon>( - internal val context: Context, - internal val logger: MediaTttLogger, - internal val windowManager: WindowManager, - private val viewUtil: ViewUtil, - @Main private val mainExecutor: DelayableExecutor, - private val accessibilityManager: AccessibilityManager, - private val configurationController: ConfigurationController, - private val powerManager: PowerManager, - @LayoutRes private val chipLayoutRes: Int, -) { - /** - * Window layout params that will be used as a starting point for the [windowLayoutParams] of - * all subclasses. - */ - @SuppressLint("WrongConstant") // We're allowed to use TYPE_VOLUME_OVERLAY - internal val commonWindowLayoutParams = WindowManager.LayoutParams().apply { - width = WindowManager.LayoutParams.WRAP_CONTENT - height = WindowManager.LayoutParams.WRAP_CONTENT - type = WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY - flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL - title = WINDOW_TITLE - format = PixelFormat.TRANSLUCENT - setTrustedOverlay() - } - - /** - * The window layout parameters we'll use when attaching the view to a window. - * - * Subclasses must override this to provide their specific layout params, and they should use - * [commonWindowLayoutParams] as part of their layout params. - */ - internal abstract val windowLayoutParams: WindowManager.LayoutParams - - /** The chip view currently being displayed. Null if the chip is not being displayed. */ - private var chipView: ViewGroup? = null - - /** The chip info currently being displayed. Null if the chip is not being displayed. */ - internal var chipInfo: T? = null - - /** A [Runnable] that, when run, will cancel the pending timeout of the chip. */ - private var cancelChipViewTimeout: Runnable? = null - - /** - * Displays the chip with the provided [newChipInfo]. - * - * This method handles inflating and attaching the view, then delegates to [updateChipView] to - * display the correct information in the chip. - */ - fun displayChip(newChipInfo: T) { - val currentChipView = chipView - - if (currentChipView != null) { - updateChipView(newChipInfo, currentChipView) - } else { - // The chip is new, so set up all our callbacks and inflate the view - configurationController.addCallback(displayScaleListener) - // Wake the screen if necessary so the user will see the chip. (Per b/239426653, we want - // the chip to show over the dream state, so we should only wake up if the screen is - // completely off.) - if (!powerManager.isScreenOn) { - powerManager.wakeUp( - SystemClock.uptimeMillis(), - PowerManager.WAKE_REASON_APPLICATION, - "com.android.systemui:media_tap_to_transfer_activated" - ) - } - - inflateAndUpdateChip(newChipInfo) - } - - // Cancel and re-set the chip timeout each time we get a new state. - val timeout = accessibilityManager.getRecommendedTimeoutMillis( - newChipInfo.getTimeoutMs().toInt(), - // Not all chips have controls so FLAG_CONTENT_CONTROLS might be superfluous, but - // include it just to be safe. - FLAG_CONTENT_ICONS or FLAG_CONTENT_TEXT or FLAG_CONTENT_CONTROLS - ) - cancelChipViewTimeout?.run() - cancelChipViewTimeout = mainExecutor.executeDelayed( - { removeChip(MediaTttRemovalReason.REASON_TIMEOUT) }, - timeout.toLong() - ) - } - - /** Inflates a new chip view, updates it with [newChipInfo], and adds the view to the window. */ - private fun inflateAndUpdateChip(newChipInfo: T) { - val newChipView = LayoutInflater - .from(context) - .inflate(chipLayoutRes, null) as ViewGroup - chipView = newChipView - updateChipView(newChipInfo, newChipView) - windowManager.addView(newChipView, windowLayoutParams) - animateChipIn(newChipView) - } - - /** Removes then re-inflates the chip. */ - private fun reinflateChip() { - val currentChipInfo = chipInfo - if (chipView == null || currentChipInfo == null) { return } - - windowManager.removeView(chipView) - inflateAndUpdateChip(currentChipInfo) - } - - private val displayScaleListener = object : ConfigurationController.ConfigurationListener { - override fun onDensityOrFontScaleChanged() { - reinflateChip() - } - } - - /** - * Hides the chip. - * - * @param removalReason a short string describing why the chip was removed (timeout, state - * change, etc.) - */ - open fun removeChip(removalReason: String) { - if (chipView == null) { return } - logger.logChipRemoval(removalReason) - configurationController.removeCallback(displayScaleListener) - windowManager.removeView(chipView) - chipView = null - chipInfo = null - // No need to time the chip out since it's already gone - cancelChipViewTimeout?.run() - } - - /** - * A method implemented by subclasses to update [currentChipView] based on [newChipInfo]. - */ - @CallSuper - open fun updateChipView(newChipInfo: T, currentChipView: ViewGroup) { - chipInfo = newChipInfo - } - - /** - * A method that can be implemented by subclcasses to do custom animations for when the chip - * appears. - */ - open fun animateChipIn(chipView: ViewGroup) {} - - /** - * Returns the size that the icon should be, or null if no size override is needed. - */ - open fun getIconSize(isAppIcon: Boolean): Int? = null - - /** - * An internal method to set the icon on the view. - * - * This is in the common superclass since both the sender and the receiver show an icon. - * - * @param appPackageName the package name of the app playing the media. Will be used to fetch - * the app icon and app name if overrides aren't provided. - * - * @return the content description of the icon. - */ - internal fun setIcon( - currentChipView: ViewGroup, - appPackageName: String?, - appIconDrawableOverride: Drawable? = null, - appNameOverride: CharSequence? = null, - ): CharSequence { - val appIconView = currentChipView.requireViewById<CachingIconView>(R.id.app_icon) - val iconInfo = getIconInfo(appPackageName) - - getIconSize(iconInfo.isAppIcon)?.let { size -> - val lp = appIconView.layoutParams - lp.width = size - lp.height = size - appIconView.layoutParams = lp - } - - appIconView.contentDescription = appNameOverride ?: iconInfo.iconName - appIconView.setImageDrawable(appIconDrawableOverride ?: iconInfo.icon) - return appIconView.contentDescription - } - - /** - * Returns the information needed to display the icon. - * - * The information will either contain app name and icon of the app playing media, or a default - * name and icon if we can't find the app name/icon. - */ - private fun getIconInfo(appPackageName: String?): IconInfo { - if (appPackageName != null) { - try { - return IconInfo( - iconName = context.packageManager.getApplicationInfo( - appPackageName, PackageManager.ApplicationInfoFlags.of(0) - ).loadLabel(context.packageManager).toString(), - icon = context.packageManager.getApplicationIcon(appPackageName), - isAppIcon = true - ) - } catch (e: PackageManager.NameNotFoundException) { - Log.w(TAG, "Cannot find package $appPackageName", e) - } - } - return IconInfo( - iconName = context.getString(R.string.media_output_dialog_unknown_launch_app_name), - icon = context.resources.getDrawable(R.drawable.ic_cast).apply { - this.setTint( - Utils.getColorAttrDefaultColor(context, android.R.attr.textColorPrimary) - ) - }, - isAppIcon = false - ) - } -} - -// Used in CTS tests UpdateMediaTapToTransferSenderDisplayTest and -// UpdateMediaTapToTransferReceiverDisplayTest -private const val WINDOW_TITLE = "Media Transfer Chip View" -private val TAG = MediaTttChipControllerCommon::class.simpleName!! - -object MediaTttRemovalReason { - const val REASON_TIMEOUT = "TIMEOUT" - const val REASON_SCREEN_TAP = "SCREEN_TAP" -} - -private data class IconInfo( - val iconName: String, - val icon: Drawable, - /** True if [icon] is the app's icon, and false if [icon] is some generic default icon. */ - val isAppIcon: Boolean -) diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttLogger.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttLogger.kt index aa10f7e2738f..b565f3c22f24 100644 --- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttLogger.kt @@ -18,38 +18,57 @@ package com.android.systemui.media.taptotransfer.common import com.android.systemui.log.LogBuffer import com.android.systemui.log.LogLevel +import com.android.systemui.temporarydisplay.TemporaryViewLogger /** * A logger for media tap-to-transfer events. * - * @property deviceTypeTag the type of device triggering the logs -- "Sender" or "Receiver". + * @param deviceTypeTag the type of device triggering the logs -- "Sender" or "Receiver". */ class MediaTttLogger( - private val deviceTypeTag: String, - private val buffer: LogBuffer -){ + deviceTypeTag: String, + buffer: LogBuffer +) : TemporaryViewLogger(buffer, BASE_TAG + deviceTypeTag) { /** Logs a change in the chip state for the given [mediaRouteId]. */ - fun logStateChange(stateName: String, mediaRouteId: String) { + fun logStateChange(stateName: String, mediaRouteId: String, packageName: String?) { buffer.log( - BASE_TAG + deviceTypeTag, + tag, LogLevel.DEBUG, { str1 = stateName str2 = mediaRouteId + str3 = packageName }, - { "State changed to $str1 for ID=$str2" } + { "State changed to $str1 for ID=$str2 package=$str3" } ) } - /** Logs that we removed the chip for the given [reason]. */ - fun logChipRemoval(reason: String) { + /** Logs that we couldn't find information for [packageName]. */ + fun logPackageNotFound(packageName: String) { buffer.log( - BASE_TAG + deviceTypeTag, + tag, LogLevel.DEBUG, - { str1 = reason }, - { "Chip removed due to $str1" } + { str1 = packageName }, + { "Package $str1 could not be found" } ) } + + /** + * Logs that a removal request has been bypassed (ignored). + * + * @param removalReason the reason that the chip removal was requested. + * @param bypassReason the reason that the request was bypassed. + */ + fun logRemovalBypass(removalReason: String, bypassReason: String) { + buffer.log( + tag, + LogLevel.DEBUG, + { + str1 = removalReason + str2 = bypassReason + }, + { "Chip removal requested due to $str1; however, removal was ignored because $str2" }) + } } private const val BASE_TAG = "MediaTtt" diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttUtils.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttUtils.kt new file mode 100644 index 000000000000..792ae7ca6049 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/MediaTttUtils.kt @@ -0,0 +1,112 @@ +/* + * 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.media.taptotransfer.common + +import android.content.Context +import android.content.pm.PackageManager +import android.graphics.drawable.Drawable +import com.android.internal.widget.CachingIconView +import com.android.settingslib.Utils +import com.android.systemui.R + +/** Utility methods for media tap-to-transfer. */ +class MediaTttUtils { + companion object { + // Used in CTS tests UpdateMediaTapToTransferSenderDisplayTest and + // UpdateMediaTapToTransferReceiverDisplayTest + const val WINDOW_TITLE = "Media Transfer Chip View" + const val WAKE_REASON = "MEDIA_TRANSFER_ACTIVATED" + + /** + * Returns the information needed to display the icon. + * + * The information will either contain app name and icon of the app playing media, or a + * default name and icon if we can't find the app name/icon. + * + * @param appPackageName the package name of the app playing the media. + * @param logger the logger to use for any errors. + */ + fun getIconInfoFromPackageName( + context: Context, + appPackageName: String?, + logger: MediaTttLogger + ): IconInfo { + if (appPackageName != null) { + try { + val contentDescription = + context.packageManager + .getApplicationInfo( + appPackageName, + PackageManager.ApplicationInfoFlags.of(0) + ) + .loadLabel(context.packageManager) + .toString() + return IconInfo( + contentDescription, + drawable = context.packageManager.getApplicationIcon(appPackageName), + isAppIcon = true + ) + } catch (e: PackageManager.NameNotFoundException) { + logger.logPackageNotFound(appPackageName) + } + } + return IconInfo( + contentDescription = + context.getString(R.string.media_output_dialog_unknown_launch_app_name), + drawable = + context.resources.getDrawable(R.drawable.ic_cast).apply { + this.setTint( + Utils.getColorAttrDefaultColor(context, android.R.attr.textColorPrimary) + ) + }, + isAppIcon = false + ) + } + + /** + * Sets an icon to be displayed by the given view. + * + * @param iconSize the size in pixels that the icon should be. If null, the size of + * [appIconView] will not be adjusted. + */ + fun setIcon( + appIconView: CachingIconView, + icon: Drawable, + iconContentDescription: CharSequence, + iconSize: Int? = null, + ) { + iconSize?.let { size -> + val lp = appIconView.layoutParams + lp.width = size + lp.height = size + appIconView.layoutParams = lp + } + + appIconView.contentDescription = iconContentDescription + appIconView.setImageDrawable(icon) + } + } +} + +data class IconInfo( + val contentDescription: String, + val drawable: Drawable, + /** + * True if [drawable] is the app's icon, and false if [drawable] is some generic default icon. + */ + val isAppIcon: Boolean +) diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt index 35a6c74518e0..dfd9e22c14b1 100644 --- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt +++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiver.kt @@ -34,15 +34,15 @@ import com.android.settingslib.Utils import com.android.systemui.R import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Main -import com.android.systemui.media.taptotransfer.common.ChipInfoCommon -import com.android.systemui.media.taptotransfer.common.DEFAULT_TIMEOUT_MILLIS -import com.android.systemui.media.taptotransfer.common.MediaTttChipControllerCommon import com.android.systemui.media.taptotransfer.common.MediaTttLogger +import com.android.systemui.media.taptotransfer.common.MediaTttUtils import com.android.systemui.statusbar.CommandQueue import com.android.systemui.statusbar.policy.ConfigurationController +import com.android.systemui.temporarydisplay.DEFAULT_TIMEOUT_MILLIS +import com.android.systemui.temporarydisplay.TemporaryViewDisplayController +import com.android.systemui.temporarydisplay.TemporaryViewInfo import com.android.systemui.util.animation.AnimationUtil.Companion.frames import com.android.systemui.util.concurrency.DelayableExecutor -import com.android.systemui.util.view.ViewUtil import javax.inject.Inject /** @@ -56,23 +56,23 @@ class MediaTttChipControllerReceiver @Inject constructor( context: Context, @MediaTttReceiverLogger logger: MediaTttLogger, windowManager: WindowManager, - viewUtil: ViewUtil, mainExecutor: DelayableExecutor, accessibilityManager: AccessibilityManager, configurationController: ConfigurationController, powerManager: PowerManager, @Main private val mainHandler: Handler, private val uiEventLogger: MediaTttReceiverUiEventLogger, -) : MediaTttChipControllerCommon<ChipReceiverInfo>( +) : TemporaryViewDisplayController<ChipReceiverInfo, MediaTttLogger>( context, logger, windowManager, - viewUtil, mainExecutor, accessibilityManager, configurationController, powerManager, R.layout.media_ttt_chip_receiver, + MediaTttUtils.WINDOW_TITLE, + MediaTttUtils.WAKE_REASON, ) { @SuppressLint("WrongConstant") // We're allowed to use LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS override val windowLayoutParams = commonWindowLayoutParams.apply { @@ -110,7 +110,7 @@ class MediaTttChipControllerReceiver @Inject constructor( ) { val chipState: ChipStateReceiver? = ChipStateReceiver.getReceiverStateFromId(displayState) val stateName = chipState?.name ?: "Invalid" - logger.logStateChange(stateName, routeInfo.id) + logger.logStateChange(stateName, routeInfo.id, routeInfo.clientPackageName) if (chipState == null) { Log.e(RECEIVER_TAG, "Unhandled MediaTransferReceiverState $displayState") @@ -119,18 +119,18 @@ class MediaTttChipControllerReceiver @Inject constructor( uiEventLogger.logReceiverStateChange(chipState) if (chipState == ChipStateReceiver.FAR_FROM_SENDER) { - removeChip(removalReason = ChipStateReceiver.FAR_FROM_SENDER::class.simpleName!!) + removeView(removalReason = ChipStateReceiver.FAR_FROM_SENDER::class.simpleName!!) return } if (appIcon == null) { - displayChip(ChipReceiverInfo(routeInfo, appIconDrawableOverride = null, appName)) + displayView(ChipReceiverInfo(routeInfo, appIconDrawableOverride = null, appName)) return } appIcon.loadDrawableAsync( context, Icon.OnDrawableLoadedListener { drawable -> - displayChip(ChipReceiverInfo(routeInfo, drawable, appName)) + displayView(ChipReceiverInfo(routeInfo, drawable, appName)) }, // Notify the listener on the main handler since the listener will update // the UI. @@ -138,19 +138,32 @@ class MediaTttChipControllerReceiver @Inject constructor( ) } - override fun updateChipView(newChipInfo: ChipReceiverInfo, currentChipView: ViewGroup) { - super.updateChipView(newChipInfo, currentChipView) - val iconName = setIcon( - currentChipView, - newChipInfo.routeInfo.clientPackageName, - newChipInfo.appIconDrawableOverride, - newChipInfo.appNameOverride + override fun updateView(newInfo: ChipReceiverInfo, currentView: ViewGroup) { + super.updateView(newInfo, currentView) + + val iconInfo = MediaTttUtils.getIconInfoFromPackageName( + context, newInfo.routeInfo.clientPackageName, logger + ) + val iconDrawable = newInfo.appIconDrawableOverride ?: iconInfo.drawable + val iconContentDescription = newInfo.appNameOverride ?: iconInfo.contentDescription + val iconSize = context.resources.getDimensionPixelSize( + if (iconInfo.isAppIcon) { + R.dimen.media_ttt_icon_size_receiver + } else { + R.dimen.media_ttt_generic_icon_size_receiver + } + ) + + MediaTttUtils.setIcon( + currentView.requireViewById(R.id.app_icon), + iconDrawable, + iconContentDescription, + iconSize, ) - currentChipView.contentDescription = iconName } - override fun animateChipIn(chipView: ViewGroup) { - val appIconView = chipView.requireViewById<View>(R.id.app_icon) + override fun animateViewIn(view: ViewGroup) { + val appIconView = view.requireViewById<View>(R.id.app_icon) appIconView.animate() .translationYBy(-1 * getTranslationAmount().toFloat()) .setDuration(30.frames) @@ -160,19 +173,10 @@ class MediaTttChipControllerReceiver @Inject constructor( .setDuration(5.frames) .start() // Using withEndAction{} doesn't apply a11y focus when screen is unlocked. - appIconView.postOnAnimation { chipView.requestAccessibilityFocus() } - startRipple(chipView.requireViewById(R.id.ripple)) + appIconView.postOnAnimation { view.requestAccessibilityFocus() } + startRipple(view.requireViewById(R.id.ripple)) } - override fun getIconSize(isAppIcon: Boolean): Int? = - context.resources.getDimensionPixelSize( - if (isAppIcon) { - R.dimen.media_ttt_icon_size_receiver - } else { - R.dimen.media_ttt_generic_icon_size_receiver - } - ) - /** Returns the amount that the chip will be translated by in its intro animation. */ private fun getTranslationAmount(): Int { return context.resources.getDimensionPixelSize(R.dimen.media_ttt_receiver_vert_translation) @@ -216,7 +220,7 @@ data class ChipReceiverInfo( val routeInfo: MediaRoute2Info, val appIconDrawableOverride: Drawable?, val appNameOverride: CharSequence? -) : ChipInfoCommon { +) : TemporaryViewInfo { override fun getTimeoutMs() = DEFAULT_TIMEOUT_MILLIS } diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/ChipStateSender.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/ChipStateSender.kt index a153cb6c0d31..4379d25406bf 100644 --- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/ChipStateSender.kt +++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/ChipStateSender.kt @@ -25,7 +25,7 @@ import androidx.annotation.StringRes import com.android.internal.logging.UiEventLogger import com.android.internal.statusbar.IUndoMediaTransferCallback import com.android.systemui.R -import com.android.systemui.media.taptotransfer.common.DEFAULT_TIMEOUT_MILLIS +import com.android.systemui.temporarydisplay.DEFAULT_TIMEOUT_MILLIS /** * A class enumerating all the possible states of the media tap-to-transfer chip on the sender @@ -34,8 +34,7 @@ import com.android.systemui.media.taptotransfer.common.DEFAULT_TIMEOUT_MILLIS * @property stateInt the integer from [StatusBarManager] corresponding with this state. * @property stringResId the res ID of the string that should be displayed in the chip. Null if the * state should not have the chip be displayed. - * @property isMidTransfer true if the state represents that a transfer is currently ongoing. - * @property isTransferFailure true if the state represents that the transfer has failed. + * @property transferStatus the transfer status that the chip state represents. * @property timeout the amount of time this chip should display on the screen before it times out * and disappears. */ @@ -43,8 +42,7 @@ enum class ChipStateSender( @StatusBarManager.MediaTransferSenderState val stateInt: Int, val uiEvent: UiEventLogger.UiEventEnum, @StringRes val stringResId: Int?, - val isMidTransfer: Boolean = false, - val isTransferFailure: Boolean = false, + val transferStatus: TransferStatus, val timeout: Long = DEFAULT_TIMEOUT_MILLIS ) { /** @@ -56,6 +54,7 @@ enum class ChipStateSender( StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_ALMOST_CLOSE_TO_START_CAST, MediaTttSenderUiEvents.MEDIA_TTT_SENDER_ALMOST_CLOSE_TO_START_CAST, R.string.media_move_closer_to_start_cast, + transferStatus = TransferStatus.NOT_STARTED, ), /** @@ -68,6 +67,7 @@ enum class ChipStateSender( StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_ALMOST_CLOSE_TO_END_CAST, MediaTttSenderUiEvents.MEDIA_TTT_SENDER_ALMOST_CLOSE_TO_END_CAST, R.string.media_move_closer_to_end_cast, + transferStatus = TransferStatus.NOT_STARTED, ), /** @@ -78,7 +78,7 @@ enum class ChipStateSender( StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_TRIGGERED, MediaTttSenderUiEvents.MEDIA_TTT_SENDER_TRANSFER_TO_RECEIVER_TRIGGERED, R.string.media_transfer_playing_different_device, - isMidTransfer = true, + transferStatus = TransferStatus.IN_PROGRESS, timeout = TRANSFER_TRIGGERED_TIMEOUT_MILLIS ), @@ -90,7 +90,7 @@ enum class ChipStateSender( StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_TRIGGERED, MediaTttSenderUiEvents.MEDIA_TTT_SENDER_TRANSFER_TO_THIS_DEVICE_TRIGGERED, R.string.media_transfer_playing_this_device, - isMidTransfer = true, + transferStatus = TransferStatus.IN_PROGRESS, timeout = TRANSFER_TRIGGERED_TIMEOUT_MILLIS ), @@ -100,7 +100,8 @@ enum class ChipStateSender( TRANSFER_TO_RECEIVER_SUCCEEDED( StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_SUCCEEDED, MediaTttSenderUiEvents.MEDIA_TTT_SENDER_TRANSFER_TO_RECEIVER_SUCCEEDED, - R.string.media_transfer_playing_different_device + R.string.media_transfer_playing_different_device, + transferStatus = TransferStatus.SUCCEEDED, ) { override fun undoClickListener( controllerSender: MediaTttChipControllerSender, @@ -120,7 +121,7 @@ enum class ChipStateSender( // state, but that may take too long to go through the binder and the user may be // confused ast o why the UI hasn't changed yet. So, we immediately change the UI // here. - controllerSender.displayChip( + controllerSender.displayView( ChipSenderInfo( TRANSFER_TO_THIS_DEVICE_TRIGGERED, routeInfo, undoCallback ) @@ -135,7 +136,8 @@ enum class ChipStateSender( TRANSFER_TO_THIS_DEVICE_SUCCEEDED( StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_SUCCEEDED, MediaTttSenderUiEvents.MEDIA_TTT_SENDER_TRANSFER_TO_THIS_DEVICE_SUCCEEDED, - R.string.media_transfer_playing_this_device + R.string.media_transfer_playing_this_device, + transferStatus = TransferStatus.SUCCEEDED, ) { override fun undoClickListener( controllerSender: MediaTttChipControllerSender, @@ -155,7 +157,7 @@ enum class ChipStateSender( // state, but that may take too long to go through the binder and the user may be // confused as to why the UI hasn't changed yet. So, we immediately change the UI // here. - controllerSender.displayChip( + controllerSender.displayView( ChipSenderInfo( TRANSFER_TO_RECEIVER_TRIGGERED, routeInfo, undoCallback ) @@ -169,7 +171,7 @@ enum class ChipStateSender( StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_RECEIVER_FAILED, MediaTttSenderUiEvents.MEDIA_TTT_SENDER_TRANSFER_TO_RECEIVER_FAILED, R.string.media_transfer_failed, - isTransferFailure = true + transferStatus = TransferStatus.FAILED, ), /** A state representing that a transfer back to this device has failed. */ @@ -177,14 +179,15 @@ enum class ChipStateSender( StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_TRANSFER_TO_THIS_DEVICE_FAILED, MediaTttSenderUiEvents.MEDIA_TTT_SENDER_TRANSFER_TO_THIS_DEVICE_FAILED, R.string.media_transfer_failed, - isTransferFailure = true + transferStatus = TransferStatus.FAILED, ), /** A state representing that this device is far away from any receiver device. */ FAR_FROM_RECEIVER( StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_FAR_FROM_RECEIVER, MediaTttSenderUiEvents.MEDIA_TTT_SENDER_FAR_FROM_RECEIVER, - stringResId = null + stringResId = null, + transferStatus = TransferStatus.TOO_FAR, ); /** diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSender.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSender.kt index 933548963390..e539f3fd842d 100644 --- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSender.kt +++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSender.kt @@ -33,14 +33,14 @@ import com.android.systemui.animation.Interpolators import com.android.systemui.animation.ViewHierarchyAnimator import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Main -import com.android.systemui.media.taptotransfer.common.ChipInfoCommon -import com.android.systemui.media.taptotransfer.common.MediaTttChipControllerCommon import com.android.systemui.media.taptotransfer.common.MediaTttLogger -import com.android.systemui.media.taptotransfer.common.MediaTttRemovalReason +import com.android.systemui.media.taptotransfer.common.MediaTttUtils import com.android.systemui.statusbar.CommandQueue import com.android.systemui.statusbar.policy.ConfigurationController +import com.android.systemui.temporarydisplay.TemporaryDisplayRemovalReason +import com.android.systemui.temporarydisplay.TemporaryViewDisplayController +import com.android.systemui.temporarydisplay.TemporaryViewInfo import com.android.systemui.util.concurrency.DelayableExecutor -import com.android.systemui.util.view.ViewUtil import javax.inject.Inject /** @@ -53,22 +53,22 @@ class MediaTttChipControllerSender @Inject constructor( context: Context, @MediaTttSenderLogger logger: MediaTttLogger, windowManager: WindowManager, - viewUtil: ViewUtil, @Main mainExecutor: DelayableExecutor, accessibilityManager: AccessibilityManager, configurationController: ConfigurationController, powerManager: PowerManager, private val uiEventLogger: MediaTttSenderUiEventLogger -) : MediaTttChipControllerCommon<ChipSenderInfo>( +) : TemporaryViewDisplayController<ChipSenderInfo, MediaTttLogger>( context, logger, windowManager, - viewUtil, mainExecutor, accessibilityManager, configurationController, powerManager, R.layout.media_ttt_chip, + MediaTttUtils.WINDOW_TITLE, + MediaTttUtils.WAKE_REASON, ) { override val windowLayoutParams = commonWindowLayoutParams.apply { gravity = Gravity.TOP.or(Gravity.CENTER_HORIZONTAL) @@ -97,7 +97,7 @@ class MediaTttChipControllerSender @Inject constructor( ) { val chipState: ChipStateSender? = ChipStateSender.getSenderStateFromId(displayState) val stateName = chipState?.name ?: "Invalid" - logger.logStateChange(stateName, routeInfo.id) + logger.logStateChange(stateName, routeInfo.id, routeInfo.clientPackageName) if (chipState == null) { Log.e(SENDER_TAG, "Unhandled MediaTransferSenderState $displayState") @@ -106,53 +106,59 @@ class MediaTttChipControllerSender @Inject constructor( uiEventLogger.logSenderStateChange(chipState) if (chipState == ChipStateSender.FAR_FROM_RECEIVER) { - removeChip(removalReason = ChipStateSender.FAR_FROM_RECEIVER::class.simpleName!!) + removeView(removalReason = ChipStateSender.FAR_FROM_RECEIVER.name) } else { - displayChip(ChipSenderInfo(chipState, routeInfo, undoCallback)) + displayView(ChipSenderInfo(chipState, routeInfo, undoCallback)) } } - /** Displays the chip view for the given state. */ - override fun updateChipView( - newChipInfo: ChipSenderInfo, - currentChipView: ViewGroup + override fun updateView( + newInfo: ChipSenderInfo, + currentView: ViewGroup ) { - super.updateChipView(newChipInfo, currentChipView) + super.updateView(newInfo, currentView) - val chipState = newChipInfo.state + val chipState = newInfo.state // App icon - val iconName = setIcon(currentChipView, newChipInfo.routeInfo.clientPackageName) + val iconInfo = MediaTttUtils.getIconInfoFromPackageName( + context, newInfo.routeInfo.clientPackageName, logger + ) + MediaTttUtils.setIcon( + currentView.requireViewById(R.id.app_icon), + iconInfo.drawable, + iconInfo.contentDescription + ) // Text - val otherDeviceName = newChipInfo.routeInfo.name.toString() + val otherDeviceName = newInfo.routeInfo.name.toString() val chipText = chipState.getChipTextString(context, otherDeviceName) - currentChipView.requireViewById<TextView>(R.id.text).text = chipText + currentView.requireViewById<TextView>(R.id.text).text = chipText // Loading - currentChipView.requireViewById<View>(R.id.loading).visibility = - chipState.isMidTransfer.visibleIfTrue() + currentView.requireViewById<View>(R.id.loading).visibility = + (chipState.transferStatus == TransferStatus.IN_PROGRESS).visibleIfTrue() // Undo - val undoView = currentChipView.requireViewById<View>(R.id.undo) + val undoView = currentView.requireViewById<View>(R.id.undo) val undoClickListener = chipState.undoClickListener( - this, newChipInfo.routeInfo, newChipInfo.undoCallback, uiEventLogger + this, newInfo.routeInfo, newInfo.undoCallback, uiEventLogger ) undoView.setOnClickListener(undoClickListener) undoView.visibility = (undoClickListener != null).visibleIfTrue() // Failure - currentChipView.requireViewById<View>(R.id.failure_icon).visibility = - chipState.isTransferFailure.visibleIfTrue() + currentView.requireViewById<View>(R.id.failure_icon).visibility = + (chipState.transferStatus == TransferStatus.FAILED).visibleIfTrue() // For accessibility - currentChipView.requireViewById<ViewGroup>( + currentView.requireViewById<ViewGroup>( R.id.media_ttt_sender_chip_inner - ).contentDescription = "$iconName $chipText" + ).contentDescription = "${iconInfo.contentDescription} $chipText" } - override fun animateChipIn(chipView: ViewGroup) { - val chipInnerView = chipView.requireViewById<ViewGroup>(R.id.media_ttt_sender_chip_inner) + override fun animateViewIn(view: ViewGroup) { + val chipInnerView = view.requireViewById<ViewGroup>(R.id.media_ttt_sender_chip_inner) ViewHierarchyAnimator.animateAddition( chipInnerView, ViewHierarchyAnimator.Hotspot.TOP, @@ -165,14 +171,21 @@ class MediaTttChipControllerSender @Inject constructor( ) } - override fun removeChip(removalReason: String) { - // Don't remove the chip if we're mid-transfer since the user should still be able to - // see the status of the transfer. (But do remove it if it's finally timed out.) - if (chipInfo?.state?.isMidTransfer == true && - removalReason != MediaTttRemovalReason.REASON_TIMEOUT) { + override fun removeView(removalReason: String) { + // Don't remove the chip if we're in progress or succeeded, since the user should still be + // able to see the status of the transfer. (But do remove it if it's finally timed out.) + val transferStatus = info?.state?.transferStatus + if ( + (transferStatus == TransferStatus.IN_PROGRESS || + transferStatus == TransferStatus.SUCCEEDED) && + removalReason != TemporaryDisplayRemovalReason.REASON_TIMEOUT + ) { + logger.logRemovalBypass( + removalReason, bypassReason = "transferStatus=${transferStatus.name}" + ) return } - super.removeChip(removalReason) + super.removeView(removalReason) } private fun Boolean.visibleIfTrue(): Int { @@ -188,7 +201,7 @@ data class ChipSenderInfo( val state: ChipStateSender, val routeInfo: MediaRoute2Info, val undoCallback: IUndoMediaTransferCallback? = null -) : ChipInfoCommon { +) : TemporaryViewInfo { override fun getTimeoutMs() = state.timeout } diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/TransferStatus.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/TransferStatus.kt new file mode 100644 index 000000000000..f15720df5245 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/sender/TransferStatus.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.media.taptotransfer.sender + +/** Represents the different possible transfer states that we could be in. */ +enum class TransferStatus { + /** The transfer hasn't started yet. */ + NOT_STARTED, + /** The transfer is currently ongoing but hasn't completed yet. */ + IN_PROGRESS, + /** The transfer has completed successfully. */ + SUCCEEDED, + /** The transfer has completed with a failure. */ + FAILED, + /** The device is too far away to do a transfer. */ + TOO_FAR, +} diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java index 75e48d2220c8..30947e839f0a 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java @@ -35,7 +35,6 @@ import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL; import static com.android.internal.accessibility.common.ShortcutConstants.CHOOSER_PACKAGE_NAME; import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.HOME_BUTTON_LONG_PRESS_DURATION_MS; -import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.NAV_BAR_HANDLE_FORCE_OPAQUE; import static com.android.systemui.navigationbar.NavBarHelper.transitionMode; import static com.android.systemui.recents.OverviewProxyService.OverviewProxyListener; import static com.android.systemui.shared.recents.utilities.Utilities.isTablet; @@ -229,10 +228,7 @@ public class NavigationBar extends ViewController<NavigationBarView> implements private Locale mLocale; private int mLayoutDirection; - private boolean mAllowForceNavBarHandleOpaque; - private boolean mForceNavBarHandleOpaque; private Optional<Long> mHomeButtonLongPressDurationMs; - private boolean mIsCurrentUserSetup; /** @see android.view.WindowInsetsController#setSystemBarsAppearance(int, int) */ private @Appearance int mAppearance; @@ -379,37 +375,6 @@ public class NavigationBar extends ViewController<NavigationBarView> implements } @Override - public void onNavBarButtonAlphaChanged(float alpha, boolean animate) { - if (!mIsCurrentUserSetup) { - // If the current user is not yet setup, then don't update any button alphas - return; - } - if (QuickStepContract.isLegacyMode(mNavBarMode)) { - // Don't allow the bar buttons to be affected by the alpha - return; - } - - ButtonDispatcher buttonDispatcher = null; - boolean forceVisible = false; - if (QuickStepContract.isGesturalMode(mNavBarMode)) { - // Disallow home handle animations when in gestural - animate = false; - forceVisible = mAllowForceNavBarHandleOpaque && mForceNavBarHandleOpaque; - buttonDispatcher = mView.getHomeHandle(); - if (getBarTransitions() != null) { - getBarTransitions().setBackgroundOverrideAlpha(alpha); - } - } else if (QuickStepContract.isSwipeUpMode(mNavBarMode)) { - buttonDispatcher = mView.getBackButton(); - } - if (buttonDispatcher != null) { - buttonDispatcher.setVisibility( - (forceVisible || alpha > 0) ? View.VISIBLE : View.INVISIBLE); - buttonDispatcher.setAlpha(forceVisible ? 1f : alpha, animate); - } - } - - @Override public void onHomeRotationEnabled(boolean enabled) { mView.getRotationButtonController().setHomeRotationEnabled(enabled); } @@ -456,15 +421,10 @@ public class NavigationBar extends ViewController<NavigationBarView> implements new DeviceConfig.OnPropertiesChangedListener() { @Override public void onPropertiesChanged(DeviceConfig.Properties properties) { - if (properties.getKeyset().contains(NAV_BAR_HANDLE_FORCE_OPAQUE)) { - mForceNavBarHandleOpaque = properties.getBoolean( - NAV_BAR_HANDLE_FORCE_OPAQUE, /* defaultValue = */ true); - } - if (properties.getKeyset().contains(HOME_BUTTON_LONG_PRESS_DURATION_MS)) { mHomeButtonLongPressDurationMs = Optional.of( - properties.getLong(HOME_BUTTON_LONG_PRESS_DURATION_MS, 0) - ).filter(duration -> duration != 0); + properties.getLong(HOME_BUTTON_LONG_PRESS_DURATION_MS, 0)) + .filter(duration -> duration != 0); if (mView != null) { reconfigureHomeLongClick(); } @@ -472,14 +432,6 @@ public class NavigationBar extends ViewController<NavigationBarView> implements } }; - private final DeviceProvisionedController.DeviceProvisionedListener mUserSetupListener = - new DeviceProvisionedController.DeviceProvisionedListener() { - @Override - public void onUserSetupChanged() { - mIsCurrentUserSetup = mDeviceProvisionedController.isCurrentUserSetup(); - } - }; - private final NotificationShadeDepthController.DepthListener mDepthListener = new NotificationShadeDepthController.DepthListener() { boolean mHasBlurs; @@ -660,12 +612,6 @@ public class NavigationBar extends ViewController<NavigationBarView> implements mCommandQueue.addCallback(this); mLongPressHomeEnabled = mNavBarHelper.getLongPressHomeEnabled(); mNavBarHelper.init(); - mAllowForceNavBarHandleOpaque = mContext.getResources().getBoolean( - R.bool.allow_force_nav_bar_handle_opaque); - mForceNavBarHandleOpaque = mDeviceConfigProxy.getBoolean( - DeviceConfig.NAMESPACE_SYSTEMUI, - NAV_BAR_HANDLE_FORCE_OPAQUE, - /* defaultValue = */ true); mHomeButtonLongPressDurationMs = Optional.of(mDeviceConfigProxy.getLong( DeviceConfig.NAMESPACE_SYSTEMUI, HOME_BUTTON_LONG_PRESS_DURATION_MS, @@ -685,8 +631,6 @@ public class NavigationBar extends ViewController<NavigationBarView> implements // Respect the latest disabled-flags. mCommandQueue.recomputeDisableFlags(mDisplayId, false); - mIsCurrentUserSetup = mDeviceProvisionedController.isCurrentUserSetup(); - mDeviceProvisionedController.addCallback(mUserSetupListener); mNotificationShadeDepthController.addListener(mDepthListener); } @@ -698,7 +642,6 @@ public class NavigationBar extends ViewController<NavigationBarView> implements mNavBarHelper.removeNavTaskStateUpdater(mNavbarTaskbarStateUpdater); mNavBarHelper.destroy(); - mDeviceProvisionedController.removeCallback(mUserSetupListener); mNotificationShadeDepthController.removeListener(mDepthListener); mDeviceConfigProxy.removeOnPropertiesChangedListener(mOnPropertiesChangedListener); diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java index 9e1ba5f723a3..97024881ca62 100644 --- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java +++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarView.java @@ -39,6 +39,7 @@ import android.graphics.Canvas; import android.graphics.Point; import android.graphics.Rect; import android.os.Bundle; +import android.os.RemoteException; import android.util.AttributeSet; import android.util.Log; import android.util.SparseArray; @@ -51,6 +52,7 @@ import android.view.ViewGroup; import android.view.WindowInsets; import android.view.WindowInsetsController.Behavior; import android.view.WindowManager; +import android.view.WindowManagerGlobal; import android.view.accessibility.AccessibilityNodeInfo; import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; import android.widget.FrameLayout; @@ -78,7 +80,6 @@ import com.android.systemui.shared.rotation.RotationButton.RotationButtonUpdates import com.android.systemui.shared.rotation.RotationButtonController; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.QuickStepContract; -import com.android.systemui.shared.system.WindowManagerWrapper; import com.android.systemui.statusbar.phone.AutoHideController; import com.android.systemui.statusbar.phone.CentralSurfaces; import com.android.systemui.statusbar.phone.LightBarTransitionsController; @@ -775,13 +776,24 @@ public class NavigationBarView extends FrameLayout { updateSlippery(); reloadNavIcons(); updateNavButtonIcons(); - mBgExecutor.execute(() -> WindowManagerWrapper.getInstance() - .setNavBarVirtualKeyHapticFeedbackEnabled(!mShowSwipeUpUi)); + mBgExecutor.execute(() -> setNavBarVirtualKeyHapticFeedbackEnabled(!mShowSwipeUpUi)); getHomeButton().setAccessibilityDelegate( mShowSwipeUpUi ? mQuickStepAccessibilityDelegate : null); } /** + * Enable or disable haptic feedback on the navigation bar buttons. + */ + private void setNavBarVirtualKeyHapticFeedbackEnabled(boolean enabled) { + try { + WindowManagerGlobal.getWindowManagerService() + .setNavBarVirtualKeyHapticFeedbackEnabled(enabled); + } catch (RemoteException e) { + Log.w(TAG, "Failed to enable or disable navigation bar button haptics: ", e); + } + } + + /** * Updates the {@link WindowManager.LayoutParams.FLAG_SLIPPERY} state dependent on if swipe up * is enabled, or the notifications is fully opened without being in an animated state. If * slippery is enabled, touch events will leave the nav bar window and enter into the fullscreen diff --git a/packages/SystemUI/src/com/android/systemui/power/dagger/PowerModule.java b/packages/SystemUI/src/com/android/systemui/power/dagger/PowerModule.java index 3709a86f2fa5..7184fa0685af 100644 --- a/packages/SystemUI/src/com/android/systemui/power/dagger/PowerModule.java +++ b/packages/SystemUI/src/com/android/systemui/power/dagger/PowerModule.java @@ -20,13 +20,18 @@ import com.android.systemui.power.EnhancedEstimates; import com.android.systemui.power.EnhancedEstimatesImpl; import com.android.systemui.power.PowerNotificationWarnings; import com.android.systemui.power.PowerUI; +import com.android.systemui.power.data.repository.PowerRepositoryModule; import dagger.Binds; import dagger.Module; /** Dagger Module for code in the power package. */ -@Module +@Module( + includes = { + PowerRepositoryModule.class, + } +) public interface PowerModule { /** */ @Binds diff --git a/packages/SystemUI/src/com/android/systemui/power/data/repository/PowerRepository.kt b/packages/SystemUI/src/com/android/systemui/power/data/repository/PowerRepository.kt new file mode 100644 index 000000000000..b2e04bb4f26f --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/power/data/repository/PowerRepository.kt @@ -0,0 +1,74 @@ +/* + * 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.power.data.repository + +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import android.content.IntentFilter +import android.os.PowerManager +import com.android.systemui.broadcast.BroadcastDispatcher +import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging +import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow +import com.android.systemui.dagger.SysUISingleton +import javax.inject.Inject +import kotlinx.coroutines.channels.awaitClose +import kotlinx.coroutines.flow.Flow + +/** Defines interface for classes that act as source of truth for power-related data. */ +interface PowerRepository { + /** Whether the device is interactive. Starts with the current state. */ + val isInteractive: Flow<Boolean> +} + +@SysUISingleton +class PowerRepositoryImpl +@Inject +constructor( + manager: PowerManager, + dispatcher: BroadcastDispatcher, +) : PowerRepository { + + override val isInteractive: Flow<Boolean> = conflatedCallbackFlow { + fun send() { + trySendWithFailureLogging(manager.isInteractive, TAG) + } + + val receiver = + object : BroadcastReceiver() { + override fun onReceive(context: Context?, intent: Intent?) { + send() + } + } + + dispatcher.registerReceiver( + receiver, + IntentFilter().apply { + addAction(Intent.ACTION_SCREEN_ON) + addAction(Intent.ACTION_SCREEN_OFF) + }, + ) + send() + + awaitClose { dispatcher.unregisterReceiver(receiver) } + } + + companion object { + private const val TAG = "PowerRepository" + } +} diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ContextUtils.java b/packages/SystemUI/src/com/android/systemui/power/data/repository/PowerRepositoryModule.kt index 1de740a083c2..491da65c0291 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/ContextUtils.java +++ b/packages/SystemUI/src/com/android/systemui/power/data/repository/PowerRepositoryModule.kt @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 The Android Open Source Project + * 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. @@ -12,17 +12,15 @@ * 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.shared.system; - -import android.annotation.UserIdInt; -import android.content.Context; +package com.android.systemui.power.data.repository -public class ContextUtils { +import dagger.Binds +import dagger.Module - /** Get the user associated with this context */ - public static @UserIdInt int getUserId(Context context) { - return context.getUserId(); - } +@Module +interface PowerRepositoryModule { + @Binds fun bindRepository(impl: PowerRepositoryImpl): PowerRepository } diff --git a/packages/SystemUI/src/com/android/systemui/power/domain/interactor/PowerInteractor.kt b/packages/SystemUI/src/com/android/systemui/power/domain/interactor/PowerInteractor.kt new file mode 100644 index 000000000000..3f799f724fe7 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/power/domain/interactor/PowerInteractor.kt @@ -0,0 +1,34 @@ +/* + * 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.power.domain.interactor + +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.power.data.repository.PowerRepository +import javax.inject.Inject +import kotlinx.coroutines.flow.Flow + +/** Hosts business logic for interacting with the power system. */ +@SysUISingleton +class PowerInteractor +@Inject +constructor( + repository: PowerRepository, +) { + /** Whether the screen is on or off. */ + val isInteractive: Flow<Boolean> = repository.isInteractive +} diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java index 56298fa155fa..e1289a61d45d 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java @@ -16,6 +16,7 @@ package com.android.systemui.qs; import android.animation.TimeInterpolator; import android.animation.ValueAnimator; +import android.annotation.NonNull; import android.util.Log; import android.util.Pair; import android.util.SparseArray; @@ -30,15 +31,11 @@ import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.plugins.qs.QS; import com.android.systemui.plugins.qs.QSTile; import com.android.systemui.plugins.qs.QSTileView; -import com.android.systemui.qs.PagedTileLayout.PageListener; -import com.android.systemui.qs.QSHost.Callback; import com.android.systemui.qs.QSPanel.QSTileLayout; import com.android.systemui.qs.TouchAnimator.Builder; -import com.android.systemui.qs.TouchAnimator.Listener; import com.android.systemui.qs.dagger.QSScope; import com.android.systemui.qs.tileimpl.HeightOverrideable; import com.android.systemui.tuner.TunerService; -import com.android.systemui.tuner.TunerService.Tunable; import java.util.ArrayList; import java.util.Collection; @@ -47,16 +44,26 @@ import java.util.concurrent.Executor; import javax.inject.Inject; -/** */ +/** + * Performs the animated transition between the QQS and QS views. + * + * <p>The transition is driven externally via {@link #setPosition(float)}, where 0 is a fully + * collapsed QQS and one a fully expanded QS. + * + * <p>This implementation maintains a set of {@code TouchAnimator} to transition the properties of + * views both in QQS and QS. These {@code TouchAnimator} are re-created lazily if contents of either + * view change, see {@link #requestAnimatorUpdate()}. + * + * <p>During the transition, both QS and QQS are visible. For overlapping tiles (Whenever the QS + * shows the first page), the corresponding QS tiles are hidden until QS is fully expanded. + */ @QSScope -public class QSAnimator implements Callback, PageListener, Listener, OnLayoutChangeListener, - OnAttachStateChangeListener, Tunable { +public class QSAnimator implements QSHost.Callback, PagedTileLayout.PageListener, + TouchAnimator.Listener, OnLayoutChangeListener, + OnAttachStateChangeListener { private static final String TAG = "QSAnimator"; - private static final String ALLOW_FANCY_ANIMATION = "sysui_qs_fancy_anim"; - private static final String MOVE_FULL_ROWS = "sysui_qs_move_whole_rows"; - private static final float EXPANDED_TILE_DELAY = .86f; //Non first page delays private static final float QS_TILE_LABEL_FADE_OUT_START = 0.15f; @@ -65,7 +72,6 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha public static final float SHORT_PARALLAX_AMOUNT = 0.1f; - /** * List of all views that will be reset when clearing animation state * see {@link #clearAnimationState()} } @@ -93,7 +99,7 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha // slider, as well as animating the alpha of the QS tile layout (as we are tracking QQS tiles) @Nullable private TouchAnimator mFirstPageAnimator; - // TranslationX animator for QQS/QS tiles + // TranslationX animator for QQS/QS tiles. Only used on the first page! private TouchAnimator mTranslationXAnimator; // TranslationY animator for QS tiles (and their components) in the first page private TouchAnimator mTranslationYAnimator; @@ -101,13 +107,14 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha private TouchAnimator mQQSTranslationYAnimator; // Animates alpha of permanent views (QS tile layout, QQS tiles) when not in first page private TouchAnimator mNonfirstPageAlphaAnimator; - // TranslatesY the QS Tile layout using QS.getHeightDiff() - private TouchAnimator mQSTileLayoutTranslatorAnimator; // This animates fading of media player private TouchAnimator mAllPagesDelayedAnimator; - // Animator for brightness slider(s) + // Brightness slider translation driver, uses mQSExpansionPathInterpolator.yInterpolator @Nullable - private TouchAnimator mBrightnessAnimator; + private TouchAnimator mBrightnessTranslationAnimator; + // Brightness slider opacity driver. Uses linear interpolator. + @Nullable + private TouchAnimator mBrightnessOpacityAnimator; // Animator for Footer actions in QQS private TouchAnimator mQQSFooterActionsAnimator; // Height animator for QQS tiles (height changing from QQS size to QS size) @@ -125,16 +132,12 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha private boolean mNeedsAnimatorUpdate = false; private boolean mOnKeyguard; - private boolean mAllowFancy; - private boolean mFullRows; private int mNumQuickTiles; private int mLastQQSTileHeight; private float mLastPosition; private final QSTileHost mHost; private final Executor mExecutor; - private final TunerService mTunerService; private boolean mShowCollapsedOnKeyguard; - private boolean mTranslateWhileExpanding; private int mQQSTop; private int[] mTmpLoc1 = new int[2]; @@ -153,7 +156,6 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha mQuickStatusBarHeader = quickStatusBarHeader; mHost = qsTileHost; mExecutor = executor; - mTunerService = tunerService; mQSExpansionPathInterpolator = qsExpansionPathInterpolator; mHost.addCallback(this); mQsPanelController.addOnAttachStateChangeListener(this); @@ -199,7 +201,6 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha setCurrentPosition(); } - private void setCurrentPosition() { setPosition(mLastPosition); } @@ -210,28 +211,13 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha } @Override - public void onViewAttachedToWindow(@Nullable View v) { - mTunerService.addTunable(this, ALLOW_FANCY_ANIMATION, - MOVE_FULL_ROWS); + public void onViewAttachedToWindow(@NonNull View view) { + updateAnimators(); } @Override - public void onViewDetachedFromWindow(View v) { + public void onViewDetachedFromWindow(@NonNull View v) { mHost.removeCallback(this); - mTunerService.removeTunable(this); - } - - @Override - public void onTuningChanged(String key, String newValue) { - if (ALLOW_FANCY_ANIMATION.equals(key)) { - mAllowFancy = TunerService.parseIntegerSwitch(newValue, true); - if (!mAllowFancy) { - clearAnimationState(); - } - } else if (MOVE_FULL_ROWS.equals(key)) { - mFullRows = TunerService.parseIntegerSwitch(newValue, true); - } - updateAnimators(); } private void addNonFirstPageAnimators(int page) { @@ -312,13 +298,6 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha QSTileLayout tileLayout = mQsPanelController.getTileLayout(); mAllViews.add((View) tileLayout); - int heightDiff = mQs.getHeightDiff(); - if (!mTranslateWhileExpanding) { - heightDiff *= SHORT_PARALLAX_AMOUNT; - } - mQSTileLayoutTranslatorAnimator = new Builder() - .addFloat(tileLayout, "translationY", heightDiff, 0) - .build(); mLastQQSTileHeight = 0; @@ -339,8 +318,7 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha View view = mQs.getView(); // This case: less tiles to animate in small displays. - if (count < mQuickQSPanelController.getTileLayout().getNumVisibleTiles() - && mAllowFancy) { + if (count < mQuickQSPanelController.getTileLayout().getNumVisibleTiles()) { // Quick tiles. QSTileView quickTileView = mQuickQSPanelController.getTileView(tile); if (quickTileView == null) continue; @@ -422,12 +400,7 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha mAnimatedQsViews.add(tileView); mAllViews.add(quickTileView); mAllViews.add(quickTileView.getSecondaryLabel()); - } else if (mFullRows && isIconInAnimatedRow(count)) { - - firstPageBuilder.addFloat(tileView, "translationY", -heightDiff, 0); - - mAllViews.add(tileIcon); - } else { + } else if (!isIconInAnimatedRow(count)) { // Pretend there's a corresponding QQS tile (for the position) that we are // expanding from. SideLabelTileLayout qqsLayout = @@ -457,44 +430,42 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha } } - if (mAllowFancy) { - animateBrightnessSlider(firstPageBuilder); + animateBrightnessSlider(); - mFirstPageAnimator = firstPageBuilder - // Fade in the tiles/labels as we reach the final position. - .addFloat(tileLayout, "alpha", 0, 1) - .addFloat(quadraticInterpolatorBuilder.build(), "position", 0, 1) - .setListener(this) - .build(); + mFirstPageAnimator = firstPageBuilder + // Fade in the tiles/labels as we reach the final position. + .addFloat(tileLayout, "alpha", 0, 1) + .addFloat(quadraticInterpolatorBuilder.build(), "position", 0, 1) + .setListener(this) + .build(); - // Fade in the media player as we reach the final position - Builder builder = new Builder().setStartDelay(EXPANDED_TILE_DELAY); - if (mQsPanelController.shouldUseHorizontalLayout() - && mQsPanelController.mMediaHost.hostView != null) { - builder.addFloat(mQsPanelController.mMediaHost.hostView, "alpha", 0, 1); - } else { - // In portrait, media view should always be visible - mQsPanelController.mMediaHost.hostView.setAlpha(1.0f); - } - mAllPagesDelayedAnimator = builder.build(); - translationYBuilder.setInterpolator(mQSExpansionPathInterpolator.getYInterpolator()); - qqsTranslationYBuilder.setInterpolator(mQSExpansionPathInterpolator.getYInterpolator()); - translationXBuilder.setInterpolator(mQSExpansionPathInterpolator.getXInterpolator()); - if (mOnFirstPage) { - // Only recreate this animator if we're in the first page. That way we know that - // the first page is attached and has the proper positions/measures. - mQQSTranslationYAnimator = qqsTranslationYBuilder.build(); - } - mTranslationYAnimator = translationYBuilder.build(); - mTranslationXAnimator = translationXBuilder.build(); - if (mQQSTileHeightAnimator != null) { - mQQSTileHeightAnimator.setInterpolator( - mQSExpansionPathInterpolator.getYInterpolator()); - } - if (mOtherFirstPageTilesHeightAnimator != null) { - mOtherFirstPageTilesHeightAnimator.setInterpolator( - mQSExpansionPathInterpolator.getYInterpolator()); - } + // Fade in the media player as we reach the final position + Builder builder = new Builder().setStartDelay(EXPANDED_TILE_DELAY); + if (mQsPanelController.shouldUseHorizontalLayout() + && mQsPanelController.mMediaHost.hostView != null) { + builder.addFloat(mQsPanelController.mMediaHost.hostView, "alpha", 0, 1); + } else { + // In portrait, media view should always be visible + mQsPanelController.mMediaHost.hostView.setAlpha(1.0f); + } + mAllPagesDelayedAnimator = builder.build(); + translationYBuilder.setInterpolator(mQSExpansionPathInterpolator.getYInterpolator()); + qqsTranslationYBuilder.setInterpolator(mQSExpansionPathInterpolator.getYInterpolator()); + translationXBuilder.setInterpolator(mQSExpansionPathInterpolator.getXInterpolator()); + if (mOnFirstPage) { + // Only recreate this animator if we're in the first page. That way we know that + // the first page is attached and has the proper positions/measures. + mQQSTranslationYAnimator = qqsTranslationYBuilder.build(); + } + mTranslationYAnimator = translationYBuilder.build(); + mTranslationXAnimator = translationXBuilder.build(); + if (mQQSTileHeightAnimator != null) { + mQQSTileHeightAnimator.setInterpolator( + mQSExpansionPathInterpolator.getYInterpolator()); + } + if (mOtherFirstPageTilesHeightAnimator != null) { + mOtherFirstPageTilesHeightAnimator.setInterpolator( + mQSExpansionPathInterpolator.getYInterpolator()); } mNonfirstPageAlphaAnimator = nonFirstPageAlphaBuilder .addFloat(mQuickQsPanel, "alpha", 1, 0) @@ -568,7 +539,7 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha if (animator == null) { animator = new HeightExpansionAnimator( - this, mLastQQSTileHeight, tileView.getMeasuredHeight()); + this, mLastQQSTileHeight, tileView.getMeasuredHeight()); animator.setInterpolator(mQSExpansionPathInterpolator.getYInterpolator()); } animator.addView(tileView); @@ -585,7 +556,9 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha return new Pair<>(animator, builder.build()); } - private void animateBrightnessSlider(Builder firstPageBuilder) { + private void animateBrightnessSlider() { + mBrightnessTranslationAnimator = null; + mBrightnessOpacityAnimator = null; View qsBrightness = mQsPanelController.getBrightnessView(); View qqsBrightness = mQuickQSPanelController.getBrightnessView(); if (qqsBrightness != null && qqsBrightness.getVisibility() == View.VISIBLE) { @@ -593,25 +566,45 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha mAnimatedQsViews.add(qsBrightness); mAllViews.add(qqsBrightness); int translationY = getRelativeTranslationY(qsBrightness, qqsBrightness); - mBrightnessAnimator = new Builder() + mBrightnessTranslationAnimator = new Builder() // we need to animate qs brightness even if animation will not be visible, // as we might start from sliderScaleY set to 0.3 if device was in collapsed QS // portrait orientation before .addFloat(qsBrightness, "sliderScaleY", 0.3f, 1) .addFloat(qqsBrightness, "translationY", 0, translationY) + .setInterpolator(mQSExpansionPathInterpolator.getYInterpolator()) .build(); } else if (qsBrightness != null) { - firstPageBuilder.addFloat(qsBrightness, "translationY", - qsBrightness.getMeasuredHeight() * 0.5f, 0); - mBrightnessAnimator = new Builder() + // The brightness slider's visible bottom edge must maintain a constant margin from the + // QS tiles during transition. Thus the slider must (1) perform the same vertical + // translation as the tiles, and (2) compensate for the slider scaling. + + // For (1), compute the distance via the vertical distance between QQS and QS tile + // layout top. + View quickSettingsRootView = mQs.getView(); + View qsTileLayout = (View) mQsPanelController.getTileLayout(); + View qqsTileLayout = (View) mQuickQSPanelController.getTileLayout(); + getRelativePosition(mTmpLoc1, qsTileLayout, quickSettingsRootView); + getRelativePosition(mTmpLoc2, qqsTileLayout, quickSettingsRootView); + int tileMovement = mTmpLoc2[1] - mTmpLoc1[1]; + + // For (2), the slider scales to the vertical center, so compensate with half the + // height at full collapse. + float scaleCompensation = qsBrightness.getMeasuredHeight() * 0.5f; + mBrightnessTranslationAnimator = new Builder() + .addFloat(qsBrightness, "translationY", scaleCompensation + tileMovement, 0) + .addFloat(qsBrightness, "sliderScaleY", 0, 1) + .setInterpolator(mQSExpansionPathInterpolator.getYInterpolator()) + .build(); + + // While the slider's position and unfurl is animated throughouth the motion, the + // fade in happens independently. + mBrightnessOpacityAnimator = new Builder() .addFloat(qsBrightness, "alpha", 0, 1) - .addFloat(qsBrightness, "sliderScaleY", 0.3f, 1) - .setInterpolator(Interpolators.ALPHA_IN) - .setStartDelay(0.3f) + .setStartDelay(0.2f) + .setEndDelay(1 - 0.5f) .build(); mAllViews.add(qsBrightness); - } else { - mBrightnessAnimator = null; } } @@ -639,7 +632,7 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha } private void getRelativePositionInt(int[] loc1, View view, View parent) { - if(view == parent || view == null) return; + if (view == parent || view == null) return; // Ignore tile pages as they can have some offset we don't want to take into account in // RTL. if (!isAPage(view)) { @@ -672,7 +665,6 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha } } mLastPosition = position; - if (!mAllowFancy) return; if (mOnFirstPage) { mQuickQsPanel.setAlpha(1); mFirstPageAnimator.setPosition(position); @@ -694,11 +686,13 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha if (mQQSTileHeightAnimator != null) { mQQSTileHeightAnimator.setPosition(position); } - mQSTileLayoutTranslatorAnimator.setPosition(position); mQQSTranslationYAnimator.setPosition(position); mAllPagesDelayedAnimator.setPosition(position); - if (mBrightnessAnimator != null) { - mBrightnessAnimator.setPosition(position); + if (mBrightnessOpacityAnimator != null) { + mBrightnessOpacityAnimator.setPosition(position); + } + if (mBrightnessTranslationAnimator != null) { + mBrightnessTranslationAnimator.setPosition(position); } if (mQQSFooterActionsAnimator != null) { mQQSFooterActionsAnimator.setPosition(position); @@ -792,13 +786,6 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha setCurrentPosition(); }; - /** - * True whe QS will be pulled from the top, false when it will be clipped. - */ - public void setTranslateWhileExpanding(boolean shouldTranslate) { - mTranslateWhileExpanding = shouldTranslate; - } - private static class HeightExpansionAnimator { private final List<View> mViews = new ArrayList<>(); private final ValueAnimator mAnimator; @@ -806,30 +793,31 @@ public class QSAnimator implements Callback, PageListener, Listener, OnLayoutCha private final ValueAnimator.AnimatorUpdateListener mUpdateListener = new ValueAnimator.AnimatorUpdateListener() { - float mLastT = -1; - @Override - public void onAnimationUpdate(ValueAnimator valueAnimator) { - float t = valueAnimator.getAnimatedFraction(); - final int viewCount = mViews.size(); - int height = (Integer) valueAnimator.getAnimatedValue(); - for (int i = 0; i < viewCount; i++) { - View v = mViews.get(i); - if (v instanceof HeightOverrideable) { - ((HeightOverrideable) v).setHeightOverride(height); - } else { - v.setBottom(v.getTop() + height); + float mLastT = -1; + + @Override + public void onAnimationUpdate(ValueAnimator valueAnimator) { + float t = valueAnimator.getAnimatedFraction(); + final int viewCount = mViews.size(); + int height = (Integer) valueAnimator.getAnimatedValue(); + for (int i = 0; i < viewCount; i++) { + View v = mViews.get(i); + if (v instanceof HeightOverrideable) { + ((HeightOverrideable) v).setHeightOverride(height); + } else { + v.setBottom(v.getTop() + height); + } + } + if (t == 0f) { + mListener.onAnimationAtStart(); + } else if (t == 1f) { + mListener.onAnimationAtEnd(); + } else if (mLastT <= 0 || mLastT == 1) { + mListener.onAnimationStarted(); + } + mLastT = t; } - } - if (t == 0f) { - mListener.onAnimationAtStart(); - } else if (t == 1f) { - mListener.onAnimationAtEnd(); - } else if (mLastT <= 0 || mLastT == 1) { - mListener.onAnimationStarted(); - } - mLastT = t; - } - }; + }; HeightExpansionAnimator(TouchAnimator.Listener listener, int startHeight, int endHeight) { mListener = listener; diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDetailClipper.java b/packages/SystemUI/src/com/android/systemui/qs/QSDetailClipper.java index b02efba93161..de11d567d858 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSDetailClipper.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSDetailClipper.java @@ -39,8 +39,15 @@ public class QSDetailClipper { mBackground = (TransitionDrawable) detail.getBackground(); } - public void animateCircularClip(int x, int y, boolean in, AnimatorListener listener) { - updateCircularClip(true /* animate */, x, y, in, listener); + /** + * @param x x position where animation should originate + * @param y y position where animation should originate + * @param in whether animating in or out + * @param listener Animation listener. Called whether or not {@code animate} is true. + * @return the duration of the circular animator + */ + public long animateCircularClip(int x, int y, boolean in, AnimatorListener listener) { + return updateCircularClip(true /* animate */, x, y, in, listener); } /** @@ -50,8 +57,9 @@ public class QSDetailClipper { * @param y y position where animation should originate * @param in whether animating in or out * @param listener Animation listener. Called whether or not {@code animate} is true. + * @return the duration of the circular animator */ - public void updateCircularClip(boolean animate, int x, int y, boolean in, + public long updateCircularClip(boolean animate, int x, int y, boolean in, AnimatorListener listener) { if (mAnimator != null) { mAnimator.cancel(); @@ -87,6 +95,7 @@ public class QSDetailClipper { mAnimator.addListener(mGoneOnEnd); } mAnimator.start(); + return mAnimator.getDuration(); } private final Runnable mReverseBackground = new Runnable() { diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java index 05b3eae1d2f2..7b27cf45979f 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java @@ -34,6 +34,7 @@ import android.view.View; import android.view.ViewGroup; import android.view.ViewTreeObserver; +import androidx.annotation.FloatRange; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; import androidx.lifecycle.Lifecycle; @@ -166,6 +167,13 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca // visible; private boolean mQsVisible; + /** + * Whether the notification panel uses the full width of the screen. + * + * Usually {@code true} on small screens, and {@code false} on large screens. + */ + private boolean mIsNotificationPanelFullWidth; + @Inject public QSFragment(RemoteInputQuickSettingsDisabler remoteInputQsDisabler, QSTileHost qsTileHost, @@ -565,21 +573,22 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca @Override public void setInSplitShade(boolean inSplitShade) { mInSplitShade = inSplitShade; - mQSAnimator.setTranslateWhileExpanding(inSplitShade); updateShowCollapsedOnKeyguard(); updateQsState(); } @Override - public void setTransitionToFullShadeAmount(float pxAmount, float progress) { - boolean isTransitioningToFullShade = pxAmount > 0; + public void setTransitionToFullShadeProgress( + boolean isTransitioningToFullShade, + @FloatRange(from = 0.0, to = 1.0) float qsTransitionFraction, + @FloatRange(from = 0.0, to = 1.0) float qsSquishinessFraction) { if (isTransitioningToFullShade != mTransitioningToFullShade) { mTransitioningToFullShade = isTransitioningToFullShade; updateShowCollapsedOnKeyguard(); } - mFullShadeProgress = progress; + mFullShadeProgress = qsTransitionFraction; setQsExpansion(mLastQSExpansion, mLastPanelFraction, mLastHeaderTranslation, - isTransitioningToFullShade ? progress : mSquishinessFraction); + isTransitioningToFullShade ? qsSquishinessFraction : mSquishinessFraction); } @Override @@ -598,12 +607,16 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca } @Override + public void setIsNotificationPanelFullWidth(boolean isFullWidth) { + mIsNotificationPanelFullWidth = isFullWidth; + } + + @Override public void setQsExpansion(float expansion, float panelExpansionFraction, float proposedTranslation, float squishinessFraction) { float headerTranslation = mTransitioningToFullShade ? 0 : proposedTranslation; - float alphaProgress = mTransitioningToFullShade || mState == StatusBarState.KEYGUARD - ? mFullShadeProgress : panelExpansionFraction; - setAlphaAnimationProgress(mInSplitShade ? alphaProgress : 1); + float alphaProgress = calculateAlphaProgress(panelExpansionFraction); + setAlphaAnimationProgress(alphaProgress); mContainer.setExpansion(expansion); final float translationScaleY = (mInSplitShade ? 1 : QSAnimator.SHORT_PARALLAX_AMOUNT) * (expansion - 1); @@ -655,7 +668,11 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca mQSPanelController.setRevealExpansion(expansion); mQSPanelController.getTileLayout().setExpansion(expansion, proposedTranslation); mQuickQSPanelController.getTileLayout().setExpansion(expansion, proposedTranslation); - mQSPanelScrollView.setTranslationY(translationScaleY * heightDiff); + + float qsScrollViewTranslation = + onKeyguard && !mShowCollapsedOnKeyguard ? panelTranslationY : 0; + mQSPanelScrollView.setTranslationY(qsScrollViewTranslation); + if (fullyCollapsed) { mQSPanelScrollView.setScrollY(0); } @@ -683,10 +700,43 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca } else if (progress > 0 && view.getVisibility() != View.VISIBLE) { view.setVisibility((View.VISIBLE)); } - float alpha = mQSPanelController.isBouncerInTransit() - ? BouncerPanelExpansionCalculator.aboutToShowBouncerProgress(progress) - : ShadeInterpolation.getContentAlpha(progress); - view.setAlpha(alpha); + view.setAlpha(interpolateAlphaAnimationProgress(progress)); + } + + private float calculateAlphaProgress(float panelExpansionFraction) { + if (mIsNotificationPanelFullWidth) { + // Small screens. QS alpha is not animated. + return 1; + } + if (mInSplitShade) { + // Large screens in landscape. + if (mTransitioningToFullShade || isKeyguardState()) { + // Always use "mFullShadeProgress" on keyguard, because + // "panelExpansionFractions" is always 1 on keyguard split shade. + return mFullShadeProgress; + } else { + return panelExpansionFraction; + } + } + // Large screens in portrait. + if (mTransitioningToFullShade) { + // Only use this value during the standard lock screen shade expansion. During the + // "quick" expansion from top, this value is 0. + return mFullShadeProgress; + } else { + return panelExpansionFraction; + } + } + + private float interpolateAlphaAnimationProgress(float progress) { + if (mQSPanelController.isBouncerInTransit()) { + return BouncerPanelExpansionCalculator.aboutToShowBouncerProgress(progress); + } + if (isKeyguardState()) { + // Alpha progress should be linear on lockscreen shade expansion. + return progress; + } + return ShadeInterpolation.getContentAlpha(progress); } private void updateQsBounds() { diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java index 7155626a1aa1..448e1807f7af 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java @@ -49,7 +49,6 @@ import com.android.systemui.tuner.TunerService.Tunable; import java.util.ArrayList; import java.util.List; -import java.util.Objects; /** View that represents the quick settings tile panel (when expanded/pulled down). **/ public class QSPanel extends LinearLayout implements Tunable { @@ -291,7 +290,16 @@ public class QSPanel extends LinearLayout implements Tunable { } else { topOffset = tileHeightOffset; } - int top = Objects.requireNonNull(mChildrenLayoutTop.get(child)); + // Animation can occur before the layout pass, meaning setSquishinessFraction() gets + // called before onLayout(). So, a child view could be null because it has not + // been added to mChildrenLayoutTop yet (which happens in onLayout()). + // We use a continue statement here to catch this NPE because, on the layout pass, + // this code will be called again from onLayout() with the populated children views. + Integer childLayoutTop = mChildrenLayoutTop.get(child); + if (childLayoutTop == null) { + continue; + } + int top = childLayoutTop; child.setLeftTopRightBottom(child.getLeft(), top + topOffset, child.getRight(), top + topOffset + child.getHeight()); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java index b20d7ba33397..67bf3003deff 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooter.java @@ -97,7 +97,8 @@ public class QSSecurityFooter extends ViewController<View> super(rootView); mFooterText = mView.findViewById(R.id.footer_text); mPrimaryFooterIcon = mView.findViewById(R.id.primary_footer_icon); - mFooterIcon = new Icon.Resource(R.drawable.ic_info_outline); + mFooterIcon = new Icon.Resource( + R.drawable.ic_info_outline, /* contentDescription= */ null); mContext = rootView.getContext(); mSecurityController = securityController; mMainHandler = mainHandler; diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooterUtils.java b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooterUtils.java index f6322743eaa1..bd75c75faa00 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooterUtils.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QSSecurityFooterUtils.java @@ -75,6 +75,7 @@ import com.android.internal.jank.InteractionJankMonitor; import com.android.systemui.R; import com.android.systemui.animation.DialogCuj; import com.android.systemui.animation.DialogLaunchAnimator; +import com.android.systemui.common.shared.model.ContentDescription; import com.android.systemui.common.shared.model.Icon; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Application; @@ -243,16 +244,17 @@ public class QSSecurityFooterUtils implements DialogInterface.OnClickListener { isWorkProfileOn).toString(); Icon icon; + ContentDescription contentDescription = null; if (isParentalControlsEnabled) { - icon = new Icon.Loaded(securityModel.getDeviceAdminIcon()); + icon = new Icon.Loaded(securityModel.getDeviceAdminIcon(), contentDescription); } else if (vpnName != null || vpnNameWorkProfile != null) { if (securityModel.isVpnBranded()) { - icon = new Icon.Resource(R.drawable.stat_sys_branded_vpn); + icon = new Icon.Resource(R.drawable.stat_sys_branded_vpn, contentDescription); } else { - icon = new Icon.Resource(R.drawable.stat_sys_vpn_ic); + icon = new Icon.Resource(R.drawable.stat_sys_vpn_ic, contentDescription); } } else { - icon = new Icon.Resource(R.drawable.ic_info_outline); + icon = new Icon.Resource(R.drawable.ic_info_outline, contentDescription); } return new SecurityButtonConfig(icon, text, isClickable); diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java index 8ad011904d3d..cf10c7940871 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java +++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java @@ -125,9 +125,10 @@ public class QSCustomizer extends LinearLayout { isShown = true; mOpening = true; setVisibility(View.VISIBLE); - mClipper.animateCircularClip(mX, mY, true, new ExpandAnimatorListener(tileAdapter)); + long duration = mClipper.animateCircularClip( + mX, mY, true, new ExpandAnimatorListener(tileAdapter)); mQsContainerController.setCustomizerAnimating(true); - mQsContainerController.setCustomizerShowing(true); + mQsContainerController.setCustomizerShowing(true, duration); } } @@ -153,13 +154,14 @@ public class QSCustomizer extends LinearLayout { // Make sure we're not opening (because we're closing). Nobody can think we are // customizing after the next two lines. mOpening = false; + long duration = 0; if (animate) { - mClipper.animateCircularClip(mX, mY, false, mCollapseAnimationListener); + duration = mClipper.animateCircularClip(mX, mY, false, mCollapseAnimationListener); } else { setVisibility(View.GONE); } mQsContainerController.setCustomizerAnimating(animate); - mQsContainerController.setCustomizerShowing(false); + mQsContainerController.setCustomizerShowing(false, duration); } } diff --git a/packages/SystemUI/src/com/android/systemui/qs/footer/ui/binder/FooterActionsViewBinder.kt b/packages/SystemUI/src/com/android/systemui/qs/footer/ui/binder/FooterActionsViewBinder.kt index 8dd506ec8775..28ddead0bdd9 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/footer/ui/binder/FooterActionsViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/footer/ui/binder/FooterActionsViewBinder.kt @@ -31,7 +31,6 @@ import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.lifecycleScope import androidx.lifecycle.repeatOnLifecycle import com.android.systemui.R -import com.android.systemui.common.ui.binder.ContentDescriptionViewBinder import com.android.systemui.common.ui.binder.IconViewBinder import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.people.ui.view.PeopleViewBinder.bind @@ -233,10 +232,8 @@ object FooterActionsViewBinder { val icon = model.icon val iconView = button.icon - val contentDescription = model.contentDescription IconViewBinder.bind(icon, iconView) - ContentDescriptionViewBinder.bind(contentDescription, iconView) if (model.iconTint != null) { iconView.setColorFilter(model.iconTint, PorterDuff.Mode.SRC_IN) } else { diff --git a/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsButtonViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsButtonViewModel.kt index 4c0879e225c1..2ad0513c2ace 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsButtonViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsButtonViewModel.kt @@ -18,7 +18,6 @@ package com.android.systemui.qs.footer.ui.viewmodel import android.annotation.DrawableRes import android.view.View -import com.android.systemui.common.shared.model.ContentDescription import com.android.systemui.common.shared.model.Icon /** @@ -29,7 +28,6 @@ data class FooterActionsButtonViewModel( val icon: Icon, val iconTint: Int?, @DrawableRes val background: Int, - val contentDescription: ContentDescription, // TODO(b/230830644): Replace View by an Expandable interface that can expand in either dialog // or activity. val onClick: (View) -> Unit, diff --git a/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModel.kt index b556a3e0d66b..a935338c2565 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/footer/ui/viewmodel/FooterActionsViewModel.kt @@ -138,10 +138,12 @@ class FooterActionsViewModel( /** The model for the settings button. */ val settings: FooterActionsButtonViewModel = FooterActionsButtonViewModel( - Icon.Resource(R.drawable.ic_settings), + Icon.Resource( + R.drawable.ic_settings, + ContentDescription.Resource(R.string.accessibility_quick_settings_settings) + ), iconTint = null, R.drawable.qs_footer_action_circle, - ContentDescription.Resource(R.string.accessibility_quick_settings_settings), this::onSettingsButtonClicked, ) @@ -149,14 +151,16 @@ class FooterActionsViewModel( val power: FooterActionsButtonViewModel? = if (showPowerButton) { FooterActionsButtonViewModel( - Icon.Resource(android.R.drawable.ic_lock_power_off), + Icon.Resource( + android.R.drawable.ic_lock_power_off, + ContentDescription.Resource(R.string.accessibility_quick_settings_power_menu) + ), iconTint = Utils.getColorAttrDefaultColor( context, com.android.internal.R.attr.textColorOnAccent, ), R.drawable.qs_footer_action_circle_color, - ContentDescription.Resource(R.string.accessibility_quick_settings_power_menu), this::onPowerButtonClicked, ) } else { @@ -252,10 +256,12 @@ class FooterActionsViewModel( } return FooterActionsButtonViewModel( - Icon.Loaded(icon), + Icon.Loaded( + icon, + ContentDescription.Loaded(userSwitcherContentDescription(status.currentUserName)), + ), iconTint, R.drawable.qs_footer_action_circle, - ContentDescription.Loaded(userSwitcherContentDescription(status.currentUserName)), this::onUserSwitcherClicked, ) } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java index 58426656e4bf..e9a6c25c0e6d 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSIconViewImpl.java @@ -50,6 +50,7 @@ public class QSIconViewImpl extends QSIconView { protected int mIconSizePx; private boolean mAnimationEnabled = true; private int mState = -1; + private boolean mDisabledByPolicy = false; private int mTint; @Nullable private QSTile.Icon mLastIcon; @@ -159,14 +160,10 @@ public class QSIconViewImpl extends QSIconView { } protected void setIcon(ImageView iv, QSTile.State state, boolean allowAnimations) { - if (state.disabledByPolicy) { - iv.setColorFilter(getContext().getColor(R.color.qs_tile_disabled_color)); - } else { - iv.clearColorFilter(); - } - if (state.state != mState) { + if (state.state != mState || state.disabledByPolicy != mDisabledByPolicy) { int color = getColor(state); mState = state.state; + mDisabledByPolicy = state.disabledByPolicy; if (mTint != 0 && allowAnimations && shouldAnimate(iv)) { animateGrayScale(mTint, color, iv, () -> updateIcon(iv, state, allowAnimations)); } else { @@ -241,8 +238,8 @@ public class QSIconViewImpl extends QSIconView { */ private static int getIconColorForState(Context context, QSTile.State state) { if (state.disabledByPolicy || state.state == Tile.STATE_UNAVAILABLE) { - return Utils.applyAlpha(QSTileViewImpl.UNAVAILABLE_ALPHA, - Utils.getColorAttrDefaultColor(context, android.R.attr.textColorPrimary)); + return Utils.getColorAttrDefaultColor( + context, com.android.internal.R.attr.textColorTertiary); } else if (state.state == Tile.STATE_INACTIVE) { return Utils.getColorAttrDefaultColor(context, android.R.attr.textColorPrimary); } else if (state.state == Tile.STATE_ACTIVE) { diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt index 163ee2af600c..972b24343d10 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt @@ -100,14 +100,15 @@ open class QSTileViewImpl @JvmOverloads constructor( Utils.getColorAttrDefaultColor(context, com.android.internal.R.attr.textColorOnAccent) private val colorLabelInactive = Utils.getColorAttrDefaultColor(context, android.R.attr.textColorPrimary) - private val colorLabelUnavailable = Utils.applyAlpha(UNAVAILABLE_ALPHA, colorLabelInactive) + private val colorLabelUnavailable = + Utils.getColorAttrDefaultColor(context, com.android.internal.R.attr.textColorTertiary) private val colorSecondaryLabelActive = Utils.getColorAttrDefaultColor(context, android.R.attr.textColorSecondaryInverse) private val colorSecondaryLabelInactive = Utils.getColorAttrDefaultColor(context, android.R.attr.textColorSecondary) private val colorSecondaryLabelUnavailable = - Utils.applyAlpha(UNAVAILABLE_ALPHA, colorSecondaryLabelInactive) + Utils.getColorAttrDefaultColor(context, com.android.internal.R.attr.textColorTertiary) private lateinit var label: TextView protected lateinit var secondaryLabel: TextView diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java index c2a82a76d3e8..a31500c6bb18 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ColorInversionTile.java @@ -49,7 +49,6 @@ import javax.inject.Inject; /** Quick settings tile: Invert colors **/ public class ColorInversionTile extends QSTileImpl<BooleanState> { - private final Icon mIcon = ResourceIcon.get(drawable.ic_invert_colors); private final SettingObserver mSetting; @Inject @@ -123,7 +122,9 @@ public class ColorInversionTile extends QSTileImpl<BooleanState> { state.value = enabled; state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE; state.label = mContext.getString(R.string.quick_settings_inversion_label); - state.icon = mIcon; + state.icon = ResourceIcon.get(state.value + ? drawable.qs_invert_colors_icon_on + : drawable.qs_invert_colors_icon_off); state.expandedAccessibilityClassName = Switch.class.getName(); state.contentDescription = state.label; } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java index 9fdf5940c392..2fc99f323611 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java @@ -128,13 +128,13 @@ public class DataSaverTile extends QSTileImpl<BooleanState> implements @Override protected void handleUpdateState(BooleanState state, Object arg) { - state.value = arg instanceof Boolean ? (Boolean) arg + state.value = arg instanceof Boolean ? ((Boolean) arg).booleanValue() : mDataSaverController.isDataSaverEnabled(); state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE; state.label = mContext.getString(R.string.data_saver); state.contentDescription = state.label; - state.icon = ResourceIcon.get(state.value ? R.drawable.ic_data_saver - : R.drawable.ic_data_saver_off); + state.icon = ResourceIcon.get(state.value ? R.drawable.qs_data_saver_icon_on + : R.drawable.qs_data_saver_icon_off); state.expandedAccessibilityClassName = Switch.class.getName(); } diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt index 05b342072974..c65bd9b4348e 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt @@ -31,7 +31,6 @@ import com.android.systemui.controls.ControlsServiceInfo import com.android.systemui.controls.dagger.ControlsComponent import com.android.systemui.controls.dagger.ControlsComponent.Visibility.AVAILABLE import com.android.systemui.controls.management.ControlsListingController -import com.android.systemui.controls.ui.ControlsActivity import com.android.systemui.controls.ui.ControlsUiController import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dagger.qualifiers.Main @@ -42,7 +41,6 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.qs.QSHost import com.android.systemui.qs.logging.QSLogger import com.android.systemui.qs.tileimpl.QSTileImpl -import com.android.systemui.statusbar.policy.KeyguardStateController import java.util.concurrent.atomic.AtomicBoolean import javax.inject.Inject @@ -55,8 +53,7 @@ class DeviceControlsTile @Inject constructor( statusBarStateController: StatusBarStateController, activityStarter: ActivityStarter, qsLogger: QSLogger, - private val controlsComponent: ControlsComponent, - private val keyguardStateController: KeyguardStateController + private val controlsComponent: ControlsComponent ) : QSTileImpl<QSTile.State>( host, backgroundLooper, @@ -105,7 +102,8 @@ class DeviceControlsTile @Inject constructor( } val intent = Intent().apply { - component = ComponentName(mContext, ControlsActivity::class.java) + component = ComponentName(mContext, controlsComponent.getControlsUiController().get() + .resolveActivity()) addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK) putExtra(ControlsUiController.EXTRA_ANIMATE, true) } @@ -127,10 +125,15 @@ class DeviceControlsTile @Inject constructor( state.icon = icon if (controlsComponent.isEnabled() && hasControlsApps.get()) { if (controlsComponent.getVisibility() == AVAILABLE) { - val structure = controlsComponent - .getControlsController().get().getPreferredStructure().structure - state.state = Tile.STATE_ACTIVE - state.secondaryLabel = if (structure == tileLabel) null else structure + val structureInfo = controlsComponent + .getControlsController().get().getPreferredStructure() + state.state = if (structureInfo.controls.isEmpty()) { + Tile.STATE_INACTIVE + } else { + Tile.STATE_ACTIVE + } + val label = structureInfo.structure + state.secondaryLabel = if (label == tileLabel) null else label } else { state.state = Tile.STATE_INACTIVE state.secondaryLabel = mContext.getText(R.string.controls_tile_locked) diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java index 81813db5abfd..0e9f6599522f 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NightDisplayTile.java @@ -144,9 +144,10 @@ public class NightDisplayTile extends QSTileImpl<BooleanState> implements protected void handleUpdateState(BooleanState state, Object arg) { state.value = mManager.isNightDisplayActivated(); state.label = mContext.getString(R.string.quick_settings_night_display_label); - state.icon = ResourceIcon.get(com.android.internal.R.drawable.ic_qs_night_display_on); state.expandedAccessibilityClassName = Switch.class.getName(); state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE; + state.icon = ResourceIcon.get(state.value ? R.drawable.qs_nightlight_icon_on + : R.drawable.qs_nightlight_icon_off); state.secondaryLabel = getSecondaryLabel(state.value); state.contentDescription = TextUtils.isEmpty(state.secondaryLabel) ? state.label diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UiModeNightTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UiModeNightTile.java index e2964eaf2a23..f60e0661a235 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UiModeNightTile.java +++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UiModeNightTile.java @@ -17,6 +17,7 @@ package com.android.systemui.qs.tiles; import android.app.UiModeManager; +import android.content.Context; import android.content.Intent; import android.content.res.Configuration; import android.os.Handler; @@ -60,9 +61,7 @@ public class UiModeNightTile extends QSTileImpl<QSTile.BooleanState> implements ConfigurationController.ConfigurationListener, BatteryController.BatteryStateChangeCallback { public static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("hh:mm a"); - private final Icon mIcon = ResourceIcon.get( - com.android.internal.R.drawable.ic_qs_ui_mode_night); - private UiModeManager mUiModeManager; + private final UiModeManager mUiModeManager; private final BatteryController mBatteryController; private final LocationController mLocationController; @Inject @@ -82,7 +81,8 @@ public class UiModeNightTile extends QSTileImpl<QSTile.BooleanState> implements super(host, backgroundLooper, mainHandler, falsingManager, metricsLogger, statusBarStateController, activityStarter, qsLogger); mBatteryController = batteryController; - mUiModeManager = host.getUserContext().getSystemService(UiModeManager.class); + mUiModeManager = (UiModeManager) host.getUserContext().getSystemService( + Context.UI_MODE_SERVICE); mLocationController = locationController; configurationController.observe(getLifecycle(), this); batteryController.observe(getLifecycle(), this); @@ -155,7 +155,6 @@ public class UiModeNightTile extends QSTileImpl<QSTile.BooleanState> implements } state.value = nightMode; state.label = mContext.getString(R.string.quick_settings_ui_mode_night_label); - state.icon = mIcon; state.contentDescription = TextUtils.isEmpty(state.secondaryLabel) ? state.label : TextUtils.concat(state.label, ", ", state.secondaryLabel); @@ -164,6 +163,9 @@ public class UiModeNightTile extends QSTileImpl<QSTile.BooleanState> implements } else { state.state = state.value ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE; } + state.icon = ResourceIcon.get(state.state == Tile.STATE_ACTIVE + ? R.drawable.qs_light_dark_theme_icon_on + : R.drawable.qs_light_dark_theme_icon_off); state.showRippleEffect = false; state.expandedAccessibilityClassName = Switch.class.getName(); } diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java index 30862b78c93f..3788ad98092f 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java +++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java @@ -61,6 +61,7 @@ import android.os.Handler; import android.os.IBinder; import android.os.Looper; import android.os.PatternMatcher; +import android.os.Process; import android.os.RemoteException; import android.os.SystemClock; import android.os.UserHandle; @@ -174,7 +175,6 @@ public class OverviewProxyService extends CurrentUserTracker implements private boolean mBound; private boolean mIsEnabled; private int mCurrentBoundedUserId = -1; - private float mNavBarButtonAlpha; private boolean mInputFocusTransferStarted; private float mInputFocusTransferStartY; private long mInputFocusTransferStartMillis; @@ -296,12 +296,6 @@ public class OverviewProxyService extends CurrentUserTracker implements } @Override - public void setNavBarButtonAlpha(float alpha, boolean animate) { - verifyCallerAndClearCallingIdentityPostMain("setNavBarButtonAlpha", () -> - notifyNavBarButtonAlphaChanged(alpha, animate)); - } - - @Override public void onAssistantProgress(@FloatRange(from = 0.0, to = 1.0) float progress) { verifyCallerAndClearCallingIdentityPostMain("onAssistantProgress", () -> notifyAssistantProgress(progress)); @@ -581,6 +575,12 @@ public class OverviewProxyService extends CurrentUserTracker implements AssistUtils assistUtils, DumpManager dumpManager) { super(broadcastDispatcher); + + // b/241601880: This component shouldn't be running for a non-primary user + if (!Process.myUserHandle().equals(UserHandle.SYSTEM)) { + Log.e(TAG_OPS, "Unexpected initialization for non-primary user", new Throwable()); + } + mContext = context; mPipOptional = pipOptional; mCentralSurfacesOptionalLazy = centralSurfacesOptionalLazy; @@ -603,9 +603,6 @@ public class OverviewProxyService extends CurrentUserTracker implements mBackAnimation = backAnimation; mUiEventLogger = uiEventLogger; - // Assumes device always starts with back button until launcher tells it that it does not - mNavBarButtonAlpha = 1.0f; - dumpManager.registerDumpable(getClass().getSimpleName(), this); // Listen for nav bar mode changes @@ -807,7 +804,6 @@ public class OverviewProxyService extends CurrentUserTracker implements mConnectionCallbacks.add(listener); } listener.onConnectionChanged(mOverviewProxy != null); - listener.onNavBarButtonAlphaChanged(mNavBarButtonAlpha, false); } @Override @@ -837,17 +833,10 @@ public class OverviewProxyService extends CurrentUserTracker implements if (mOverviewProxy != null) { mOverviewProxy.asBinder().unlinkToDeath(mOverviewServiceDeathRcpt, 0); mOverviewProxy = null; - notifyNavBarButtonAlphaChanged(1f, false /* animate */); notifyConnectionChanged(); } } - private void notifyNavBarButtonAlphaChanged(float alpha, boolean animate) { - for (int i = mConnectionCallbacks.size() - 1; i >= 0; --i) { - mConnectionCallbacks.get(i).onNavBarButtonAlphaChanged(alpha, animate); - } - } - private void notifyHomeRotationEnabled(boolean enabled) { for (int i = mConnectionCallbacks.size() - 1; i >= 0; --i) { mConnectionCallbacks.get(i).onHomeRotationEnabled(enabled); @@ -1076,7 +1065,6 @@ public class OverviewProxyService extends CurrentUserTracker implements pw.print(" mInputFocusTransferStartMillis="); pw.println(mInputFocusTransferStartMillis); pw.print(" mWindowCornerRadius="); pw.println(mWindowCornerRadius); pw.print(" mSupportsRoundedCornersOnWindows="); pw.println(mSupportsRoundedCornersOnWindows); - pw.print(" mNavBarButtonAlpha="); pw.println(mNavBarButtonAlpha); pw.print(" mActiveNavBarRegion="); pw.println(mActiveNavBarRegion); pw.print(" mNavBarMode="); pw.println(mNavBarMode); mSysUiState.dump(pw, args); @@ -1091,8 +1079,6 @@ public class OverviewProxyService extends CurrentUserTracker implements default void onQuickScrubStarted() {} /** Notify the recents app (overview) is started by 3-button navigation. */ default void onToggleRecentApps() {} - /** Notify changes in the nav bar button alpha */ - default void onNavBarButtonAlphaChanged(float alpha, boolean animate) {} default void onHomeRotationEnabled(boolean enabled) {} default void onTaskbarStatusUpdated(boolean visible, boolean stashed) {} default void onTaskbarAutohideSuspend(boolean suspend) {} diff --git a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java index 06c80a1ca57d..2ee5f05549cf 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java +++ b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java @@ -37,10 +37,12 @@ import android.os.RemoteException; import android.text.SpannableStringBuilder; import android.text.style.BulletSpan; import android.util.DisplayMetrics; +import android.util.Log; import android.view.Gravity; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; +import android.view.WindowManagerGlobal; import android.view.accessibility.AccessibilityManager; import android.view.animation.DecelerateInterpolator; import android.widget.Button; @@ -54,7 +56,6 @@ import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.navigationbar.NavigationBarView; import com.android.systemui.navigationbar.NavigationModeController; import com.android.systemui.shared.system.QuickStepContract; -import com.android.systemui.shared.system.WindowManagerWrapper; import com.android.systemui.statusbar.phone.CentralSurfaces; import com.android.systemui.util.leak.RotationUtils; @@ -67,6 +68,7 @@ import dagger.Lazy; public class ScreenPinningRequest implements View.OnClickListener, NavigationModeController.ModeChangedListener { + private static final String TAG = "ScreenPinningRequest"; private final Context mContext; private final Lazy<Optional<CentralSurfaces>> mCentralSurfacesOptionalLazy; @@ -248,9 +250,8 @@ public class ScreenPinningRequest implements View.OnClickListener, mLayout.findViewById(R.id.screen_pinning_text_area) .setLayoutDirection(View.LAYOUT_DIRECTION_LOCALE); View buttons = mLayout.findViewById(R.id.screen_pinning_buttons); - WindowManagerWrapper wm = WindowManagerWrapper.getInstance(); if (!QuickStepContract.isGesturalMode(mNavBarMode) - && wm.hasSoftNavigationBar(mContext.getDisplayId()) && !isTablet(mContext)) { + && hasSoftNavigationBar(mContext.getDisplayId()) && !isTablet(mContext)) { buttons.setLayoutDirection(View.LAYOUT_DIRECTION_LOCALE); swapChildrenIfRtlAndVertical(buttons); } else { @@ -321,6 +322,20 @@ public class ScreenPinningRequest implements View.OnClickListener, addView(mLayout, getRequestLayoutParams(rotation)); } + /** + * @param displayId the id of display to check if there is a software navigation bar. + * + * @return whether there is a soft nav bar on specific display. + */ + private boolean hasSoftNavigationBar(int displayId) { + try { + return WindowManagerGlobal.getWindowManagerService().hasNavigationBar(displayId); + } catch (RemoteException e) { + Log.e(TAG, "Failed to check soft navigation bar", e); + return false; + } + } + private void swapChildrenIfRtlAndVertical(View group) { if (mContext.getResources().getConfiguration().getLayoutDirection() != View.LAYOUT_DIRECTION_RTL) { diff --git a/packages/SystemUI/src/com/android/systemui/shade/LargeScreenShadeHeaderController.kt b/packages/SystemUI/src/com/android/systemui/shade/LargeScreenShadeHeaderController.kt index 6b32daff0ab1..fe40d4cbe23a 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/LargeScreenShadeHeaderController.kt +++ b/packages/SystemUI/src/com/android/systemui/shade/LargeScreenShadeHeaderController.kt @@ -30,6 +30,7 @@ import androidx.constraintlayout.motion.widget.MotionLayout import com.android.settingslib.Utils import com.android.systemui.Dumpable import com.android.systemui.R +import com.android.systemui.animation.Interpolators import com.android.systemui.animation.ShadeInterpolation import com.android.systemui.battery.BatteryMeterView import com.android.systemui.battery.BatteryMeterViewController @@ -310,6 +311,14 @@ class LargeScreenShadeHeaderController @Inject constructor( updateVisibility() } + fun startCustomizingAnimation(show: Boolean, duration: Long) { + header.animate() + .setDuration(duration) + .alpha(if (show) 0f else 1f) + .setInterpolator(if (show) Interpolators.ALPHA_OUT else Interpolators.ALPHA_IN) + .start() + } + private fun loadConstraints() { if (header is MotionLayout) { // Use resources.getXml instead of passing the resource id due to bug b/205018300 diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java index 91c6a9c892e7..1011a6d831e6 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java @@ -33,6 +33,7 @@ import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_Q import static com.android.systemui.statusbar.StatusBarState.KEYGUARD; import static com.android.systemui.statusbar.StatusBarState.SHADE; import static com.android.systemui.statusbar.StatusBarState.SHADE_LOCKED; +import static com.android.systemui.statusbar.VibratorHelper.TOUCH_VIBRATION_ATTRIBUTES; import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_ALL; import static com.android.systemui.statusbar.notification.stack.StackStateAnimator.ANIMATION_DURATION_FOLD_TO_AOD; import static com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManagerKt.STATE_CLOSED; @@ -62,6 +63,7 @@ import android.hardware.fingerprint.FingerprintSensorPropertiesInternal; import android.os.Bundle; import android.os.Handler; import android.os.PowerManager; +import android.os.Process; import android.os.Trace; import android.os.UserManager; import android.os.VibrationEffect; @@ -117,7 +119,6 @@ import com.android.systemui.biometrics.AuthController; import com.android.systemui.camera.CameraGestureHelper; import com.android.systemui.classifier.Classifier; import com.android.systemui.classifier.FalsingCollector; -import com.android.systemui.controls.dagger.ControlsComponent; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.DisplayId; import com.android.systemui.dagger.qualifiers.Main; @@ -140,7 +141,6 @@ import com.android.systemui.plugins.FalsingManager.FalsingTapListener; import com.android.systemui.plugins.qs.QS; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener; -import com.android.systemui.qrcodescanner.controller.QRCodeScannerController; import com.android.systemui.screenrecord.RecordingController; import com.android.systemui.shade.transition.ShadeTransitionController; import com.android.systemui.shared.system.QuickStepContract; @@ -217,7 +217,6 @@ import com.android.systemui.util.LargeScreenUtils; import com.android.systemui.util.ListenerSet; import com.android.systemui.util.Utils; import com.android.systemui.util.time.SystemClock; -import com.android.systemui.wallet.controller.QuickAccessWalletController; import com.android.wm.shell.animation.FlingAnimationUtils; import java.io.PrintWriter; @@ -239,6 +238,9 @@ public final class NotificationPanelViewController extends PanelViewController { private static final boolean SPEW_LOGCAT = Compile.IS_DEBUG && Log.isLoggable(TAG, Log.VERBOSE); private static final boolean DEBUG_DRAWABLE = false; + private static final VibrationEffect ADDITIONAL_TAP_REQUIRED_VIBRATION_EFFECT = + VibrationEffect.get(VibrationEffect.EFFECT_STRENGTH_MEDIUM, false); + /** * The parallax amount of the quick settings translation when dragging down the panel */ @@ -325,9 +327,6 @@ public final class NotificationPanelViewController extends PanelViewController { private final FragmentService mFragmentService; private final ScrimController mScrimController; private final PrivacyDotViewController mPrivacyDotViewController; - private final QuickAccessWalletController mQuickAccessWalletController; - private final QRCodeScannerController mQRCodeScannerController; - private final ControlsComponent mControlsComponent; private final NotificationRemoteInputManager mRemoteInputManager; private final LockscreenShadeTransitionController mLockscreenShadeTransitionController; @@ -449,6 +448,8 @@ public final class NotificationPanelViewController extends PanelViewController { private boolean mQsTouchAboveFalsingThreshold; private int mQsFalsingThreshold; + /** Indicates drag starting height when swiping down or up on heads-up notifications */ + private int mHeadsUpStartHeight; private HeadsUpTouchHelper mHeadsUpTouchHelper; private boolean mListenForHeadsUp; private int mNavigationBarBottomHeight; @@ -651,6 +652,8 @@ public final class NotificationPanelViewController extends PanelViewController { /** The drag distance required to fully expand the split shade. */ private int mSplitShadeFullTransitionDistance; + /** The drag distance required to fully transition scrims. */ + private int mSplitShadeScrimTransitionDistance; private final NotificationListContainer mNotificationListContainer; private final NotificationStackSizeCalculator mNotificationStackSizeCalculator; @@ -684,20 +687,28 @@ public final class NotificationPanelViewController extends PanelViewController { private final FalsingTapListener mFalsingTapListener = new FalsingTapListener() { @Override - public void onDoubleTapRequired() { + public void onAdditionalTapRequired() { if (mStatusBarStateController.getState() == StatusBarState.SHADE_LOCKED) { mTapAgainViewController.show(); } else { mKeyguardIndicationController.showTransientIndication( R.string.notification_tap_again); } - mVibratorHelper.vibrate(VibrationEffect.EFFECT_STRENGTH_MEDIUM); + + if (!mStatusBarStateController.isDozing()) { + mVibratorHelper.vibrate( + Process.myUid(), + mView.getContext().getPackageName(), + ADDITIONAL_TAP_REQUIRED_VIBRATION_EFFECT, + "falsing-additional-tap-required", + TOUCH_VIBRATION_ATTRIBUTES); + } } }; private final CameraGestureHelper mCameraGestureHelper; - private final Provider<KeyguardBottomAreaViewModel> mKeyguardBottomAreaViewModelProvider; - private final Provider<KeyguardBottomAreaInteractor> mKeyguardBottomAreaInteractorProvider; + private final KeyguardBottomAreaViewModel mKeyguardBottomAreaViewModel; + private final KeyguardBottomAreaInteractor mKeyguardBottomAreaInteractor; @Inject public NotificationPanelViewController(NotificationPanelView view, @@ -746,8 +757,6 @@ public final class NotificationPanelViewController extends PanelViewController { NavigationModeController navigationModeController, FragmentService fragmentService, ContentResolver contentResolver, - QuickAccessWalletController quickAccessWalletController, - QRCodeScannerController qrCodeScannerController, RecordingController recordingController, LargeScreenShadeHeaderController largeScreenShadeHeaderController, ScreenOffAnimationController screenOffAnimationController, @@ -755,7 +764,6 @@ public final class NotificationPanelViewController extends PanelViewController { PanelExpansionStateManager panelExpansionStateManager, NotificationRemoteInputManager remoteInputManager, Optional<SysUIUnfoldComponent> unfoldComponent, - ControlsComponent controlsComponent, InteractionJankMonitor interactionJankMonitor, QsFrameTranslateController qsFrameTranslateController, SysUiState sysUiState, @@ -768,8 +776,8 @@ public final class NotificationPanelViewController extends PanelViewController { ShadeTransitionController shadeTransitionController, SystemClock systemClock, CameraGestureHelper cameraGestureHelper, - Provider<KeyguardBottomAreaViewModel> keyguardBottomAreaViewModelProvider, - Provider<KeyguardBottomAreaInteractor> keyguardBottomAreaInteractorProvider) { + KeyguardBottomAreaViewModel keyguardBottomAreaViewModel, + KeyguardBottomAreaInteractor keyguardBottomAreaInteractor) { super(view, falsingManager, dozeLog, @@ -791,9 +799,6 @@ public final class NotificationPanelViewController extends PanelViewController { mVibratorHelper = vibratorHelper; mKeyguardMediaController = keyguardMediaController; mPrivacyDotViewController = privacyDotViewController; - mQuickAccessWalletController = quickAccessWalletController; - mQRCodeScannerController = qrCodeScannerController; - mControlsComponent = controlsComponent; mMetricsLogger = metricsLogger; mConfigurationController = configurationController; mFlingAnimationUtilsBuilder = flingAnimationUtilsBuilder; @@ -897,7 +902,7 @@ public final class NotificationPanelViewController extends PanelViewController { mQsFrameTranslateController = qsFrameTranslateController; updateUserSwitcherFlags(); - mKeyguardBottomAreaViewModelProvider = keyguardBottomAreaViewModelProvider; + mKeyguardBottomAreaViewModel = keyguardBottomAreaViewModel; onFinishInflate(); keyguardUnlockAnimationController.addKeyguardUnlockAnimationListener( new KeyguardUnlockAnimationController.KeyguardUnlockAnimationListener() { @@ -951,7 +956,7 @@ public final class NotificationPanelViewController extends PanelViewController { } }); mCameraGestureHelper = cameraGestureHelper; - mKeyguardBottomAreaInteractorProvider = keyguardBottomAreaInteractorProvider; + mKeyguardBottomAreaInteractor = keyguardBottomAreaInteractor; } @VisibleForTesting @@ -1064,6 +1069,8 @@ public final class NotificationPanelViewController extends PanelViewController { mLockscreenNotificationQSPadding = mResources.getDimensionPixelSize( R.dimen.notification_side_paddings); mUdfpsMaxYBurnInOffset = mResources.getDimensionPixelSize(R.dimen.udfps_burn_in_offset_y); + mSplitShadeScrimTransitionDistance = mResources.getDimensionPixelSize( + R.dimen.split_shade_scrim_transition_distance); } private void updateViewControllers(KeyguardStatusView keyguardStatusView, @@ -1276,17 +1283,7 @@ public final class NotificationPanelViewController extends PanelViewController { } private void initBottomArea() { - if (mFeatureFlags.isEnabled(Flags.MODERN_BOTTOM_AREA)) { - mKeyguardBottomArea.init(mKeyguardBottomAreaViewModelProvider.get(), mFalsingManager); - } else { - // TODO(b/235403546): remove this method call when the new implementation is complete - // and these are not needed. - mKeyguardBottomArea.init( - mFalsingManager, - mQuickAccessWalletController, - mControlsComponent, - mQRCodeScannerController); - } + mKeyguardBottomArea.init(mKeyguardBottomAreaViewModel, mFalsingManager); } @VisibleForTesting @@ -1342,6 +1339,9 @@ public final class NotificationPanelViewController extends PanelViewController { mIsFullWidth = isFullWidth; mScrimController.setClipsQsScrim(isFullWidth); mNotificationStackScrollLayoutController.setIsFullWidth(isFullWidth); + if (mQs != null) { + mQs.setIsNotificationPanelFullWidth(isFullWidth); + } } private void startQsSizeChangeAnimation(int oldHeight, final int newHeight) { @@ -1354,7 +1354,7 @@ public final class NotificationPanelViewController extends PanelViewController { mQsSizeChangeAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN); mQsSizeChangeAnimator.addUpdateListener(animation -> { requestScrollerTopPaddingUpdate(false /* animate */); - requestPanelHeightUpdate(); + updateExpandedHeightToMaxHeight(); int height = (int) mQsSizeChangeAnimator.getAnimatedValue(); mQs.setHeightOverride(height); }); @@ -1403,7 +1403,6 @@ public final class NotificationPanelViewController extends PanelViewController { } mNotificationStackScrollLayoutController.setIntrinsicPadding(stackScrollerPadding); - mKeyguardBottomArea.setAntiBurnInOffsetX(mClockPositionResult.clockX); mStackScrollerMeasuringPass++; requestScrollerTopPaddingUpdate(animate); @@ -1453,7 +1452,7 @@ public final class NotificationPanelViewController extends PanelViewController { mKeyguardStatusViewController.getClockBottom(mStatusBarHeaderHeightKeyguard), mKeyguardStatusViewController.isClockTopAligned()); mClockPositionAlgorithm.run(mClockPositionResult); - mKeyguardBottomAreaInteractorProvider.get().setClockPosition( + mKeyguardBottomAreaInteractor.setClockPosition( mClockPositionResult.clockX, mClockPositionResult.clockY); boolean animate = mNotificationStackScrollLayoutController.isAddOrRemoveAnimationPending(); boolean animateClock = (animate || mAnimateNextPositionUpdate) && shouldAnimateClockChange; @@ -2134,7 +2133,7 @@ public final class NotificationPanelViewController extends PanelViewController { mMetricsLogger.count(COUNTER_PANEL_OPEN_QS, 1); setQsExpandImmediate(true); setShowShelfOnly(true); - requestPanelHeightUpdate(); + updateExpandedHeightToMaxHeight(); // Normally, we start listening when the panel is expanded, but here we need to start // earlier so the state is already up to date when dragging down. @@ -2346,7 +2345,7 @@ public final class NotificationPanelViewController extends PanelViewController { // Reset scroll position and apply that position to the expanded height. float height = mQsExpansionHeight; setQsExpansion(height); - requestPanelHeightUpdate(); + updateExpandedHeightToMaxHeight(); mNotificationStackScrollLayoutController.checkSnoozeLeavebehind(); // When expanding QS, let's authenticate the user if possible, @@ -2362,7 +2361,7 @@ public final class NotificationPanelViewController extends PanelViewController { if (changed) { mQsExpanded = expanded; updateQsState(); - requestPanelHeightUpdate(); + updateExpandedHeightToMaxHeight(); mFalsingCollector.setQsExpanded(expanded); mCentralSurfaces.setQsExpanded(expanded); mNotificationsQSContainerController.setQsExpanded(expanded); @@ -2451,8 +2450,8 @@ public final class NotificationPanelViewController extends PanelViewController { final float squishiness; if ((mQsExpandImmediate || mQsExpanded) && !mSplitShadeEnabled) { squishiness = 1; - } else if (mLockscreenShadeTransitionController.getQSDragProgress() > 0) { - squishiness = mLockscreenShadeTransitionController.getQSDragProgress(); + } else if (mTransitioningToFullShadeProgress > 0.0f) { + squishiness = mLockscreenShadeTransitionController.getQsSquishTransitionFraction(); } else { squishiness = mNotificationStackScrollLayoutController .getNotificationSquishinessFraction(); @@ -3086,16 +3085,7 @@ public final class NotificationPanelViewController extends PanelViewController { int maxHeight; if (mQsExpandImmediate || mQsExpanded || mIsExpanding && mQsExpandedWhenExpandingStarted || mPulsing || mSplitShadeEnabled) { - if (mSplitShadeEnabled && mBarState == SHADE) { - // Max panel height is used to calculate the fraction of the shade expansion. - // Traditionally the value is based on the number of notifications. - // On split-shade, we want the required distance to be a specific and constant - // value, to make sure the expansion motion has the expected speed. - // We also only want this on non-lockscreen for now. - maxHeight = mSplitShadeFullTransitionDistance; - } else { - maxHeight = calculatePanelHeightQsExpanded(); - } + maxHeight = calculatePanelHeightQsExpanded(); } else { maxHeight = calculatePanelHeightShade(); } @@ -3296,8 +3286,7 @@ public final class NotificationPanelViewController extends PanelViewController { getExpandedFraction()); float alpha = Math.min(expansionAlpha, 1 - computeQsExpansionFraction()); alpha *= mBottomAreaShadeAlpha; - mKeyguardBottomArea.setComponentAlphas(alpha); - mKeyguardBottomAreaInteractorProvider.get().setAlpha(alpha); + mKeyguardBottomAreaInteractor.setAlpha(alpha); mLockIconViewController.setAlpha(alpha); } @@ -3455,6 +3444,31 @@ public final class NotificationPanelViewController extends PanelViewController { } @Override + public int getMaxPanelTransitionDistance() { + // Traditionally the value is based on the number of notifications. On split-shade, we want + // the required distance to be a specific and constant value, to make sure the expansion + // motion has the expected speed. We also only want this on non-lockscreen for now. + if (mSplitShadeEnabled && mBarState == SHADE) { + boolean transitionFromHeadsUp = + mHeadsUpManager.isTrackingHeadsUp() || mExpandingFromHeadsUp; + // heads-up starting height is too close to mSplitShadeFullTransitionDistance and + // when dragging HUN transition is already 90% complete. It makes shade become + // immediately visible when starting to drag. We want to set distance so that + // nothing is immediately visible when dragging (important for HUN swipe up motion) - + // 0.4 expansion fraction is a good starting point. + if (transitionFromHeadsUp) { + double maxDistance = Math.max(mSplitShadeFullTransitionDistance, + mHeadsUpStartHeight * 2.5); + return (int) Math.min(getMaxPanelHeight(), maxDistance); + } else { + return mSplitShadeFullTransitionDistance; + } + } else { + return getMaxPanelHeight(); + } + } + + @Override protected boolean isTrackingBlocked() { return mConflictingQsExpansionGesture && mQsExpanded || mBlockingExpansionForCurrentTouch; } @@ -3496,8 +3510,7 @@ public final class NotificationPanelViewController extends PanelViewController { } private void updateDozingVisibilities(boolean animate) { - mKeyguardBottomArea.setDozing(mDozing, animate); - mKeyguardBottomAreaInteractorProvider.get().setAnimateDozingTransitions(animate); + mKeyguardBottomAreaInteractor.setAnimateDozingTransitions(animate); if (!mDozing && animate) { mKeyguardStatusBarViewController.animateKeyguardStatusBarIn(); } @@ -3654,10 +3667,35 @@ public final class NotificationPanelViewController extends PanelViewController { } /** + * Called when heads-up notification is being dragged up or down to indicate what's the starting + * height for shade motion + */ + public void setHeadsUpDraggingStartingHeight(int startHeight) { + mHeadsUpStartHeight = startHeight; + float scrimMinFraction; + if (mSplitShadeEnabled) { + boolean highHun = mHeadsUpStartHeight * 2.5 > mSplitShadeScrimTransitionDistance; + // if HUN height is higher than 40% of predefined transition distance, it means HUN + // is too high for regular transition. In that case we need to calculate transition + // distance - here we take scrim transition distance as equal to shade transition + // distance. It doesn't result in perfect motion - usually scrim transition distance + // should be longer - but it's good enough for HUN case. + float transitionDistance = + highHun ? getMaxPanelTransitionDistance() : mSplitShadeFullTransitionDistance; + scrimMinFraction = mHeadsUpStartHeight / transitionDistance; + } else { + int transitionDistance = getMaxPanelHeight(); + scrimMinFraction = transitionDistance > 0f + ? (float) mHeadsUpStartHeight / transitionDistance : 0f; + } + setPanelScrimMinFraction(scrimMinFraction); + } + + /** * Sets the minimum fraction for the panel expansion offset. This may be non-zero in certain * cases, such as if there's a heads-up notification. */ - public void setPanelScrimMinFraction(float minFraction) { + private void setPanelScrimMinFraction(float minFraction) { mMinFraction = minFraction; mDepthController.setPanelPullDownMinFraction(mMinFraction); mScrimController.setPanelScrimMinFraction(mMinFraction); @@ -3741,6 +3779,7 @@ public final class NotificationPanelViewController extends PanelViewController { mQs.setHeaderClickable(isQsExpansionEnabled()); mQs.setOverscrolling(mStackScrollerOverscrolling); mQs.setInSplitShade(mSplitShadeEnabled); + mQs.setIsNotificationPanelFullWidth(mIsFullWidth); // recompute internal state when qspanel height changes mQs.getView().addOnLayoutChangeListener( @@ -3799,8 +3838,7 @@ public final class NotificationPanelViewController extends PanelViewController { mView.setDozing(dozing); mDozing = dozing; mNotificationStackScrollLayoutController.setDozing(mDozing, animate); - mKeyguardBottomArea.setDozing(mDozing, animate); - mKeyguardBottomAreaInteractorProvider.get().setAnimateDozingTransitions(animate); + mKeyguardBottomAreaInteractor.setAnimateDozingTransitions(animate); mKeyguardStatusBarViewController.setDozing(mDozing); if (dozing) { @@ -3849,7 +3887,6 @@ public final class NotificationPanelViewController extends PanelViewController { public void dozeTimeTick() { mLockIconViewController.dozeTimeTick(); - mKeyguardBottomArea.dozeTimeTick(); mKeyguardStatusViewController.dozeTimeTick(); if (mInterpolatedDarkAmount > 0) { positionClockAndNotifications(); @@ -4391,7 +4428,7 @@ public final class NotificationPanelViewController extends PanelViewController { if (mKeyguardShowing) { updateMaxDisplayedNotifications(true); } - requestPanelHeightUpdate(); + updateExpandedHeightToMaxHeight(); } @Override @@ -4524,7 +4561,7 @@ public final class NotificationPanelViewController extends PanelViewController { if (mQsExpanded && mQsFullyExpanded) { mQsExpansionHeight = mQsMaxExpansionHeight; requestScrollerTopPaddingUpdate(false /* animate */); - requestPanelHeightUpdate(); + updateExpandedHeightToMaxHeight(); } if (mAccessibilityManager.isEnabled()) { mView.setAccessibilityPaneTitle(determineAccessibilityPaneTitle()); @@ -4672,7 +4709,6 @@ public final class NotificationPanelViewController extends PanelViewController { public void onDozeAmountChanged(float linearAmount, float amount) { mInterpolatedDarkAmount = amount; mLinearDarkAmount = linearAmount; - mKeyguardBottomArea.setDarkAmount(mInterpolatedDarkAmount); positionClockAndNotifications(); } } @@ -4794,7 +4830,7 @@ public final class NotificationPanelViewController extends PanelViewController { if (mQsExpanded && mQsFullyExpanded) { mQsExpansionHeight = mQsMaxExpansionHeight; requestScrollerTopPaddingUpdate(false /* animate */); - requestPanelHeightUpdate(); + updateExpandedHeightToMaxHeight(); // Size has changed, start an animation. if (mQsMaxExpansionHeight != oldMaxHeight) { diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java index e93f60596280..8d74a09ab8b1 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java +++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowViewController.java @@ -29,6 +29,7 @@ import android.view.View; import android.view.ViewGroup; import com.android.internal.annotations.VisibleForTesting; +import com.android.keyguard.AuthKeyguardMessageArea; import com.android.keyguard.LockIconViewController; import com.android.systemui.R; import com.android.systemui.classifier.FalsingCollector; @@ -72,7 +73,7 @@ public class NotificationShadeWindowViewController { private final AmbientState mAmbientState; private final PulsingGestureListener mPulsingGestureListener; - private GestureDetector mGestureDetector; + private GestureDetector mPulsingWakeupGestureHandler; private View mBrightnessMirror; private boolean mTouchActive; private boolean mTouchCancelled; @@ -138,10 +139,18 @@ public class NotificationShadeWindowViewController { return mView.findViewById(R.id.keyguard_bouncer_container); } + /** + * @return Location where to place the KeyguardMessageArea + */ + public AuthKeyguardMessageArea getKeyguardMessageArea() { + return mView.findViewById(R.id.keyguard_message_area); + } + /** Inflates the {@link R.layout#status_bar_expanded} layout and sets it up. */ public void setupExpandedStatusBar() { mStackScrollLayout = mView.findViewById(R.id.notification_stack_scroller); - mGestureDetector = new GestureDetector(mView.getContext(), mPulsingGestureListener); + mPulsingWakeupGestureHandler = new GestureDetector(mView.getContext(), + mPulsingGestureListener); mView.setInteractionEventHandler(new NotificationShadeWindowView.InteractionEventHandler() { @Override @@ -188,7 +197,7 @@ public class NotificationShadeWindowViewController { } mFalsingCollector.onTouchEvent(ev); - mGestureDetector.onTouchEvent(ev); + mPulsingWakeupGestureHandler.onTouchEvent(ev); mStatusBarKeyguardViewManager.onTouch(ev); if (mBrightnessMirror != null && mBrightnessMirror.getVisibility() == View.VISIBLE) { diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationsQSContainerController.kt b/packages/SystemUI/src/com/android/systemui/shade/NotificationsQSContainerController.kt index 2a467763951c..d6f0de83ecc1 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/NotificationsQSContainerController.kt +++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationsQSContainerController.kt @@ -35,6 +35,7 @@ class NotificationsQSContainerController @Inject constructor( view: NotificationsQuickSettingsContainer, private val navigationModeController: NavigationModeController, private val overviewProxyService: OverviewProxyService, + private val largeScreenShadeHeaderController: LargeScreenShadeHeaderController, private val featureFlags: FeatureFlags, @Main private val delayableExecutor: DelayableExecutor ) : ViewController<NotificationsQuickSettingsContainer>(view), QSContainerController { @@ -156,9 +157,12 @@ class NotificationsQSContainerController @Inject constructor( } } - override fun setCustomizerShowing(showing: Boolean) { - isQSCustomizing = showing - updateBottomSpacing() + override fun setCustomizerShowing(showing: Boolean, animationDuration: Long) { + if (showing != isQSCustomizing) { + isQSCustomizing = showing + largeScreenShadeHeaderController.startCustomizingAnimation(showing, animationDuration) + updateBottomSpacing() + } } override fun setDetailShowing(showing: Boolean) { diff --git a/packages/SystemUI/src/com/android/systemui/shade/PanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/PanelViewController.java index a00769374938..c3f1e571ab87 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/PanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/shade/PanelViewController.java @@ -248,7 +248,7 @@ public abstract class PanelViewController { keyguardStateController.addCallback(new KeyguardStateController.Callback() { @Override public void onKeyguardFadingAwayChanged() { - requestPanelHeightUpdate(); + updateExpandedHeightToMaxHeight(); } }); mAmbientState = ambientState; @@ -730,7 +730,7 @@ public abstract class PanelViewController { setExpandedHeightInternal(height); } - protected void requestPanelHeightUpdate() { + void updateExpandedHeightToMaxHeight() { float currentMaxPanelHeight = getMaxPanelHeight(); if (isFullyCollapsed()) { @@ -753,6 +753,13 @@ public abstract class PanelViewController { setExpandedHeight(currentMaxPanelHeight); } + /** + * Returns drag down distance after which panel should be fully expanded. Usually it's the + * same as max panel height but for large screen devices (especially split shade) we might + * want to return different value to shorten drag distance + */ + public abstract int getMaxPanelTransitionDistance(); + public void setExpandedHeightInternal(float h) { if (isNaN(h)) { Log.wtf(TAG, "ExpandedHeight set to NaN"); @@ -763,18 +770,15 @@ public abstract class PanelViewController { () -> mLatencyTracker.onActionEnd(LatencyTracker.ACTION_EXPAND_PANEL)); mExpandLatencyTracking = false; } - float maxPanelHeight = getMaxPanelHeight(); + float maxPanelHeight = getMaxPanelTransitionDistance(); if (mHeightAnimator == null) { // Split shade has its own overscroll logic if (mTracking && !mInSplitShade) { float overExpansionPixels = Math.max(0, h - maxPanelHeight); setOverExpansionInternal(overExpansionPixels, true /* isFromGesture */); } - mExpandedHeight = Math.min(h, maxPanelHeight); - } else { - mExpandedHeight = h; } - + mExpandedHeight = Math.min(h, maxPanelHeight); // If we are closing the panel and we are almost there due to a slow decelerating // interpolator, abort the animation. if (mExpandedHeight < 1f && mExpandedHeight != 0f && mClosing) { @@ -832,7 +836,7 @@ public abstract class PanelViewController { protected abstract int getMaxPanelHeight(); public void setExpandedFraction(float frac) { - setExpandedHeight(getMaxPanelHeight() * frac); + setExpandedHeight(getMaxPanelTransitionDistance() * frac); } public float getExpandedHeight() { @@ -1029,7 +1033,7 @@ public abstract class PanelViewController { mHeightAnimator = animator; if (animator == null && mPanelUpdateWhenAnimatorEnds) { mPanelUpdateWhenAnimatorEnds = false; - requestPanelHeightUpdate(); + updateExpandedHeightToMaxHeight(); } } @@ -1421,7 +1425,7 @@ public abstract class PanelViewController { @Override public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { - requestPanelHeightUpdate(); + updateExpandedHeightToMaxHeight(); mHasLayoutedSinceDown = true; if (mUpdateFlingOnLayout) { abortAnimations(); diff --git a/packages/SystemUI/src/com/android/systemui/shade/PulsingGestureListener.kt b/packages/SystemUI/src/com/android/systemui/shade/PulsingGestureListener.kt index 621a6090f4a0..084b7dc3a646 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/PulsingGestureListener.kt +++ b/packages/SystemUI/src/com/android/systemui/shade/PulsingGestureListener.kt @@ -26,6 +26,8 @@ import com.android.systemui.Dumpable import com.android.systemui.dock.DockManager import com.android.systemui.dump.DumpManager import com.android.systemui.plugins.FalsingManager +import com.android.systemui.plugins.FalsingManager.LOW_PENALTY +import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.statusbar.phone.CentralSurfaces import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent import com.android.systemui.tuner.TunerService @@ -35,12 +37,12 @@ import javax.inject.Inject /** * If tap and/or double tap to wake is enabled, this gestureListener will wake the display on - * tap/double tap when the device is pulsing (AoD 2). Taps are gated by the proximity sensor and - * falsing manager. + * tap/double tap when the device is pulsing (AoD2) or transitioning to AoD. Taps are gated by the + * proximity sensor and falsing manager. * - * Touches go through the [NotificationShadeWindowViewController] when the device is pulsing. - * Otherwise, if the device is dozing and NOT pulsing, wake-ups are handled by - * [com.android.systemui.doze.DozeSensors]. + * Touches go through the [NotificationShadeWindowViewController] when the device is dozing but the + * screen is still ON and not in the true AoD display state. When the device is in the true AoD + * display state, wake-ups are handled by [com.android.systemui.doze.DozeSensors]. */ @CentralSurfacesComponent.CentralSurfacesScope class PulsingGestureListener @Inject constructor( @@ -49,6 +51,7 @@ class PulsingGestureListener @Inject constructor( private val dockManager: DockManager, private val centralSurfaces: CentralSurfaces, private val ambientDisplayConfiguration: AmbientDisplayConfiguration, + private val statusBarStateController: StatusBarStateController, tunerService: TunerService, dumpManager: DumpManager ) : GestureDetector.SimpleOnGestureListener(), Dumpable { @@ -73,11 +76,12 @@ class PulsingGestureListener @Inject constructor( dumpManager.registerDumpable(this) } - override fun onSingleTapConfirmed(e: MotionEvent): Boolean { - if (singleTapEnabled && + override fun onSingleTapUp(e: MotionEvent): Boolean { + if (statusBarStateController.isDozing && + singleTapEnabled && !dockManager.isDocked && !falsingManager.isProximityNear && - !falsingManager.isFalseTap(FalsingManager.MODERATE_PENALTY) + !falsingManager.isFalseTap(LOW_PENALTY) ) { centralSurfaces.wakeUpIfDozing( SystemClock.uptimeMillis(), @@ -88,8 +92,16 @@ class PulsingGestureListener @Inject constructor( return false } - override fun onDoubleTap(e: MotionEvent): Boolean { - if ((doubleTapEnabled || singleTapEnabled) && + /** + * Receives [MotionEvent.ACTION_DOWN], [MotionEvent.ACTION_MOVE], and [MotionEvent.ACTION_UP] + * motion events for a double tap. + */ + override fun onDoubleTapEvent(e: MotionEvent): Boolean { + // React to the [MotionEvent.ACTION_UP] event after double tap is detected. Falsing + // checks MUST be on the ACTION_UP event. + if (e.actionMasked == MotionEvent.ACTION_UP && + statusBarStateController.isDozing && + (doubleTapEnabled || singleTapEnabled) && !falsingManager.isProximityNear && !falsingManager.isFalseDoubleTap ) { diff --git a/packages/SystemUI/src/com/android/systemui/shade/transition/ScrimShadeTransitionController.kt b/packages/SystemUI/src/com/android/systemui/shade/transition/ScrimShadeTransitionController.kt index afd57daca10b..618c8924cd21 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/transition/ScrimShadeTransitionController.kt +++ b/packages/SystemUI/src/com/android/systemui/shade/transition/ScrimShadeTransitionController.kt @@ -14,6 +14,7 @@ import com.android.systemui.statusbar.phone.panelstate.PanelExpansionChangeEvent import com.android.systemui.statusbar.phone.panelstate.PanelState import com.android.systemui.statusbar.phone.panelstate.STATE_OPENING import com.android.systemui.statusbar.policy.ConfigurationController +import com.android.systemui.statusbar.policy.HeadsUpManager import com.android.systemui.util.LargeScreenUtils import java.io.PrintWriter import javax.inject.Inject @@ -28,6 +29,7 @@ constructor( private val scrimController: ScrimController, @Main private val resources: Resources, private val statusBarStateController: SysuiStatusBarStateController, + private val headsUpManager: HeadsUpManager ) { private var inSplitShade = false @@ -84,7 +86,11 @@ constructor( } private fun canUseCustomFraction(panelState: Int?) = - inSplitShade && isScreenUnlocked() && panelState == STATE_OPENING + inSplitShade && isScreenUnlocked() && panelState == STATE_OPENING && + // in case of HUN we can't always use predefined distances to manage scrim + // transition because dragDownPxAmount can start from value bigger than + // splitShadeScrimTransitionDistance + !headsUpManager.isTrackingHeadsUp private fun isScreenUnlocked() = statusBarStateController.currentOrUpcomingState == StatusBarState.SHADE diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java index 47dc5c2a5513..e06c97756ea7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java @@ -19,6 +19,7 @@ package com.android.systemui.statusbar; import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_FINANCED; import static android.app.admin.DevicePolicyResources.Strings.SystemUi.KEYGUARD_MANAGEMENT_DISCLOSURE; import static android.app.admin.DevicePolicyResources.Strings.SystemUi.KEYGUARD_NAMED_MANAGEMENT_DISCLOSURE; +import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_TOO_DARK; import static android.hardware.biometrics.BiometricSourceType.FACE; import static android.view.View.GONE; import static android.view.View.VISIBLE; @@ -49,6 +50,7 @@ import android.content.pm.UserInfo; import android.content.res.ColorStateList; import android.content.res.Resources; import android.graphics.Color; +import android.hardware.biometrics.BiometricFaceConstants; import android.hardware.biometrics.BiometricSourceType; import android.hardware.face.FaceManager; import android.hardware.fingerprint.FingerprintManager; @@ -78,6 +80,7 @@ import com.android.keyguard.KeyguardUpdateMonitorCallback; import com.android.settingslib.Utils; import com.android.settingslib.fuelgauge.BatteryStatus; import com.android.systemui.R; +import com.android.systemui.biometrics.FaceHelpMessageDeferral; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Background; @@ -178,7 +181,8 @@ public class KeyguardIndicationController { private boolean mBatteryPresent = true; private long mChargingTimeRemaining; private String mBiometricErrorMessageToShowOnScreenOn; - private final Set<Integer> mCoExFaceHelpMsgIdsToShow; + private final Set<Integer> mCoExFaceAcquisitionMsgIdsToShow; + private final FaceHelpMessageDeferral mFaceAcquiredMessageDeferral; private boolean mInited; private KeyguardUpdateMonitorCallback mUpdateMonitorCallback; @@ -228,7 +232,8 @@ public class KeyguardIndicationController { LockPatternUtils lockPatternUtils, ScreenLifecycle screenLifecycle, KeyguardBypassController keyguardBypassController, - AccessibilityManager accessibilityManager) { + AccessibilityManager accessibilityManager, + FaceHelpMessageDeferral faceHelpMessageDeferral) { mContext = context; mBroadcastDispatcher = broadcastDispatcher; mDevicePolicyManager = devicePolicyManager; @@ -249,11 +254,12 @@ public class KeyguardIndicationController { mScreenLifecycle = screenLifecycle; mScreenLifecycle.addObserver(mScreenObserver); - mCoExFaceHelpMsgIdsToShow = new HashSet<>(); + mFaceAcquiredMessageDeferral = faceHelpMessageDeferral; + mCoExFaceAcquisitionMsgIdsToShow = new HashSet<>(); int[] msgIds = context.getResources().getIntArray( com.android.systemui.R.array.config_face_help_msgs_when_fingerprint_enrolled); for (int msgId : msgIds) { - mCoExFaceHelpMsgIdsToShow.add(msgId); + mCoExFaceAcquisitionMsgIdsToShow.add(msgId); } mHandler = new Handler(mainLooper) { @@ -687,11 +693,11 @@ public class KeyguardIndicationController { /** * Returns the indication text indicating that trust has been granted. * - * @return {@code null} or an empty string if a trust indication text should not be shown. + * @return an empty string if a trust indication text should not be shown. */ @VisibleForTesting String getTrustGrantedIndication() { - return TextUtils.isEmpty(mTrustGrantedIndication) + return mTrustGrantedIndication == null ? mContext.getString(R.string.keyguard_indication_trust_unlocked) : mTrustGrantedIndication.toString(); } @@ -927,7 +933,7 @@ public class KeyguardIndicationController { return; // udfps affordance is highlighted, no need to show action to unlock } else if (mKeyguardUpdateMonitor.isFaceEnrolled()) { String message = mContext.getString(R.string.keyguard_retry); - mStatusBarKeyguardViewManager.showBouncerMessage(message, mInitialTextColorState); + mStatusBarKeyguardViewManager.setKeyguardMessage(message, mInitialTextColorState); } } else { final boolean canSkipBouncer = mKeyguardUpdateMonitor.getUserCanSkipBouncer( @@ -990,7 +996,7 @@ public class KeyguardIndicationController { mTopIndicationView == null ? null : mTopIndicationView.getText())); pw.println(" computePowerIndication(): " + computePowerIndication()); pw.println(" trustGrantedIndication: " + getTrustGrantedIndication()); - pw.println(" mCoExFaceHelpMsgIdsToShow=" + mCoExFaceHelpMsgIdsToShow); + pw.println(" mCoExFaceHelpMsgIdsToShow=" + mCoExFaceAcquisitionMsgIdsToShow); mRotateTextViewController.dump(pw, args); } @@ -1036,8 +1042,22 @@ public class KeyguardIndicationController { } @Override + public void onBiometricAcquired(BiometricSourceType biometricSourceType, int acquireInfo) { + if (biometricSourceType == FACE) { + mFaceAcquiredMessageDeferral.processFrame(acquireInfo); + } + } + + @Override public void onBiometricHelp(int msgId, String helpString, BiometricSourceType biometricSourceType) { + if (biometricSourceType == FACE) { + mFaceAcquiredMessageDeferral.updateMessage(msgId, helpString); + if (mFaceAcquiredMessageDeferral.shouldDefer(msgId)) { + return; + } + } + // TODO(b/141025588): refactor to reduce repetition of code/comments // Only checking if unlocking with Biometric is allowed (no matter strong or non-strong // as long as primary auth, i.e. PIN/pattern/password, is not required), so it's ok to @@ -1055,19 +1075,24 @@ public class KeyguardIndicationController { final boolean isUnlockWithFingerprintPossible = mKeyguardUpdateMonitor.getCachedIsUnlockWithFingerprintPossible( getCurrentUser()); - if (faceAuthSoftError - && isUnlockWithFingerprintPossible - && !mCoExFaceHelpMsgIdsToShow.contains(msgId)) { + final boolean isCoExFaceAcquisitionMessage = + faceAuthSoftError && isUnlockWithFingerprintPossible; + if (isCoExFaceAcquisitionMessage && !mCoExFaceAcquisitionMsgIdsToShow.contains(msgId)) { if (DEBUG) { Log.d(TAG, "skip showing msgId=" + msgId + " helpString=" + helpString + ", due to co-ex logic"); } return; } else if (mStatusBarKeyguardViewManager.isBouncerShowing()) { - mStatusBarKeyguardViewManager.showBouncerMessage(helpString, + mStatusBarKeyguardViewManager.setKeyguardMessage(helpString, mInitialTextColorState); } else if (mScreenLifecycle.getScreenState() == SCREEN_ON) { - if (faceAuthFailed && isUnlockWithFingerprintPossible) { + if (isCoExFaceAcquisitionMessage && msgId == FACE_ACQUIRED_TOO_DARK) { + showBiometricMessage( + helpString, + mContext.getString(R.string.keyguard_suggest_fingerprint) + ); + } else if (faceAuthFailed && isUnlockWithFingerprintPossible) { showBiometricMessage( mContext.getString(R.string.keyguard_face_failed), mContext.getString(R.string.keyguard_suggest_fingerprint) @@ -1088,43 +1113,65 @@ public class KeyguardIndicationController { } @Override + public void onBiometricAuthFailed(BiometricSourceType biometricSourceType) { + if (biometricSourceType == FACE) { + mFaceAcquiredMessageDeferral.reset(); + } + } + + @Override public void onBiometricError(int msgId, String errString, BiometricSourceType biometricSourceType) { - if (shouldSuppressBiometricError(msgId, biometricSourceType, mKeyguardUpdateMonitor)) { - return; + CharSequence deferredFaceMessage = null; + if (biometricSourceType == FACE) { + if (msgId == BiometricFaceConstants.FACE_ERROR_TIMEOUT) { + deferredFaceMessage = mFaceAcquiredMessageDeferral.getDeferredMessage(); + if (DEBUG) { + Log.d(TAG, "showDeferredFaceMessage msgId=" + deferredFaceMessage); + } + } + mFaceAcquiredMessageDeferral.reset(); } - if (biometricSourceType == FACE - && msgId == FaceManager.FACE_ERROR_UNABLE_TO_PROCESS) { - // suppress all face UNABLE_TO_PROCESS errors + if (shouldSuppressBiometricError(msgId, biometricSourceType, mKeyguardUpdateMonitor)) { if (DEBUG) { - Log.d(TAG, "skip showing FACE_ERROR_UNABLE_TO_PROCESS errString=" - + errString); + Log.d(TAG, "suppressingBiometricError msgId=" + msgId + + " source=" + biometricSourceType); } - } else if (biometricSourceType == FACE - && msgId == FaceManager.FACE_ERROR_TIMEOUT) { + } else if (biometricSourceType == FACE && msgId == FaceManager.FACE_ERROR_TIMEOUT) { + // Co-ex: show deferred message OR nothing if (mKeyguardUpdateMonitor.getCachedIsUnlockWithFingerprintPossible( - getCurrentUser())) { - // no message if fingerprint is also enrolled + KeyguardUpdateMonitor.getCurrentUser())) { + // if we're on the lock screen (bouncer isn't showing), show the deferred msg + if (deferredFaceMessage != null + && !mStatusBarKeyguardViewManager.isBouncerShowing()) { + showBiometricMessage( + deferredFaceMessage, + mContext.getString(R.string.keyguard_suggest_fingerprint) + ); + return; + } + + // otherwise, don't show any message if (DEBUG) { Log.d(TAG, "skip showing FACE_ERROR_TIMEOUT due to co-ex logic"); } return; } - // The face timeout message is not very actionable, let's ask the user to + // Face-only: The face timeout message is not very actionable, let's ask the user to // manually retry. - if (mStatusBarKeyguardViewManager.isShowingAlternateAuth()) { - mStatusBarKeyguardViewManager.showBouncerMessage( - mContext.getResources().getString(R.string.keyguard_try_fingerprint), - mInitialTextColorState + if (deferredFaceMessage != null) { + showBiometricMessage( + deferredFaceMessage, + mContext.getString(R.string.keyguard_unlock) ); } else { // suggest swiping up to unlock (try face auth again or swipe up to bouncer) showActionToUnlock(); } } else if (mStatusBarKeyguardViewManager.isBouncerShowing()) { - mStatusBarKeyguardViewManager.showBouncerMessage(errString, mInitialTextColorState); + mStatusBarKeyguardViewManager.setKeyguardMessage(errString, mInitialTextColorState); } else if (mScreenLifecycle.getScreenState() == SCREEN_ON) { showBiometricMessage(errString); } else { @@ -1134,8 +1181,9 @@ public class KeyguardIndicationController { private boolean shouldSuppressBiometricError(int msgId, BiometricSourceType biometricSourceType, KeyguardUpdateMonitor updateMonitor) { - if (biometricSourceType == BiometricSourceType.FINGERPRINT) + if (biometricSourceType == BiometricSourceType.FINGERPRINT) { return shouldSuppressFingerprintError(msgId, updateMonitor); + } if (biometricSourceType == FACE) { return shouldSuppressFaceError(msgId, updateMonitor); } @@ -1161,7 +1209,8 @@ public class KeyguardIndicationController { // check of whether non-strong biometric is allowed return ((!updateMonitor.isUnlockingWithBiometricAllowed(true /* isStrongBiometric */) && msgId != FaceManager.FACE_ERROR_LOCKOUT_PERMANENT) - || msgId == FaceManager.FACE_ERROR_CANCELED); + || msgId == FaceManager.FACE_ERROR_CANCELED + || msgId == FaceManager.FACE_ERROR_UNABLE_TO_PROCESS); } @@ -1200,10 +1249,11 @@ public class KeyguardIndicationController { boolean isStrongBiometric) { super.onBiometricAuthenticated(userId, biometricSourceType, isStrongBiometric); hideBiometricMessage(); - - if (biometricSourceType == FACE - && !mKeyguardBypassController.canBypass()) { - showActionToUnlock(); + if (biometricSourceType == FACE) { + mFaceAcquiredMessageDeferral.reset(); + if (!mKeyguardBypassController.canBypass()) { + showActionToUnlock(); + } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeQsTransitionController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeQsTransitionController.kt new file mode 100644 index 000000000000..62c225ba0b4e --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeQsTransitionController.kt @@ -0,0 +1,159 @@ +/* + * 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 + +import android.content.Context +import android.util.IndentingPrintWriter +import android.util.MathUtils +import androidx.annotation.FloatRange +import androidx.annotation.Px +import com.android.systemui.R +import com.android.systemui.dump.DumpManager +import com.android.systemui.plugins.qs.QS +import com.android.systemui.statusbar.policy.ConfigurationController +import dagger.assisted.Assisted +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject +import kotlin.math.max + +/** Responsible for the QS components during the lockscreen shade transition. */ +class LockscreenShadeQsTransitionController +@AssistedInject +constructor( + context: Context, + configurationController: ConfigurationController, + dumpManager: DumpManager, + @Assisted private val qsProvider: () -> QS, +) : AbstractLockscreenShadeTransitionController(context, configurationController, dumpManager) { + + private val qs: QS + get() = qsProvider() + + /** + * The progress fraction of the QS transition during lockscreen shade expansion. + * + * Note that this value might be 0 for some time when the expansion is already in progress, + * since there is a transition start delay for QS on some device configurations. For this + * reason, don't use this value to check whether the shade expansion is in progress. + */ + @FloatRange(from = 0.0, to = 1.0) + var qsTransitionFraction = 0f + private set + + /** + * The fraction of the QS "squish" transition progress during lockscreen shade expansion. + * + * Note that in some device configurations (large screens) this value can start at a value + * greater than 0. For this reason don't use this value to check whether the QS transition has + * started or not. + */ + @FloatRange(from = 0.0, to = 1.0) + var qsSquishTransitionFraction = 0f + private set + + /** + * The drag down amount, in pixels __for the QS transition__, also taking into account the + * [qsTransitionStartDelay]. + * + * Since it takes into account the start delay, it is __not__ the same as the raw drag down + * amount from the shade expansion. + */ + @Px private var qsDragDownAmount = 0f + + /** + * Distance it takes for the QS transition to complete during the lockscreen shade expansion. + */ + @Px private var qsTransitionDistance = 0 + + /** Distance delay for the QS transition to start during the lockscreen shade expansion. */ + @Px private var qsTransitionStartDelay = 0 + + /** + * Distance that it takes to complete the QS "squish" transition during the lockscreen shade + * expansion. + */ + @Px private var qsSquishTransitionDistance = 0 + + /** + * Whether the transition to full shade is in progress. Might be `true` even though + * [qsTransitionFraction] is still 0, due to [qsTransitionStartDelay]. + */ + private var isTransitioningToFullShade = false + + /** + * The fraction at which the QS "squish" transition should start during the lockscreen shade + * expansion. + * + * 0 is fully collapsed, 1 is fully expanded. + */ + @FloatRange(from = 0.0, to = 1.0) private var qsSquishStartFraction = 0f + + override fun updateResources() { + qsTransitionDistance = + context.resources.getDimensionPixelSize(R.dimen.lockscreen_shade_qs_transition_distance) + qsTransitionStartDelay = + context.resources.getDimensionPixelSize(R.dimen.lockscreen_shade_qs_transition_delay) + qsSquishTransitionDistance = + context.resources.getDimensionPixelSize( + R.dimen.lockscreen_shade_qs_squish_transition_distance + ) + qsSquishStartFraction = + context.resources.getFloat(R.dimen.lockscreen_shade_qs_squish_start_fraction) + + qsSquishTransitionFraction = max(qsSquishTransitionFraction, qsSquishStartFraction) + } + + override fun onDragDownAmountChanged(dragDownAmount: Float) { + qsDragDownAmount = dragDownAmount - qsTransitionStartDelay + qsTransitionFraction = MathUtils.saturate(qsDragDownAmount / qsTransitionDistance) + qsSquishTransitionFraction = + MathUtils.lerp( + /* start= */ qsSquishStartFraction, + /* stop= */ 1f, + /* amount= */ MathUtils.saturate(qsDragDownAmount / qsSquishTransitionDistance) + ) + isTransitioningToFullShade = dragDownAmount > 0.0f + qs.setTransitionToFullShadeProgress( + isTransitioningToFullShade, + qsTransitionFraction, + qsSquishTransitionFraction + ) + } + + override fun dump(pw: IndentingPrintWriter) { + pw.println( + """ + Resources: + qsTransitionDistance: $qsTransitionDistance + qsTransitionStartDelay: $qsTransitionStartDelay + qsSquishTransitionDistance: $qsSquishTransitionDistance + qsSquishStartFraction: $qsSquishStartFraction + State: + dragDownAmount: $dragDownAmount + qsDragDownAmount: $qsDragDownAmount + qsDragFraction: $qsTransitionFraction + qsSquishFraction: $qsSquishTransitionFraction + isTransitioningToFullShade: $isTransitioningToFullShade + """.trimIndent() + ) + } + + @AssistedFactory + fun interface Factory { + fun create(qsProvider: () -> QS): LockscreenShadeQsTransitionController + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt index d3343dfdcd19..80069319601f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt @@ -11,6 +11,7 @@ import android.util.MathUtils import android.view.MotionEvent import android.view.View import android.view.ViewConfiguration +import androidx.annotation.FloatRange import androidx.annotation.VisibleForTesting import com.android.systemui.Dumpable import com.android.systemui.ExpandHelper @@ -68,7 +69,8 @@ class LockscreenShadeTransitionController @Inject constructor( wakefulnessLifecycle: WakefulnessLifecycle, configurationController: ConfigurationController, falsingManager: FalsingManager, - dumpManager: DumpManager + dumpManager: DumpManager, + qsTransitionControllerFactory: LockscreenShadeQsTransitionController.Factory, ) : Dumpable { private var pulseHeight: Float = 0f @get:VisibleForTesting @@ -120,12 +122,6 @@ class LockscreenShadeTransitionController @Inject constructor( private var notificationShelfTransitionDistance = 0 /** - * Distance that the full shade transition takes in order for the Quick Settings to fully fade - * and expand. - */ - private var qsTransitionDistance = 0 - - /** * Distance that the full shade transition takes in order for depth of the wallpaper to fully * change. */ @@ -188,6 +184,18 @@ class LockscreenShadeTransitionController @Inject constructor( keyguardTransitionControllerFactory.create(notificationPanelController) } + private val qsTransitionController = qsTransitionControllerFactory.create { qS } + + /** See [LockscreenShadeQsTransitionController.qsTransitionFraction].*/ + @get:FloatRange(from = 0.0, to = 1.0) + val qSDragProgress: Float + get() = qsTransitionController.qsTransitionFraction + + /** See [LockscreenShadeQsTransitionController.qsSquishTransitionFraction].*/ + @get:FloatRange(from = 0.0, to = 1.0) + val qsSquishTransitionFraction: Float + get() = qsTransitionController.qsSquishTransitionFraction + /** * [LockScreenShadeOverScroller] property that delegates to either * [SingleShadeLockScreenOverScroller] or [SplitShadeLockScreenOverScroller]. @@ -242,8 +250,6 @@ class LockscreenShadeTransitionController @Inject constructor( R.dimen.lockscreen_shade_transition_by_tap_distance) notificationShelfTransitionDistance = context.resources.getDimensionPixelSize( R.dimen.lockscreen_shade_notif_shelf_transition_distance) - qsTransitionDistance = context.resources.getDimensionPixelSize( - R.dimen.lockscreen_shade_qs_transition_distance) depthControllerTransitionDistance = context.resources.getDimensionPixelSize( R.dimen.lockscreen_shade_depth_controller_transition_distance) udfpsTransitionDistance = context.resources.getDimensionPixelSize( @@ -411,8 +417,7 @@ class LockscreenShadeTransitionController @Inject constructor( MathUtils.saturate(dragDownAmount / notificationShelfTransitionDistance) nsslController.setTransitionToFullShadeAmount(fractionToShade) - qSDragProgress = MathUtils.saturate(dragDownAmount / qsTransitionDistance) - qS.setTransitionToFullShadeAmount(field, qSDragProgress) + qsTransitionController.dragDownAmount = value notificationPanelController.setTransitionToFullShadeAmount(field, false /* animate */, 0 /* delay */) @@ -426,12 +431,6 @@ class LockscreenShadeTransitionController @Inject constructor( } } - /** - * The drag progress of the quick settings drag down amount - */ - var qSDragProgress = 0f - private set - private fun transitionToShadeAmountCommon(dragDownAmount: Float) { if (depthControllerTransitionDistance == 0) { // split shade depthController.transitionToFullShadeProgress = 0f @@ -704,7 +703,6 @@ class LockscreenShadeTransitionController @Inject constructor( it.println("pulseHeight: $pulseHeight") it.println("useSplitShade: $useSplitShade") it.println("dragDownAmount: $dragDownAmount") - it.println("qSDragProgress: $qSDragProgress") it.println("isDragDownAnywhereEnabled: $isDragDownAnywhereEnabled") it.println("isFalsingCheckNeeded: $isFalsingCheckNeeded") it.println("isWakingToShadeLocked: $isWakingToShadeLocked") diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt index f6c4a316b211..cb13fcf246cb 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt @@ -81,7 +81,6 @@ class NotificationShadeDepthController @Inject constructor( } lateinit var root: View - private var blurRoot: View? = null private var keyguardAnimator: Animator? = null private var notificationAnimator: Animator? = null private var updateScheduled: Boolean = false @@ -235,7 +234,7 @@ class NotificationShadeDepthController @Inject constructor( val opaque = scrimsVisible && !blursDisabledForAppLaunch Trace.traceCounter(Trace.TRACE_TAG_APP, "shade_blur_radius", blur) - blurUtils.applyBlur(blurRoot?.viewRootImpl ?: root.viewRootImpl, blur, opaque) + blurUtils.applyBlur(root.viewRootImpl, blur, opaque) lastAppliedBlur = blur wallpaperController.setNotificationShadeZoom(zoomOut) listeners.forEach { @@ -271,7 +270,6 @@ class NotificationShadeDepthController @Inject constructor( override fun onAnimationEnd(animation: Animator?) { keyguardAnimator = null wakeAndUnlockBlurRadius = 0f - scheduleUpdate() } }) start() @@ -302,7 +300,6 @@ class NotificationShadeDepthController @Inject constructor( override fun onDozeAmountChanged(linear: Float, eased: Float) { wakeAndUnlockBlurRadius = blurUtils.blurRadiusOfRatio(eased) - scheduleUpdate() } } @@ -439,12 +436,11 @@ class NotificationShadeDepthController @Inject constructor( shadeAnimation.animateTo(blurUtils.blurRadiusOfRatio(targetBlurNormalized).toInt()) } - private fun scheduleUpdate(viewToBlur: View? = null) { + private fun scheduleUpdate() { if (updateScheduled) { return } updateScheduled = true - blurRoot = viewToBlur choreographer.postFrameCallback(updateBlurCallback) } @@ -495,16 +491,11 @@ class NotificationShadeDepthController @Inject constructor( */ private var pendingRadius = -1 - /** - * View on {@link Surface} that wants depth. - */ - private var view: View? = null - private var springAnimation = SpringAnimation(this, object : FloatPropertyCompat<DepthAnimation>("blurRadius") { override fun setValue(rect: DepthAnimation?, value: Float) { radius = value - scheduleUpdate(view) + scheduleUpdate() } override fun getValue(rect: DepthAnimation?): Float { @@ -519,11 +510,10 @@ class NotificationShadeDepthController @Inject constructor( springAnimation.addEndListener { _, _, _, _ -> pendingRadius = -1 } } - fun animateTo(newRadius: Int, viewToBlur: View? = null) { - if (pendingRadius == newRadius && view == viewToBlur) { + fun animateTo(newRadius: Int) { + if (pendingRadius == newRadius) { return } - view = viewToBlur pendingRadius = newRadius springAnimation.animateToFinalPosition(newRadius.toFloat()) } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java index cea3debe6379..41c0367772b5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java @@ -16,6 +16,8 @@ package com.android.systemui.statusbar; +import static com.android.keyguard.BouncerPanelExpansionCalculator.aboutToShowBouncerProgress; + import android.content.Context; import android.content.res.Configuration; import android.content.res.Resources; @@ -90,6 +92,12 @@ public class NotificationShelf extends ActivatableNotificationView implements super(context, attrs); } + @VisibleForTesting + public NotificationShelf(Context context, AttributeSet attrs, boolean showNotificationShelf) { + super(context, attrs); + mShowNotificationShelf = showNotificationShelf; + } + @Override @VisibleForTesting public void onFinishInflate() { @@ -175,7 +183,11 @@ public class NotificationShelf extends ActivatableNotificationView implements if (ambientState.isExpansionChanging() && !ambientState.isOnKeyguard()) { float expansion = ambientState.getExpansionFraction(); - viewState.alpha = ShadeInterpolation.getContentAlpha(expansion); + if (ambientState.isBouncerInTransit()) { + viewState.alpha = aboutToShowBouncerProgress(expansion); + } else { + viewState.alpha = ShadeInterpolation.getContentAlpha(expansion); + } } else { viewState.alpha = 1f - ambientState.getHideAmount(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/VibratorHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/VibratorHelper.java index c74621df94c9..258f9fc5449f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/VibratorHelper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/VibratorHelper.java @@ -38,7 +38,7 @@ import javax.inject.Inject; public class VibratorHelper { private final Vibrator mVibrator; - private static final VibrationAttributes TOUCH_VIBRATION_ATTRIBUTES = + public static final VibrationAttributes TOUCH_VIBRATION_ATTRIBUTES = VibrationAttributes.createForUsage(VibrationAttributes.USAGE_TOUCH); private final Executor mExecutor; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt index 31b21c9b5321..553826dda919 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationLaunchAnimatorController.kt @@ -136,7 +136,7 @@ class NotificationLaunchAnimatorController( headsUpManager.removeNotification(notificationKey, true /* releaseImmediately */, animate) } - override fun onLaunchAnimationCancelled() { + override fun onLaunchAnimationCancelled(newKeyguardOccludedState: Boolean?) { // TODO(b/184121838): Should we call InteractionJankMonitor.cancel if the animation started // here? notificationShadeWindowViewController.setExpandAnimationRunning(false) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/BubbleCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/BubbleCoordinator.java index 3627b4084ec7..52f4c1cd054b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/BubbleCoordinator.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/BubbleCoordinator.java @@ -144,11 +144,6 @@ public class BubbleCoordinator implements Coordinator { public void invalidateNotifications(String reason) { mNotifFilter.invalidateList(reason); } - - @Override - public void maybeCancelSummary(NotificationEntry entry) { - // no-op - } }; private boolean isInterceptingDismissal(NotificationEntry entry) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java index ba26cfaa30b4..df81c0ed3a61 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java @@ -1369,6 +1369,8 @@ public class NotificationContentView extends FrameLayout implements Notification } ImageView bubbleButton = layout.findViewById(com.android.internal.R.id.bubble_button); View actionContainer = layout.findViewById(com.android.internal.R.id.actions_container); + LinearLayout actionListMarginTarget = layout.findViewById( + com.android.internal.R.id.notification_action_list_margin_target); if (bubbleButton == null || actionContainer == null) { return; } @@ -1393,6 +1395,16 @@ public class NotificationContentView extends FrameLayout implements Notification bubbleButton.setOnClickListener(mContainingNotification.getBubbleClickListener()); bubbleButton.setVisibility(VISIBLE); actionContainer.setVisibility(VISIBLE); + // Set notification_action_list_margin_target's bottom margin to 0 when showing bubble + if (actionListMarginTarget != null) { + ViewGroup.LayoutParams lp = actionListMarginTarget.getLayoutParams(); + if (lp instanceof ViewGroup.MarginLayoutParams) { + final ViewGroup.MarginLayoutParams mlp = (ViewGroup.MarginLayoutParams) lp; + if (mlp.bottomMargin > 0) { + mlp.setMargins(mlp.leftMargin, mlp.topMargin, mlp.rightMargin, 0); + } + } + } } else { bubbleButton.setVisibility(GONE); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java index ea28452d63c4..ce465bcfb42d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java @@ -23,6 +23,8 @@ import android.annotation.Nullable; import android.content.Context; import android.util.MathUtils; +import androidx.annotation.VisibleForTesting; + import com.android.systemui.Dumpable; import com.android.systemui.R; import com.android.systemui.dagger.SysUISingleton; @@ -137,7 +139,17 @@ public class AmbientState implements Dumpable { * True right after we swipe up on lockscreen and have not finished the fling down that follows. * False when we stop flinging or leave lockscreen. */ - private boolean mNeedFlingAfterLockscreenSwipeUp = false; + private boolean mIsFlingRequiredAfterLockScreenSwipeUp = false; + + @VisibleForTesting + public boolean isFlingRequiredAfterLockScreenSwipeUp() { + return mIsFlingRequiredAfterLockScreenSwipeUp; + } + + @VisibleForTesting + public void setFlingRequiredAfterLockScreenSwipeUp(boolean value) { + mIsFlingRequiredAfterLockScreenSwipeUp = value; + } /** * @return Height of the notifications panel without top padding when expansion completes. @@ -181,7 +193,7 @@ public class AmbientState implements Dumpable { public void setSwipingUp(boolean isSwipingUp) { if (!isSwipingUp && mIsSwipingUp) { // Just stopped swiping up. - mNeedFlingAfterLockscreenSwipeUp = true; + mIsFlingRequiredAfterLockScreenSwipeUp = true; } mIsSwipingUp = isSwipingUp; } @@ -196,10 +208,10 @@ public class AmbientState implements Dumpable { /** * @param isFlinging Whether we are flinging the shade open or closed. */ - public void setIsFlinging(boolean isFlinging) { + public void setFlinging(boolean isFlinging) { if (isOnKeyguard() && !isFlinging && mIsFlinging) { // Just stopped flinging. - mNeedFlingAfterLockscreenSwipeUp = false; + mIsFlingRequiredAfterLockScreenSwipeUp = false; } mIsFlinging = isFlinging; } @@ -508,7 +520,7 @@ public class AmbientState implements Dumpable { public void setStatusBarState(int statusBarState) { if (mStatusBarState != StatusBarState.KEYGUARD) { - mNeedFlingAfterLockscreenSwipeUp = false; + mIsFlingRequiredAfterLockScreenSwipeUp = false; } mStatusBarState = statusBarState; } @@ -576,7 +588,7 @@ public class AmbientState implements Dumpable { * @return Whether we need to do a fling down after swiping up on lockscreen. */ public boolean isFlingingAfterSwipeUpOnLockscreen() { - return mIsFlinging && mNeedFlingAfterLockscreenSwipeUp; + return mIsFlinging && mIsFlingRequiredAfterLockScreenSwipeUp; } /** @@ -744,7 +756,8 @@ public class AmbientState implements Dumpable { pw.println("mIsSwipingUp=" + mIsSwipingUp); pw.println("mPanelTracking=" + mPanelTracking); pw.println("mIsFlinging=" + mIsFlinging); - pw.println("mNeedFlingAfterLockscreenSwipeUp=" + mNeedFlingAfterLockscreenSwipeUp); + pw.println("mIsFlingRequiredAfterLockScreenSwipeUp=" + + mIsFlingRequiredAfterLockScreenSwipeUp); pw.println("mZDistanceBetweenElements=" + mZDistanceBetweenElements); pw.println("mBaseZHeight=" + mBaseZHeight); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java index 1fb265fea0b1..5fbaa515d5d7 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java @@ -2794,10 +2794,9 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable if (mDebugRemoveAnimation) { Log.d(TAG, "generateRemove " + key + "\nmIsExpanded " + mIsExpanded - + "\nmAnimationsEnabled " + mAnimationsEnabled - + "\n!invisible group " + !isChildInInvisibleGroup(child)); + + "\nmAnimationsEnabled " + mAnimationsEnabled); } - if (mIsExpanded && mAnimationsEnabled && !isChildInInvisibleGroup(child)) { + if (mIsExpanded && mAnimationsEnabled) { if (!mChildrenToAddAnimated.contains(child)) { if (mDebugRemoveAnimation) { Log.d(TAG, "needsAnimation = true " + key); @@ -2845,26 +2844,6 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable return hasAddEvent && mAddedHeadsUpChildren.contains(child); } - // TODO (b/162832756): remove since this won't happen in new pipeline (we prune groups in - // ShadeListBuilder) - /** - * @param child the child to query - * @return whether a view is not a top level child but a child notification and that group is - * not expanded - */ - @ShadeViewRefactor(RefactorComponent.ADAPTER) - private boolean isChildInInvisibleGroup(View child) { - if (child instanceof ExpandableNotificationRow) { - ExpandableNotificationRow row = (ExpandableNotificationRow) child; - NotificationEntry groupSummary = - mGroupMembershipManager.getGroupSummary(row.getEntry()); - if (groupSummary != null && groupSummary.getRow() != row) { - return row.getVisibility() == View.INVISIBLE; - } - } - return false; - } - /** * Updates the scroll position when a child was removed * @@ -5042,7 +5021,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable @ShadeViewRefactor(RefactorComponent.SHADE_VIEW) public void setPanelFlinging(boolean flinging) { - mAmbientState.setIsFlinging(flinging); + mAmbientState.setFlinging(flinging); if (!flinging) { // re-calculate the stack height which was frozen while flinging updateStackPosition(); 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 8bd7886c662e..fe431377f854 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java @@ -23,7 +23,6 @@ import android.content.res.Resources; import android.hardware.biometrics.BiometricFaceConstants; import android.hardware.biometrics.BiometricFingerprintConstants; import android.hardware.biometrics.BiometricSourceType; -import android.hardware.face.FaceManager; import android.hardware.fingerprint.FingerprintManager; import android.metrics.LogMaker; import android.os.Handler; @@ -177,7 +176,6 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp private KeyguardViewMediator mKeyguardViewMediator; private ScrimController mScrimController; private PendingAuthenticated mPendingAuthenticated = null; - private boolean mPendingShowBouncer; private boolean mHasScreenTurnedOnSinceAuthenticating; private boolean mFadedAwayAfterWakeAndUnlock; private BiometricModeListener mBiometricModeListener; @@ -474,31 +472,22 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp break; case MODE_UNLOCK_COLLAPSING: Trace.beginSection("MODE_UNLOCK_COLLAPSING"); - if (!wasDeviceInteractive) { - mPendingShowBouncer = true; - } else { - // If the keyguard unlock controller is going to handle the unlock animation, it - // will fling the panel collapsed when it's ready. - if (!mKeyguardUnlockAnimationController.willHandleUnlockAnimation()) { - mShadeController.animateCollapsePanels( - CommandQueue.FLAG_EXCLUDE_NONE, - true /* force */, - false /* delayed */, - BIOMETRIC_COLLAPSE_SPEEDUP_FACTOR); - } - mPendingShowBouncer = false; - mKeyguardViewController.notifyKeyguardAuthenticated( - false /* strongAuth */); + // If the keyguard unlock controller is going to handle the unlock animation, it + // will fling the panel collapsed when it's ready. + if (!mKeyguardUnlockAnimationController.willHandleUnlockAnimation()) { + mShadeController.animateCollapsePanels( + CommandQueue.FLAG_EXCLUDE_NONE, + true /* force */, + false /* delayed */, + BIOMETRIC_COLLAPSE_SPEEDUP_FACTOR); } + mKeyguardViewController.notifyKeyguardAuthenticated( + false /* strongAuth */); Trace.endSection(); break; case MODE_SHOW_BOUNCER: Trace.beginSection("MODE_SHOW_BOUNCER"); - if (!wasDeviceInteractive) { - mPendingShowBouncer = true; - } else { - showBouncer(); - } + mKeyguardViewController.showBouncer(true); Trace.endSection(); break; case MODE_WAKE_AND_UNLOCK_FROM_DREAM: @@ -536,15 +525,6 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp } } - private void showBouncer() { - if (mMode == MODE_SHOW_BOUNCER) { - mKeyguardViewController.showBouncer(true); - } - mShadeController.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE, true /* force */, - false /* delayed */, BIOMETRIC_COLLAPSE_SPEEDUP_FACTOR); - mPendingShowBouncer = false; - } - public boolean hasPendingAuthentication() { return mPendingAuthenticated != null && mUpdateMonitor @@ -702,10 +682,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp final boolean fingerprintLockout = biometricSourceType == BiometricSourceType.FINGERPRINT && (msgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT || msgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT); - final boolean faceLockout = biometricSourceType == BiometricSourceType.FACE - && (msgId == FaceManager.FACE_ERROR_LOCKOUT - || msgId == FaceManager.FACE_ERROR_LOCKOUT_PERMANENT); - if (fingerprintLockout || faceLockout) { + if (fingerprintLockout) { startWakeAndUnlock(MODE_SHOW_BOUNCER); UI_EVENT_LOGGER.log(BiometricUiEvent.BIOMETRIC_BOUNCER_SHOWN, getSessionId()); } @@ -771,13 +748,6 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp final WakefulnessLifecycle.Observer mWakefulnessObserver = new WakefulnessLifecycle.Observer() { @Override - public void onFinishedWakingUp() { - if (mPendingShowBouncer) { - BiometricUnlockController.this.showBouncer(); - } - } - - @Override public void onStartedGoingToSleep() { resetMode(); mFadedAwayAfterWakeAndUnlock = false; diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java index 20b6d0b49fbc..f37243adfa9e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java @@ -40,6 +40,7 @@ import androidx.lifecycle.LifecycleOwner; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.statusbar.RegisterStatusBarResult; +import com.android.keyguard.AuthKeyguardMessageArea; import com.android.keyguard.FaceAuthApiRequestReason; import com.android.systemui.Dumpable; import com.android.systemui.animation.ActivityLaunchAnimator; @@ -220,6 +221,9 @@ public interface CentralSurfaces extends Dumpable, ActivityStarter, LifecycleOwn ViewGroup getBouncerContainer(); + /** Get the Keyguard Message Area that displays auth messages. */ + AuthKeyguardMessageArea getKeyguardMessageArea(); + int getStatusBarHeight(); void updateQsExpansionEnabled(); @@ -390,8 +394,6 @@ public interface CentralSurfaces extends Dumpable, ActivityStarter, LifecycleOwn void fadeKeyguardAfterLaunchTransition(Runnable beforeFading, Runnable endRunnable, Runnable cancelRunnable); - void fadeKeyguardWhilePulsing(); - void animateKeyguardUnoccluding(); void startLaunchTransitionTimeout(); 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 6426aef43799..0b63bbfec877 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java @@ -100,11 +100,14 @@ import android.view.MotionEvent; import android.view.ThreadedRenderer; import android.view.View; import android.view.ViewGroup; +import android.view.ViewRootImpl; import android.view.WindowInsetsController.Appearance; import android.view.WindowManager; import android.view.WindowManagerGlobal; import android.view.accessibility.AccessibilityManager; import android.widget.DateTimeView; +import android.window.OnBackInvokedCallback; +import android.window.OnBackInvokedDispatcher; import androidx.annotation.NonNull; import androidx.lifecycle.Lifecycle; @@ -120,6 +123,7 @@ import com.android.internal.logging.UiEventLoggerImpl; import com.android.internal.logging.nano.MetricsProto.MetricsEvent; import com.android.internal.statusbar.IStatusBarService; import com.android.internal.statusbar.RegisterStatusBarResult; +import com.android.keyguard.AuthKeyguardMessageArea; import com.android.keyguard.FaceAuthApiRequestReason; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.KeyguardUpdateMonitorCallback; @@ -525,10 +529,17 @@ public class CentralSurfacesImpl extends CoreStartable implements private CentralSurfacesComponent mCentralSurfacesComponent; // Flags for disabling the status bar - // Two variables becaseu the first one evidently ran out of room for new flags. + // Two variables because the first one evidently ran out of room for new flags. private int mDisabled1 = 0; private int mDisabled2 = 0; + /** + * This keeps track of whether we have (or haven't) registered the predictive back callback. + * Since we can have visible -> visible transitions, we need to avoid + * double-registering (or double-unregistering) our callback. + */ + private boolean mIsBackCallbackRegistered = false; + /** @see android.view.WindowInsetsController#setSystemBarsAppearance(int, int) */ private @Appearance int mAppearance; @@ -652,6 +663,12 @@ public class CentralSurfacesImpl extends CoreStartable implements private final InteractionJankMonitor mJankMonitor; + private final OnBackInvokedCallback mOnBackInvokedCallback = () -> { + if (DEBUG) { + Log.d(TAG, "mOnBackInvokedCallback() called"); + } + onBackPressed(); + }; /** * Public constructor for CentralSurfaces. @@ -1582,6 +1599,11 @@ public class CentralSurfacesImpl extends CoreStartable implements } @Override + public AuthKeyguardMessageArea getKeyguardMessageArea() { + return mNotificationShadeWindowViewController.getKeyguardMessageArea(); + } + + @Override public int getStatusBarHeight() { return mStatusBarWindowController.getStatusBarHeight(); } @@ -1715,13 +1737,18 @@ public class CentralSurfacesImpl extends CoreStartable implements } @Override - public void onLaunchAnimationCancelled() { + public void onLaunchAnimationCancelled(@Nullable Boolean newKeyguardOccludedState) { + if (newKeyguardOccludedState != null) { + mKeyguardViewMediator.setOccluded( + newKeyguardOccludedState, false /* animate */); + } + // Set mIsLaunchingActivityOverLockscreen to false before actually finishing the // animation so that we can assume that mIsLaunchingActivityOverLockscreen // being true means that we will collapse the shade (or at least run the // post collapse runnables) later on. CentralSurfacesImpl.this.mIsLaunchingActivityOverLockscreen = false; - getDelegate().onLaunchAnimationCancelled(); + getDelegate().onLaunchAnimationCancelled(newKeyguardOccludedState); } }; } else if (dismissShade) { @@ -2745,9 +2772,38 @@ public class CentralSurfacesImpl extends CoreStartable implements if (visibleToUser) { handleVisibleToUserChangedImpl(visibleToUser); mNotificationLogger.startNotificationLogging(); + + if (!mIsBackCallbackRegistered) { + ViewRootImpl viewRootImpl = getViewRootImpl(); + if (viewRootImpl != null) { + viewRootImpl.getOnBackInvokedDispatcher() + .registerOnBackInvokedCallback(OnBackInvokedDispatcher.PRIORITY_DEFAULT, + mOnBackInvokedCallback); + mIsBackCallbackRegistered = true; + if (DEBUG) Log.d(TAG, "is now VISIBLE to user AND callback registered"); + } + } else { + if (DEBUG) Log.d(TAG, "is now VISIBLE to user, BUT callback ALREADY unregistered"); + } } else { mNotificationLogger.stopNotificationLogging(); handleVisibleToUserChangedImpl(visibleToUser); + + if (mIsBackCallbackRegistered) { + ViewRootImpl viewRootImpl = getViewRootImpl(); + if (viewRootImpl != null) { + viewRootImpl.getOnBackInvokedDispatcher() + .unregisterOnBackInvokedCallback(mOnBackInvokedCallback); + mIsBackCallbackRegistered = false; + if (DEBUG) Log.d(TAG, "is NOT VISIBLE to user, AND callback unregistered"); + } + } else { + if (DEBUG) { + Log.d(TAG, + "is NOT VISIBLE to user, BUT NO callback (or callback ALREADY " + + "unregistered)"); + } + } } } @@ -3019,19 +3075,6 @@ public class CentralSurfacesImpl extends CoreStartable implements } /** - * Fades the content of the Keyguard while we are dozing and makes it invisible when finished - * fading. - */ - @Override - public void fadeKeyguardWhilePulsing() { - mNotificationPanelViewController.fadeOut(0, FADE_KEYGUARD_DURATION_PULSING, - ()-> { - hideKeyguard(); - mStatusBarKeyguardViewManager.onKeyguardFadedAway(); - }).start(); - } - - /** * Plays the animation when an activity that was occluding Keyguard goes away. */ @Override @@ -3320,14 +3363,12 @@ public class CentralSurfacesImpl extends CoreStartable implements // show the bouncer/lockscreen. if (!mKeyguardViewMediator.isHiding() && !mKeyguardUnlockAnimationController.isPlayingCannedUnlockAnimation()) { - if (mState == StatusBarState.SHADE_LOCKED - && mKeyguardUpdateMonitor.isUdfpsEnrolled()) { + if (mState == StatusBarState.SHADE_LOCKED) { // shade is showing while locked on the keyguard, so go back to showing the // lock screen where users can use the UDFPS affordance to enter the device mStatusBarKeyguardViewManager.reset(true); - } else if ((mState == StatusBarState.KEYGUARD - && !mStatusBarKeyguardViewManager.bouncerIsOrWillBeShowing()) - || mState == StatusBarState.SHADE_LOCKED) { + } else if (mState == StatusBarState.KEYGUARD + && !mStatusBarKeyguardViewManager.bouncerIsOrWillBeShowing()) { mStatusBarKeyguardViewManager.showGenericBouncer(true /* scrimmed */); } } @@ -3473,6 +3514,12 @@ public class CentralSurfacesImpl extends CoreStartable implements return mNotificationPanelViewController.getKeyguardBottomAreaView(); } + protected ViewRootImpl getViewRootImpl() { + NotificationShadeWindowView nswv = getNotificationShadeWindowView(); + if (nswv != null) return nswv.getViewRootImpl(); + + return null; + } /** * Propagation of the bouncer state, indicating that it's fully visible. */ @@ -3581,6 +3628,7 @@ public class CentralSurfacesImpl extends CoreStartable implements dismissVolumeDialog(); mWakeUpCoordinator.setFullyAwake(false); mKeyguardBypassController.onStartedGoingToSleep(); + mStatusBarTouchableRegionManager.updateTouchableRegion(); // The unlocked screen off and fold to aod animations might use our LightRevealScrim - // we need to be expanded for it to be visible. @@ -3609,6 +3657,7 @@ public class CentralSurfacesImpl extends CoreStartable implements // once we fully woke up. updateRevealEffect(true /* wakingUp */); updateNotificationPanelTouchState(); + mStatusBarTouchableRegionManager.updateTouchableRegion(); // If we are waking up during the screen off animation, we should undo making the // expanded visible (we did that so the LightRevealScrim would be visible). @@ -3790,6 +3839,12 @@ public class CentralSurfacesImpl extends CoreStartable implements updateScrimController(); } + @VisibleForTesting + public void setNotificationShadeWindowViewController( + NotificationShadeWindowViewController nswvc) { + mNotificationShadeWindowViewController = nswvc; + } + /** * Set the amount of progress we are currently in if we're transitioning to the full shade. * 0.0f means we're not transitioning yet, while 1 means we're all the way in the full diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java index ddff7d8e32af..24ce5e98bdd0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeServiceHost.java @@ -28,8 +28,6 @@ import android.util.Log; import android.view.MotionEvent; import android.view.View; -import androidx.annotation.Nullable; - import com.android.internal.annotations.VisibleForTesting; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.systemui.assist.AssistManager; @@ -50,11 +48,9 @@ import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.policy.BatteryController; import com.android.systemui.statusbar.policy.DeviceProvisionedController; -import com.android.systemui.unfold.FoldAodAnimationController; -import com.android.systemui.unfold.SysUIUnfoldComponent; +import com.android.systemui.util.Assert; import java.util.ArrayList; -import java.util.Optional; import javax.inject.Inject; @@ -80,8 +76,6 @@ public final class DozeServiceHost implements DozeHost { private final WakefulnessLifecycle mWakefulnessLifecycle; private final SysuiStatusBarStateController mStatusBarStateController; private final DeviceProvisionedController mDeviceProvisionedController; - @Nullable - private final FoldAodAnimationController mFoldAodAnimationController; private final HeadsUpManagerPhone mHeadsUpManagerPhone; private final BatteryController mBatteryController; private final ScrimController mScrimController; @@ -114,7 +108,6 @@ public final class DozeServiceHost implements DozeHost { Lazy<AssistManager> assistManagerLazy, DozeScrimController dozeScrimController, KeyguardUpdateMonitor keyguardUpdateMonitor, PulseExpansionHandler pulseExpansionHandler, - Optional<SysUIUnfoldComponent> sysUIUnfoldComponent, NotificationShadeWindowController notificationShadeWindowController, NotificationWakeUpCoordinator notificationWakeUpCoordinator, AuthController authController, @@ -138,8 +131,6 @@ public final class DozeServiceHost implements DozeHost { mNotificationWakeUpCoordinator = notificationWakeUpCoordinator; mAuthController = authController; mNotificationIconAreaController = notificationIconAreaController; - mFoldAodAnimationController = sysUIUnfoldComponent - .map(SysUIUnfoldComponent::getFoldAodAnimationController).orElse(null); } // TODO: we should try to not pass status bar in here if we can avoid it. @@ -167,6 +158,7 @@ public final class DozeServiceHost implements DozeHost { } void firePowerSaveChanged(boolean active) { + Assert.isMainThread(); for (Callback callback : mCallbacks) { callback.onPowerSaveChanged(active); } @@ -177,6 +169,7 @@ public final class DozeServiceHost implements DozeHost { entry.setPulseSuppressed(true); mNotificationIconAreaController.updateAodNotificationIcons(); }; + Assert.isMainThread(); for (Callback callback : mCallbacks) { callback.onNotificationAlerted(pulseSuppressedListener); } @@ -193,11 +186,13 @@ public final class DozeServiceHost implements DozeHost { @Override public void addCallback(@NonNull Callback callback) { + Assert.isMainThread(); mCallbacks.add(callback); } @Override public void removeCallback(@NonNull Callback callback) { + Assert.isMainThread(); mCallbacks.remove(callback); } @@ -212,12 +207,10 @@ public final class DozeServiceHost implements DozeHost { } void updateDozing() { - // When in wake-and-unlock while pulsing, keep dozing state until fully unlocked. - boolean - dozing = - mDozingRequested && mStatusBarStateController.getState() == StatusBarState.KEYGUARD - || mBiometricUnlockControllerLazy.get().getMode() - == BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING; + Assert.isMainThread(); + + boolean dozing = + mDozingRequested && mStatusBarStateController.getState() == StatusBarState.KEYGUARD; // When in wake-and-unlock we may not have received a change to StatusBarState // but we still should not be dozing, manually set to false. if (mBiometricUnlockControllerLazy.get().getMode() @@ -225,10 +218,10 @@ public final class DozeServiceHost implements DozeHost { dozing = false; } - mStatusBarStateController.setIsDozing(dozing); - if (mFoldAodAnimationController != null) { - mFoldAodAnimationController.setIsDozing(dozing); + for (Callback callback : mCallbacks) { + callback.onDozingChanged(dozing); } + mStatusBarStateController.setIsDozing(dozing); } @Override @@ -452,6 +445,7 @@ public final class DozeServiceHost implements DozeHost { return; } mAlwaysOnSuppressed = suppressed; + Assert.isMainThread(); for (Callback callback : mCallbacks) { callback.onAlwaysOnSuppressedChanged(suppressed); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java index 6bfb0dad28f7..90d0b697337a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java @@ -115,9 +115,7 @@ public class HeadsUpTouchHelper implements Gefingerpoken { mInitialTouchY = y; int startHeight = (int) (mPickedChild.getActualHeight() + mPickedChild.getTranslationY()); - float maxPanelHeight = mPanel.getMaxPanelHeight(); - mPanel.setPanelScrimMinFraction(maxPanelHeight > 0f - ? (float) startHeight / maxPanelHeight : 0f); + mPanel.setHeadsUpDraggingStartingHeight(startHeight); mPanel.startExpandMotion(x, y, true /* startTracking */, startHeight); // This call needs to be after the expansion start otherwise we will get a // flicker of one frame as it's not expanded yet. diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java deleted file mode 100644 index dc77d10486a3..000000000000 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java +++ /dev/null @@ -1,682 +0,0 @@ -/* - * Copyright (C) 2014 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.phone; - -import static com.android.internal.util.Preconditions.checkNotNull; -import static com.android.systemui.controls.dagger.ControlsComponent.Visibility.AVAILABLE; -import static com.android.systemui.doze.util.BurnInHelperKt.getBurnInOffset; -import static com.android.systemui.wallet.controller.QuickAccessWalletController.WalletChangeEvent.DEFAULT_PAYMENT_APP_CHANGE; -import static com.android.systemui.wallet.controller.QuickAccessWalletController.WalletChangeEvent.WALLET_PREFERENCE_CHANGE; - -import android.app.ActivityTaskManager; -import android.app.admin.DevicePolicyManager; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.res.ColorStateList; -import android.content.res.Configuration; -import android.graphics.drawable.Drawable; -import android.os.RemoteException; -import android.os.UserHandle; -import android.service.quickaccesswallet.GetWalletCardsError; -import android.service.quickaccesswallet.GetWalletCardsResponse; -import android.service.quickaccesswallet.QuickAccessWalletClient; -import android.util.AttributeSet; -import android.util.Log; -import android.util.TypedValue; -import android.view.View; -import android.view.ViewGroup; -import android.view.ViewPropertyAnimator; -import android.view.WindowInsets; -import android.widget.FrameLayout; -import android.widget.ImageView; -import android.widget.TextView; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import com.android.settingslib.Utils; -import com.android.systemui.Dependency; -import com.android.systemui.R; -import com.android.systemui.animation.ActivityLaunchAnimator; -import com.android.systemui.animation.Interpolators; -import com.android.systemui.controls.dagger.ControlsComponent; -import com.android.systemui.controls.management.ControlsListingController; -import com.android.systemui.controls.ui.ControlsActivity; -import com.android.systemui.controls.ui.ControlsUiController; -import com.android.systemui.keyguard.ui.binder.KeyguardBottomAreaViewBinder; -import com.android.systemui.keyguard.ui.viewmodel.KeyguardBottomAreaViewModel; -import com.android.systemui.plugins.ActivityStarter; -import com.android.systemui.plugins.FalsingManager; -import com.android.systemui.qrcodescanner.controller.QRCodeScannerController; -import com.android.systemui.statusbar.policy.KeyguardStateController; -import com.android.systemui.wallet.controller.QuickAccessWalletController; - -import java.util.ArrayList; -import java.util.List; - -/** - * Implementation for the bottom area of the Keyguard, including camera/phone affordance and status - * text. - */ -public class KeyguardBottomAreaView extends FrameLayout { - - private static final String TAG = "CentralSurfaces/KeyguardBottomAreaView"; - private static final int DOZE_ANIMATION_ELEMENT_DURATION = 250; - - private ImageView mWalletButton; - private ImageView mQRCodeScannerButton; - private ImageView mControlsButton; - private boolean mHasCard = false; - private final WalletCardRetriever mCardRetriever = new WalletCardRetriever(); - private QuickAccessWalletController mQuickAccessWalletController; - private QRCodeScannerController mQRCodeScannerController; - private ControlsComponent mControlsComponent; - private boolean mControlServicesAvailable = false; - - @Nullable private View mAmbientIndicationArea; - private ViewGroup mIndicationArea; - private TextView mIndicationText; - private TextView mIndicationTextBottom; - private ViewGroup mOverlayContainer; - - private ActivityStarter mActivityStarter; - private KeyguardStateController mKeyguardStateController; - private FalsingManager mFalsingManager; - - private boolean mDozing; - private int mIndicationBottomMargin; - private int mIndicationPadding; - private float mDarkAmount; - private int mBurnInXOffset; - private int mBurnInYOffset; - - private final ControlsListingController.ControlsListingCallback mListingCallback = - serviceInfos -> post(() -> { - boolean available = !serviceInfos.isEmpty(); - - if (available != mControlServicesAvailable) { - mControlServicesAvailable = available; - updateControlsVisibility(); - updateAffordanceColors(); - } - }); - - private final KeyguardStateController.Callback mKeyguardStateCallback = - new KeyguardStateController.Callback() { - @Override - public void onKeyguardShowingChanged() { - if (mKeyguardStateController.isShowing()) { - if (mQuickAccessWalletController != null) { - mQuickAccessWalletController.queryWalletCards(mCardRetriever); - } - } - } - }; - - @Nullable private KeyguardBottomAreaViewBinder.Binding mBinding; - private boolean mUsesBinder; - - public KeyguardBottomAreaView(Context context) { - this(context, null); - } - - public KeyguardBottomAreaView(Context context, AttributeSet attrs) { - this(context, attrs, 0); - } - - public KeyguardBottomAreaView(Context context, AttributeSet attrs, int defStyleAttr) { - this(context, attrs, defStyleAttr, 0); - } - - public KeyguardBottomAreaView(Context context, AttributeSet attrs, int defStyleAttr, - int defStyleRes) { - super(context, attrs, defStyleAttr, defStyleRes); - } - - /** - * Initializes the view. - */ - public void init( - final KeyguardBottomAreaViewModel viewModel, - final FalsingManager falsingManager) { - Log.i(TAG, System.identityHashCode(this) + " initialized with a binder"); - mUsesBinder = true; - mBinding = KeyguardBottomAreaViewBinder.bind(this, viewModel, falsingManager); - } - - /** - * Initializes the {@link KeyguardBottomAreaView} with the given dependencies - * - * @deprecated Use - * {@link #init(KeyguardBottomAreaViewModel, FalsingManager)} instead - */ - @Deprecated - public void init( - FalsingManager falsingManager, - QuickAccessWalletController controller, - ControlsComponent controlsComponent, - QRCodeScannerController qrCodeScannerController) { - if (mUsesBinder) { - return; - } - - Log.i(TAG, "initialized without a binder"); - mFalsingManager = falsingManager; - - mQuickAccessWalletController = controller; - mQuickAccessWalletController.setupWalletChangeObservers( - mCardRetriever, WALLET_PREFERENCE_CHANGE, DEFAULT_PAYMENT_APP_CHANGE); - mQuickAccessWalletController.updateWalletPreference(); - mQuickAccessWalletController.queryWalletCards(mCardRetriever); - updateWalletVisibility(); - - mControlsComponent = controlsComponent; - mControlsComponent.getControlsListingController().ifPresent( - c -> c.addCallback(mListingCallback)); - - mQRCodeScannerController = qrCodeScannerController; - mQRCodeScannerController.registerQRCodeScannerChangeObservers( - QRCodeScannerController.DEFAULT_QR_CODE_SCANNER_CHANGE, - QRCodeScannerController.QR_CODE_SCANNER_PREFERENCE_CHANGE); - updateQRCodeButtonVisibility(); - - updateAffordanceColors(); - } - - /** - * Initializes this instance of {@link KeyguardBottomAreaView} based on the given instance of - * another {@link KeyguardBottomAreaView} - */ - public void initFrom(KeyguardBottomAreaView oldBottomArea) { - if (mUsesBinder) { - return; - } - - // if it exists, continue to use the original ambient indication container - // instead of the newly inflated one - if (mAmbientIndicationArea != null) { - // remove old ambient indication from its parent - View originalAmbientIndicationView = - oldBottomArea.findViewById(R.id.ambient_indication_container); - ((ViewGroup) originalAmbientIndicationView.getParent()) - .removeView(originalAmbientIndicationView); - - // remove current ambient indication from its parent (discard) - ViewGroup ambientIndicationParent = (ViewGroup) mAmbientIndicationArea.getParent(); - int ambientIndicationIndex = - ambientIndicationParent.indexOfChild(mAmbientIndicationArea); - ambientIndicationParent.removeView(mAmbientIndicationArea); - - // add the old ambient indication to this view - ambientIndicationParent.addView(originalAmbientIndicationView, ambientIndicationIndex); - mAmbientIndicationArea = originalAmbientIndicationView; - - // update burn-in offsets - dozeTimeTick(); - } - } - - @Override - protected void onFinishInflate() { - super.onFinishInflate(); - if (mUsesBinder) { - return; - } - - mOverlayContainer = findViewById(R.id.overlay_container); - mWalletButton = findViewById(R.id.wallet_button); - mQRCodeScannerButton = findViewById(R.id.qr_code_scanner_button); - mControlsButton = findViewById(R.id.controls_button); - mIndicationArea = findViewById(R.id.keyguard_indication_area); - mAmbientIndicationArea = findViewById(R.id.ambient_indication_container); - mIndicationText = findViewById(R.id.keyguard_indication_text); - mIndicationTextBottom = findViewById(R.id.keyguard_indication_text_bottom); - mIndicationBottomMargin = getResources().getDimensionPixelSize( - R.dimen.keyguard_indication_margin_bottom); - mBurnInYOffset = getResources().getDimensionPixelSize( - R.dimen.default_burn_in_prevention_offset); - mKeyguardStateController = Dependency.get(KeyguardStateController.class); - mKeyguardStateController.addCallback(mKeyguardStateCallback); - setClipChildren(false); - setClipToPadding(false); - mActivityStarter = Dependency.get(ActivityStarter.class); - - mIndicationPadding = getResources().getDimensionPixelSize( - R.dimen.keyguard_indication_area_padding); - updateWalletVisibility(); - updateQRCodeButtonVisibility(); - updateControlsVisibility(); - } - - @Override - protected void onAttachedToWindow() { - super.onAttachedToWindow(); - if (mUsesBinder) { - return; - } - - final IntentFilter filter = new IntentFilter(); - filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED); - mKeyguardStateController.addCallback(mKeyguardStateCallback); - } - - @Override - protected void onDetachedFromWindow() { - super.onDetachedFromWindow(); - if (mUsesBinder) { - return; - } - - mKeyguardStateController.removeCallback(mKeyguardStateCallback); - - if (mQuickAccessWalletController != null) { - mQuickAccessWalletController.unregisterWalletChangeObservers( - WALLET_PREFERENCE_CHANGE, DEFAULT_PAYMENT_APP_CHANGE); - } - - if (mQRCodeScannerController != null) { - mQRCodeScannerController.unregisterQRCodeScannerChangeObservers( - QRCodeScannerController.DEFAULT_QR_CODE_SCANNER_CHANGE, - QRCodeScannerController.QR_CODE_SCANNER_PREFERENCE_CHANGE); - } - - if (mControlsComponent != null) { - mControlsComponent.getControlsListingController().ifPresent( - c -> c.removeCallback(mListingCallback)); - } - } - - @Override - protected void onConfigurationChanged(Configuration newConfig) { - super.onConfigurationChanged(newConfig); - if (mUsesBinder) { - if (mBinding != null) { - mBinding.onConfigurationChanged(); - } - return; - } - - mIndicationBottomMargin = getResources().getDimensionPixelSize( - R.dimen.keyguard_indication_margin_bottom); - mBurnInYOffset = getResources().getDimensionPixelSize( - R.dimen.default_burn_in_prevention_offset); - MarginLayoutParams mlp = (MarginLayoutParams) mIndicationArea.getLayoutParams(); - if (mlp.bottomMargin != mIndicationBottomMargin) { - mlp.bottomMargin = mIndicationBottomMargin; - mIndicationArea.setLayoutParams(mlp); - } - - // Respect font size setting. - mIndicationTextBottom.setTextSize(TypedValue.COMPLEX_UNIT_PX, - getResources().getDimensionPixelSize( - com.android.internal.R.dimen.text_size_small_material)); - mIndicationText.setTextSize(TypedValue.COMPLEX_UNIT_PX, - getResources().getDimensionPixelSize( - com.android.internal.R.dimen.text_size_small_material)); - - ViewGroup.LayoutParams lp = mWalletButton.getLayoutParams(); - lp.width = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_fixed_width); - lp.height = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_fixed_height); - mWalletButton.setLayoutParams(lp); - - lp = mQRCodeScannerButton.getLayoutParams(); - lp.width = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_fixed_width); - lp.height = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_fixed_height); - mQRCodeScannerButton.setLayoutParams(lp); - - lp = mControlsButton.getLayoutParams(); - lp.width = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_fixed_width); - lp.height = getResources().getDimensionPixelSize(R.dimen.keyguard_affordance_fixed_height); - mControlsButton.setLayoutParams(lp); - - mIndicationPadding = getResources().getDimensionPixelSize( - R.dimen.keyguard_indication_area_padding); - - updateWalletVisibility(); - updateQRCodeButtonVisibility(); - updateAffordanceColors(); - } - - private void updateWalletVisibility() { - if (mUsesBinder) { - return; - } - - if (mDozing - || mQuickAccessWalletController == null - || !mQuickAccessWalletController.isWalletEnabled() - || !mHasCard) { - mWalletButton.setVisibility(GONE); - - if (mControlsButton.getVisibility() == GONE) { - mIndicationArea.setPadding(0, 0, 0, 0); - } - } else { - mWalletButton.setVisibility(VISIBLE); - mWalletButton.setOnClickListener(this::onWalletClick); - mIndicationArea.setPadding(mIndicationPadding, 0, mIndicationPadding, 0); - } - } - - private void updateControlsVisibility() { - if (mUsesBinder) { - return; - } - - if (mControlsComponent == null) return; - - mControlsButton.setImageResource(mControlsComponent.getTileImageId()); - mControlsButton.setContentDescription(getContext() - .getString(mControlsComponent.getTileTitleId())); - updateAffordanceColors(); - - boolean hasFavorites = mControlsComponent.getControlsController() - .map(c -> c.getFavorites().size() > 0) - .orElse(false); - if (mDozing - || !hasFavorites - || !mControlServicesAvailable - || mControlsComponent.getVisibility() != AVAILABLE) { - mControlsButton.setVisibility(GONE); - if (mWalletButton.getVisibility() == GONE) { - mIndicationArea.setPadding(0, 0, 0, 0); - } - } else { - mControlsButton.setVisibility(VISIBLE); - mControlsButton.setOnClickListener(this::onControlsClick); - mIndicationArea.setPadding(mIndicationPadding, 0, mIndicationPadding, 0); - } - } - - public void setDarkAmount(float darkAmount) { - if (mUsesBinder) { - return; - } - - if (darkAmount == mDarkAmount) { - return; - } - mDarkAmount = darkAmount; - dozeTimeTick(); - } - - /** - * Returns a list of animators to use to animate the indication areas. - */ - public List<ViewPropertyAnimator> getIndicationAreaAnimators() { - if (mUsesBinder) { - return checkNotNull(mBinding).getIndicationAreaAnimators(); - } - - List<ViewPropertyAnimator> animators = - new ArrayList<>(mAmbientIndicationArea != null ? 2 : 1); - animators.add(mIndicationArea.animate()); - if (mAmbientIndicationArea != null) { - animators.add(mAmbientIndicationArea.animate()); - } - return animators; - } - - @Override - public boolean hasOverlappingRendering() { - return false; - } - - private void startFinishDozeAnimation() { - long delay = 0; - if (mWalletButton.getVisibility() == View.VISIBLE) { - startFinishDozeAnimationElement(mWalletButton, delay); - } - if (mQRCodeScannerButton.getVisibility() == View.VISIBLE) { - startFinishDozeAnimationElement(mQRCodeScannerButton, delay); - } - if (mControlsButton.getVisibility() == View.VISIBLE) { - startFinishDozeAnimationElement(mControlsButton, delay); - } - } - - private void startFinishDozeAnimationElement(View element, long delay) { - element.setAlpha(0f); - element.setTranslationY(element.getHeight() / 2); - element.animate() - .alpha(1f) - .translationY(0f) - .setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN) - .setStartDelay(delay) - .setDuration(DOZE_ANIMATION_ELEMENT_DURATION); - } - - public void setDozing(boolean dozing, boolean animate) { - if (mUsesBinder) { - return; - } - - mDozing = dozing; - - updateWalletVisibility(); - updateControlsVisibility(); - updateQRCodeButtonVisibility(); - - if (dozing) { - mOverlayContainer.setVisibility(INVISIBLE); - } else { - mOverlayContainer.setVisibility(VISIBLE); - if (animate) { - startFinishDozeAnimation(); - } - } - } - - public void dozeTimeTick() { - if (mUsesBinder) { - return; - } - - int burnInYOffset = getBurnInOffset(mBurnInYOffset * 2, false /* xAxis */) - - mBurnInYOffset; - mIndicationArea.setTranslationY(burnInYOffset * mDarkAmount); - if (mAmbientIndicationArea != null) { - mAmbientIndicationArea.setTranslationY(burnInYOffset * mDarkAmount); - } - } - - public void setAntiBurnInOffsetX(int burnInXOffset) { - if (mUsesBinder) { - return; - } - - if (mBurnInXOffset == burnInXOffset) { - return; - } - mBurnInXOffset = burnInXOffset; - mIndicationArea.setTranslationX(burnInXOffset); - if (mAmbientIndicationArea != null) { - mAmbientIndicationArea.setTranslationX(burnInXOffset); - } - } - - /** - * Sets the alpha of various sub-components, for example the indication areas and bottom quick - * action buttons. Does not set the alpha of the lock icon. - */ - public void setComponentAlphas(float alpha) { - if (mUsesBinder) { - return; - } - - setImportantForAccessibility( - alpha == 0f - ? View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS - : View.IMPORTANT_FOR_ACCESSIBILITY_AUTO); - if (mAmbientIndicationArea != null) { - mAmbientIndicationArea.setAlpha(alpha); - } - mIndicationArea.setAlpha(alpha); - mWalletButton.setAlpha(alpha); - mQRCodeScannerButton.setAlpha(alpha); - mControlsButton.setAlpha(alpha); - } - - @Override - public WindowInsets onApplyWindowInsets(WindowInsets insets) { - int bottom = insets.getDisplayCutout() != null - ? insets.getDisplayCutout().getSafeInsetBottom() : 0; - if (isPaddingRelative()) { - setPaddingRelative(getPaddingStart(), getPaddingTop(), getPaddingEnd(), bottom); - } else { - setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), bottom); - } - return insets; - } - - private void updateQRCodeButtonVisibility() { - if (mUsesBinder) { - return; - } - - if (mQuickAccessWalletController != null - && mQuickAccessWalletController.isWalletEnabled()) { - // Don't enable if quick access wallet is enabled - return; - } - - if (mQRCodeScannerController != null - && mQRCodeScannerController.isEnabledForLockScreenButton()) { - mQRCodeScannerButton.setVisibility(VISIBLE); - mQRCodeScannerButton.setOnClickListener(this::onQRCodeScannerClicked); - mIndicationArea.setPadding(mIndicationPadding, 0, mIndicationPadding, 0); - } else { - mQRCodeScannerButton.setVisibility(GONE); - if (mControlsButton.getVisibility() == GONE) { - mIndicationArea.setPadding(0, 0, 0, 0); - } - } - } - - private void onQRCodeScannerClicked(View view) { - if (mUsesBinder) { - return; - } - - Intent intent = mQRCodeScannerController.getIntent(); - if (intent != null) { - try { - ActivityTaskManager.getService().startActivityAsUser( - null, getContext().getBasePackageName(), - getContext().getAttributionTag(), intent, - intent.resolveTypeIfNeeded(getContext().getContentResolver()), - null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null, null, - UserHandle.CURRENT.getIdentifier()); - } catch (RemoteException e) { - // This is unexpected. Nonetheless, just log the error and prevent the UI from - // crashing - Log.e(TAG, "Unexpected intent: " + intent - + " when the QR code scanner button was clicked"); - } - } - } - - private void updateAffordanceColors() { - if (mUsesBinder) { - return; - } - - int iconColor = Utils.getColorAttrDefaultColor( - mContext, - com.android.internal.R.attr.textColorPrimary); - mWalletButton.getDrawable().setTint(iconColor); - mControlsButton.getDrawable().setTint(iconColor); - mQRCodeScannerButton.getDrawable().setTint(iconColor); - - ColorStateList bgColor = Utils.getColorAttr( - mContext, - com.android.internal.R.attr.colorSurface); - mWalletButton.setBackgroundTintList(bgColor); - mControlsButton.setBackgroundTintList(bgColor); - mQRCodeScannerButton.setBackgroundTintList(bgColor); - } - - private void onWalletClick(View v) { - if (mUsesBinder) { - return; - } - - // More coming here; need to inform the user about how to proceed - if (mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) { - return; - } - - ActivityLaunchAnimator.Controller animationController = createLaunchAnimationController(v); - mQuickAccessWalletController.startQuickAccessUiIntent( - mActivityStarter, animationController, mHasCard); - } - - protected ActivityLaunchAnimator.Controller createLaunchAnimationController(View view) { - return ActivityLaunchAnimator.Controller.fromView(view, null); - } - - private void onControlsClick(View v) { - if (mUsesBinder) { - return; - } - - if (mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) { - return; - } - - Intent intent = new Intent(mContext, ControlsActivity.class) - .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK) - .putExtra(ControlsUiController.EXTRA_ANIMATE, true); - - ActivityLaunchAnimator.Controller controller = - v != null ? ActivityLaunchAnimator.Controller.fromView(v, null /* cujType */) - : null; - if (mControlsComponent.getVisibility() == AVAILABLE) { - mActivityStarter.startActivity(intent, true /* dismissShade */, controller, - true /* showOverLockscreenWhenLocked */); - } else { - mActivityStarter.postStartActivityDismissingKeyguard(intent, 0 /* delay */, controller); - } - } - - private class WalletCardRetriever implements - QuickAccessWalletClient.OnWalletCardsRetrievedCallback { - - @Override - public void onWalletCardsRetrieved(@NonNull GetWalletCardsResponse response) { - mHasCard = !response.getWalletCards().isEmpty(); - Drawable tileIcon = mQuickAccessWalletController.getWalletClient().getTileIcon(); - if (tileIcon != null) { - mWalletButton.setImageDrawable(tileIcon); - } - post(() -> { - updateWalletVisibility(); - updateAffordanceColors(); - }); - } - - @Override - public void onWalletCardRetrievalError(@NonNull GetWalletCardsError error) { - mHasCard = false; - post(() -> { - updateWalletVisibility(); - updateAffordanceColors(); - }); - } - } -} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.kt new file mode 100644 index 000000000000..4897c529dd51 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.kt @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2014 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.phone + +import android.content.Context +import android.content.res.Configuration +import android.util.AttributeSet +import android.view.View +import android.view.ViewGroup +import android.view.ViewPropertyAnimator +import android.view.WindowInsets +import android.widget.FrameLayout +import com.android.systemui.R +import com.android.systemui.keyguard.ui.binder.KeyguardBottomAreaViewBinder +import com.android.systemui.keyguard.ui.binder.KeyguardBottomAreaViewBinder.bind +import com.android.systemui.keyguard.ui.viewmodel.KeyguardBottomAreaViewModel +import com.android.systemui.plugins.FalsingManager + +/** + * Renders the bottom area of the lock-screen. Concerned primarily with the quick affordance UI + * elements. A secondary concern is the interaction of the quick affordance elements with the + * indication area between them, though the indication area is primarily controlled elsewhere. + */ +class KeyguardBottomAreaView +@JvmOverloads +constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0, + defStyleRes: Int = 0, +) : + FrameLayout( + context, + attrs, + defStyleAttr, + defStyleRes, + ) { + + private var ambientIndicationArea: View? = null + private lateinit var binding: KeyguardBottomAreaViewBinder.Binding + + /** Initializes the view. */ + fun init( + viewModel: KeyguardBottomAreaViewModel, + falsingManager: FalsingManager, + ) { + binding = bind(this, viewModel, falsingManager) + } + + /** + * Initializes this instance of [KeyguardBottomAreaView] based on the given instance of another + * [KeyguardBottomAreaView] + */ + fun initFrom(oldBottomArea: KeyguardBottomAreaView) { + // if it exists, continue to use the original ambient indication container + // instead of the newly inflated one + ambientIndicationArea?.let { nonNullAmbientIndicationArea -> + // remove old ambient indication from its parent + val originalAmbientIndicationView = + oldBottomArea.findViewById<View>(R.id.ambient_indication_container) + (originalAmbientIndicationView.parent as ViewGroup).removeView( + originalAmbientIndicationView + ) + + // remove current ambient indication from its parent (discard) + val ambientIndicationParent = nonNullAmbientIndicationArea.parent as ViewGroup + val ambientIndicationIndex = + ambientIndicationParent.indexOfChild(nonNullAmbientIndicationArea) + ambientIndicationParent.removeView(nonNullAmbientIndicationArea) + + // add the old ambient indication to this view + ambientIndicationParent.addView(originalAmbientIndicationView, ambientIndicationIndex) + ambientIndicationArea = originalAmbientIndicationView + } + } + + override fun onFinishInflate() { + super.onFinishInflate() + ambientIndicationArea = findViewById(R.id.ambient_indication_container) + } + + override fun onConfigurationChanged(newConfig: Configuration) { + super.onConfigurationChanged(newConfig) + binding.onConfigurationChanged() + } + + /** Returns a list of animators to use to animate the indication areas. */ + val indicationAreaAnimators: List<ViewPropertyAnimator> + get() = binding.getIndicationAreaAnimators() + + override fun hasOverlappingRendering(): Boolean { + return false + } + + override fun onApplyWindowInsets(insets: WindowInsets): WindowInsets { + val bottom = insets.displayCutout?.safeInsetBottom ?: 0 + if (isPaddingRelative) { + setPaddingRelative(paddingStart, paddingTop, paddingEnd, bottom) + } else { + setPadding(paddingLeft, paddingTop, paddingRight, bottom) + } + return insets + } +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java index 0001cd0a2798..d380e9f03720 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java @@ -220,6 +220,7 @@ public class KeyguardBouncer { && !mKeyguardUpdateMonitor.getCachedIsUnlockWithFingerprintPossible( KeyguardUpdateMonitor.getCurrentUser()) && !needsFullscreenBouncer() + && !mKeyguardUpdateMonitor.isFaceLockedOut() && !mKeyguardUpdateMonitor.userNeedsStrongAuth() && !mKeyguardBypassController.getBypassEnabled()) { mHandler.postDelayed(mShowRunnable, BOUNCER_FACE_DELAY); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java index cb0a1480c233..4d1c3617ac1a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java @@ -259,11 +259,17 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump private boolean mKeyguardOccluded; @Inject - public ScrimController(LightBarController lightBarController, DozeParameters dozeParameters, - AlarmManager alarmManager, KeyguardStateController keyguardStateController, - DelayedWakeLock.Builder delayedWakeLockBuilder, Handler handler, - KeyguardUpdateMonitor keyguardUpdateMonitor, DockManager dockManager, - ConfigurationController configurationController, @Main Executor mainExecutor, + public ScrimController( + LightBarController lightBarController, + DozeParameters dozeParameters, + AlarmManager alarmManager, + KeyguardStateController keyguardStateController, + DelayedWakeLock.Builder delayedWakeLockBuilder, + Handler handler, + KeyguardUpdateMonitor keyguardUpdateMonitor, + DockManager dockManager, + ConfigurationController configurationController, + @Main Executor mainExecutor, ScreenOffAnimationController screenOffAnimationController, KeyguardUnlockAnimationController keyguardUnlockAnimationController, StatusBarKeyguardViewManager statusBarKeyguardViewManager) { @@ -826,20 +832,15 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump mBehindTint = Color.BLACK; } else { mBehindAlpha = behindAlpha; - if (mState == ScrimState.SHADE_LOCKED) { + if (mState == ScrimState.KEYGUARD && mTransitionToFullShadeProgress > 0.0f) { + mNotificationsAlpha = MathUtils + .saturate(mTransitionToLockScreenFullShadeNotificationsProgress); + } else if (mState == ScrimState.SHADE_LOCKED) { // going from KEYGUARD to SHADE_LOCKED state mNotificationsAlpha = getInterpolatedFraction(); } else { mNotificationsAlpha = Math.max(1.0f - getInterpolatedFraction(), mQsExpansion); } - if (mState == ScrimState.KEYGUARD - && mTransitionToLockScreenFullShadeNotificationsProgress > 0.0f) { - // Interpolate the notification alpha when transitioning! - mNotificationsAlpha = MathUtils.lerp( - mNotificationsAlpha, - getInterpolatedFraction(), - mTransitionToLockScreenFullShadeNotificationsProgress); - } mNotificationsTint = mState.getNotifTint(); mBehindTint = behindTint; } @@ -1430,6 +1431,8 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump pw.print(mNotificationsAlpha); pw.print(" tint=0x"); pw.println(Integer.toHexString(mNotificationsScrim.getTint())); + pw.print(" expansionProgress="); + pw.println(mTransitionToLockScreenFullShadeNotificationsProgress); pw.print(" mTracking="); pw.println(mTracking); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java index f106e54a091b..4c5c23cd3b2f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java @@ -44,7 +44,7 @@ import androidx.annotation.VisibleForTesting; import com.android.internal.util.LatencyTracker; import com.android.internal.widget.LockPatternUtils; -import com.android.keyguard.KeyguardMessageArea; +import com.android.keyguard.AuthKeyguardMessageArea; import com.android.keyguard.KeyguardMessageAreaController; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.KeyguardUpdateMonitorCallback; @@ -122,7 +122,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb private final DreamOverlayStateController mDreamOverlayStateController; @Nullable private final FoldAodAnimationController mFoldAodAnimationController; - private KeyguardMessageAreaController mKeyguardMessageAreaController; + private KeyguardMessageAreaController<AuthKeyguardMessageArea> mKeyguardMessageAreaController; private final Lazy<com.android.systemui.shade.ShadeController> mShadeController; private final BouncerExpansionCallback mExpansionCallback = new BouncerExpansionCallback() { @@ -311,7 +311,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb mBypassController = bypassController; mNotificationContainer = notificationContainer; mKeyguardMessageAreaController = mKeyguardMessageAreaFactory.create( - KeyguardMessageArea.findSecurityMessageDisplay(container)); + centralSurfaces.getKeyguardMessageArea()); registerListeners(); } @@ -378,11 +378,9 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb return; } else if (mNotificationPanelViewController.isUnlockHintRunning()) { mBouncer.setExpansion(KeyguardBouncer.EXPANSION_HIDDEN); - } else if (mStatusBarStateController.getState() == StatusBarState.SHADE_LOCKED - && mKeyguardUpdateManager.isUdfpsEnrolled()) { + } else if (mStatusBarStateController.getState() == StatusBarState.SHADE_LOCKED) { // Don't expand to the bouncer. Instead transition back to the lock screen (see - // CentralSurfaces#showBouncerOrLockScreenIfKeyguard) where the user can use the UDFPS - // affordance to enter the device (or swipe up to the input bouncer) + // CentralSurfaces#showBouncerOrLockScreenIfKeyguard) return; } else if (bouncerNeedsScrimming()) { mBouncer.setExpansion(KeyguardBouncer.EXPANSION_VISIBLE); @@ -616,7 +614,8 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb private void updateAlternateAuthShowing(boolean updateScrim) { final boolean isShowingAltAuth = isShowingAlternateAuth(); if (mKeyguardMessageAreaController != null) { - mKeyguardMessageAreaController.setAltBouncerShowing(isShowingAltAuth); + mKeyguardMessageAreaController.setIsVisible(isShowingAltAuth); + mKeyguardMessageAreaController.setMessage(""); } mBypassController.setAltBouncerShowing(isShowingAltAuth); mKeyguardUpdateManager.setUdfpsBouncerShowing(isShowingAltAuth); @@ -837,30 +836,24 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb }); } else { executeAfterKeyguardGoneAction(); - boolean wakeUnlockPulsing = - mBiometricUnlockController.getMode() == MODE_WAKE_AND_UNLOCK_PULSING; mCentralSurfaces.setKeyguardFadingAway(startTime, delay, fadeoutDuration); mBiometricUnlockController.startKeyguardFadingAway(); hideBouncer(true /* destroyView */); - if (wakeUnlockPulsing) { - mCentralSurfaces.fadeKeyguardWhilePulsing(); + + boolean staying = mStatusBarStateController.leaveOpenOnKeyguardHide(); + if (!staying) { + mNotificationShadeWindowController.setKeyguardFadingAway(true); + mCentralSurfaces.hideKeyguard(); + // hide() will happen asynchronously and might arrive after the scrims + // were already hidden, this means that the transition callback won't + // be triggered anymore and StatusBarWindowController will be forever in + // the fadingAway state. + mCentralSurfaces.updateScrimController(); wakeAndUnlockDejank(); } else { - boolean staying = mStatusBarStateController.leaveOpenOnKeyguardHide(); - if (!staying) { - mNotificationShadeWindowController.setKeyguardFadingAway(true); - mCentralSurfaces.hideKeyguard(); - // hide() will happen asynchronously and might arrive after the scrims - // were already hidden, this means that the transition callback won't - // be triggered anymore and StatusBarWindowController will be forever in - // the fadingAway state. - mCentralSurfaces.updateScrimController(); - wakeAndUnlockDejank(); - } else { - mCentralSurfaces.hideKeyguard(); - mCentralSurfaces.finishKeyguardFadingAway(); - mBiometricUnlockController.finishKeyguardFadingAway(); - } + mCentralSurfaces.hideKeyguard(); + mCentralSurfaces.finishKeyguardFadingAway(); + mBiometricUnlockController.finishKeyguardFadingAway(); } updateStates(); @@ -1043,7 +1036,6 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb if (bouncerShowing != mLastBouncerShowing || mFirstUpdate) { mNotificationShadeWindowController.setBouncerShowing(bouncerShowing); mCentralSurfaces.setBouncerShowing(bouncerShowing); - mKeyguardMessageAreaController.setBouncerShowing(bouncerShowing); } if (occluded != mLastOccluded || mFirstUpdate) { @@ -1192,7 +1184,8 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb } } - public void showBouncerMessage(String message, ColorStateList colorState) { + /** Display security message to relevant KeyguardMessageArea. */ + public void setKeyguardMessage(String message, ColorStateList colorState) { if (isShowingAlternateAuth()) { if (mKeyguardMessageAreaController != null) { mKeyguardMessageAreaController.setMessage(message); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarLaunchAnimatorController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarLaunchAnimatorController.kt index c0922163903f..ee948c04df38 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarLaunchAnimatorController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarLaunchAnimatorController.kt @@ -51,7 +51,7 @@ class StatusBarLaunchAnimatorController( centralSurfaces.notificationPanelViewController.applyLaunchAnimationProgress(linearProgress) } - override fun onLaunchAnimationCancelled() { + override fun onLaunchAnimationCancelled(newKeyguardOccludedState: Boolean?) { delegate.onLaunchAnimationCancelled() centralSurfaces.notificationPanelViewController.setIsLaunchAnimationRunning(false) centralSurfaces.onLaunchAnimationCancelled(isLaunchForActivity) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java index 75dac1a093dd..d9c0293fe13d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java @@ -55,6 +55,7 @@ public final class StatusBarTouchableRegionManager implements Dumpable { private final Context mContext; private final HeadsUpManagerPhone mHeadsUpManager; private final NotificationShadeWindowController mNotificationShadeWindowController; + private final UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController; private boolean mIsStatusBarExpanded = false; private boolean mShouldAdjustInsets = false; @@ -72,7 +73,8 @@ public final class StatusBarTouchableRegionManager implements Dumpable { Context context, NotificationShadeWindowController notificationShadeWindowController, ConfigurationController configurationController, - HeadsUpManagerPhone headsUpManager + HeadsUpManagerPhone headsUpManager, + UnlockedScreenOffAnimationController unlockedScreenOffAnimationController ) { mContext = context; initResources(); @@ -115,6 +117,8 @@ public final class StatusBarTouchableRegionManager implements Dumpable { mNotificationShadeWindowController.setForcePluginOpenListener((forceOpen) -> { updateTouchableRegion(); }); + + mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController; } protected void setup( @@ -179,7 +183,7 @@ public final class StatusBarTouchableRegionManager implements Dumpable { /** * Set the touchable portion of the status bar based on what elements are visible. */ - private void updateTouchableRegion() { + public void updateTouchableRegion() { boolean hasCutoutInset = (mNotificationShadeWindowView != null) && (mNotificationShadeWindowView.getRootWindowInsets() != null) && (mNotificationShadeWindowView.getRootWindowInsets().getDisplayCutout() != null); @@ -242,12 +246,25 @@ public final class StatusBarTouchableRegionManager implements Dumpable { touchableRegion.union(bounds); } + /** + * Helper to let us know when calculating the region is not needed because we know the entire + * screen needs to be touchable. + */ + private boolean shouldMakeEntireScreenTouchable() { + // The touchable region is always the full area when expanded, whether we're showing the + // shade or the bouncer. It's also fully touchable when the screen off animation is playing + // since we don't want stray touches to go through the light reveal scrim to whatever is + // underneath. + return mIsStatusBarExpanded + || mCentralSurfaces.isBouncerShowing() + || mUnlockedScreenOffAnimationController.isAnimationPlaying(); + } + private final OnComputeInternalInsetsListener mOnComputeInternalInsetsListener = new OnComputeInternalInsetsListener() { @Override public void onComputeInternalInsets(ViewTreeObserver.InternalInsetsInfo info) { - if (mIsStatusBarExpanded || mCentralSurfaces.isBouncerShowing()) { - // The touchable region is always the full area when expanded + if (shouldMakeEntireScreenTouchable()) { return; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/panelstate/PanelExpansionStateManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/panelstate/PanelExpansionStateManager.kt index a6160aaf7756..6b7c42e3884a 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/panelstate/PanelExpansionStateManager.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/panelstate/PanelExpansionStateManager.kt @@ -114,8 +114,8 @@ class PanelExpansionStateManager @Inject constructor() { "end state=${state.panelStateToString()} " + "f=$fraction " + "expanded=$expanded " + - "tracking=$tracking" + - "drawDownPxAmount=$dragDownPxAmount " + + "tracking=$tracking " + + "dragDownPxAmount=$dragDownPxAmount " + "${if (fullyOpened) " fullyOpened" else ""} " + if (fullyClosed) " fullyClosed" else "" ) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/ConnectivityInfoProcessor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/ConnectivityInfoProcessor.kt deleted file mode 100644 index fe846747d0c6..000000000000 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/ConnectivityInfoProcessor.kt +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.systemui.statusbar.pipeline - -import android.content.Context -import com.android.systemui.CoreStartable -import com.android.systemui.dagger.SysUISingleton -import com.android.systemui.dagger.qualifiers.Application -import com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel.WifiViewModel -import javax.inject.Inject -import javax.inject.Provider -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.flow.collect -import kotlinx.coroutines.launch - -/** - * A temporary object that collects on [WifiViewModel] flows for debugging purposes. - * - * This will eventually get migrated to a view binder that will use the flow outputs to set state on - * views. For now, this just collects on flows so that the information gets logged. - */ -@SysUISingleton -class ConnectivityInfoProcessor @Inject constructor( - context: Context, - // TODO(b/238425913): Don't use the application scope; instead, use the status bar view's - // scope so we only do work when there's UI that cares about it. - @Application private val scope: CoroutineScope, - private val statusBarPipelineFlags: StatusBarPipelineFlags, - private val wifiViewModelProvider: Provider<WifiViewModel>, -) : CoreStartable(context) { - override fun start() { - if (!statusBarPipelineFlags.isNewPipelineBackendEnabled()) { - return - } - // TODO(b/238425913): The view binder should do this instead. For now, do it here so we can - // see the logs. - scope.launch { - wifiViewModelProvider.get().isActivityInVisible.collect { } - } - } -} 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 88eccb5ba47f..9a7c3fae780c 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 @@ -16,22 +16,17 @@ package com.android.systemui.statusbar.pipeline.dagger -import com.android.systemui.CoreStartable -import com.android.systemui.statusbar.pipeline.ConnectivityInfoProcessor +import com.android.systemui.statusbar.pipeline.shared.data.repository.ConnectivityRepository +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 dagger.Binds import dagger.Module -import dagger.multibindings.ClassKey -import dagger.multibindings.IntoMap @Module abstract class StatusBarPipelineModule { - /** Inject into ConnectivityInfoProcessor. */ @Binds - @IntoMap - @ClassKey(ConnectivityInfoProcessor::class) - abstract fun bindConnectivityInfoProcessor(cip: ConnectivityInfoProcessor): CoreStartable + abstract fun connectivityRepository(impl: ConnectivityRepositoryImpl): ConnectivityRepository @Binds abstract fun wifiRepository(impl: WifiRepositoryImpl): WifiRepository diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityPipelineLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityPipelineLogger.kt index 2a89309f7200..88d8a86d39f2 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityPipelineLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/ConnectivityPipelineLogger.kt @@ -34,7 +34,7 @@ class ConnectivityPipelineLogger @Inject constructor( /** * Logs a change in one of the **raw inputs** to the connectivity pipeline. */ - fun logInputChange(callbackName: String, changeInfo: String) { + fun logInputChange(callbackName: String, changeInfo: String?) { buffer.log( SB_LOGGING_TAG, LogLevel.INFO, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/data/model/ConnectivitySlots.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/data/model/ConnectivitySlots.kt new file mode 100644 index 000000000000..d52d0fb91b82 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/data/model/ConnectivitySlots.kt @@ -0,0 +1,56 @@ +/* + * 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.pipeline.shared.data.model + +import android.content.Context +import com.android.internal.R +import com.android.systemui.dagger.SysUISingleton +import javax.inject.Inject + +/** + * A container for all the different types of connectivity slots: wifi, mobile, etc. + */ +@SysUISingleton +class ConnectivitySlots @Inject constructor(context: Context) { + private val airplaneSlot: String = context.getString(R.string.status_bar_airplane) + private val mobileSlot: String = context.getString(R.string.status_bar_mobile) + private val wifiSlot: String = context.getString(R.string.status_bar_wifi) + private val ethernetSlot: String = context.getString(R.string.status_bar_ethernet) + + private val slotByName: Map<String, ConnectivitySlot> = mapOf( + airplaneSlot to ConnectivitySlot.AIRPLANE, + mobileSlot to ConnectivitySlot.MOBILE, + wifiSlot to ConnectivitySlot.WIFI, + ethernetSlot to ConnectivitySlot.ETHERNET + ) + + /** + * Given a string name of a slot, returns the instance of [ConnectivitySlot] that it corresponds + * to, or null if we couldn't find that slot name. + */ + fun getSlotFromName(slotName: String): ConnectivitySlot? { + return slotByName[slotName] + } +} + +/** The different types of connectivity slots. */ +enum class ConnectivitySlot { + AIRPLANE, + ETHERNET, + MOBILE, + WIFI, +} diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/data/repository/ConnectivityRepository.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/data/repository/ConnectivityRepository.kt new file mode 100644 index 000000000000..6b1750d11562 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/shared/data/repository/ConnectivityRepository.kt @@ -0,0 +1,120 @@ +/* + * 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.pipeline.shared.data.repository + +import android.content.Context +import androidx.annotation.ArrayRes +import androidx.annotation.VisibleForTesting +import com.android.systemui.Dumpable +import com.android.systemui.R +import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.dagger.qualifiers.Application +import com.android.systemui.dump.DumpManager +import com.android.systemui.statusbar.phone.StatusBarIconController +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.data.model.ConnectivitySlot +import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlots +import com.android.systemui.tuner.TunerService +import java.io.PrintWriter +import javax.inject.Inject +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.channels.awaitClose +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.stateIn + +/** + * Provides data related to the connectivity state that needs to be shared across multiple different + * types of connectivity (wifi, mobile, ethernet, etc.) + */ +interface ConnectivityRepository { + /** + * Observable for the current set of connectivity icons that should be force-hidden. + */ + val forceHiddenSlots: StateFlow<Set<ConnectivitySlot>> +} + +@OptIn(ExperimentalCoroutinesApi::class) +@SysUISingleton +class ConnectivityRepositoryImpl @Inject constructor( + private val connectivitySlots: ConnectivitySlots, + context: Context, + dumpManager: DumpManager, + logger: ConnectivityPipelineLogger, + @Application scope: CoroutineScope, + tunerService: TunerService, +) : ConnectivityRepository, Dumpable { + init { + dumpManager.registerDumpable("$SB_LOGGING_TAG:ConnectivityRepository", this) + } + + // The default set of hidden icons to use if we don't get any from [TunerService]. + private val defaultHiddenIcons: Set<ConnectivitySlot> = + context.resources.getStringArray(DEFAULT_HIDDEN_ICONS_RESOURCE) + .asList() + .toSlotSet(connectivitySlots) + + override val forceHiddenSlots: StateFlow<Set<ConnectivitySlot>> = conflatedCallbackFlow { + val callback = object : TunerService.Tunable { + override fun onTuningChanged(key: String, newHideList: String?) { + if (key != HIDDEN_ICONS_TUNABLE_KEY) { + return + } + logger.logInputChange("onTuningChanged", newHideList) + + val outputList = newHideList?.split(",")?.toSlotSet(connectivitySlots) + ?: defaultHiddenIcons + trySend(outputList) + } + } + tunerService.addTunable(callback, HIDDEN_ICONS_TUNABLE_KEY) + + awaitClose { tunerService.removeTunable(callback) } + } + .stateIn( + scope, + started = SharingStarted.WhileSubscribed(), + initialValue = defaultHiddenIcons + ) + + override fun dump(pw: PrintWriter, args: Array<out String>) { + pw.apply { + println("defaultHiddenIcons=$defaultHiddenIcons") + } + } + + companion object { + @VisibleForTesting + internal const val HIDDEN_ICONS_TUNABLE_KEY = StatusBarIconController.ICON_HIDE_LIST + @VisibleForTesting + @ArrayRes + internal val DEFAULT_HIDDEN_ICONS_RESOURCE = R.array.config_statusBarIconsToExclude + + /** Converts a list of string slot names to a set of [ConnectivitySlot] instances. */ + private fun List<String>.toSlotSet( + connectivitySlots: ConnectivitySlots + ): Set<ConnectivitySlot> { + return this + .filter { it.isNotBlank() } + .mapNotNull { connectivitySlots.getSlotFromName(it) } + .toSet() + } + } +} 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 afe19afff55f..952525d243f9 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 @@ -18,6 +18,8 @@ package com.android.systemui.statusbar.pipeline.wifi.domain.interactor import android.net.wifi.WifiManager import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlot +import com.android.systemui.statusbar.pipeline.shared.data.repository.ConnectivityRepository import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel import com.android.systemui.statusbar.pipeline.wifi.data.repository.WifiRepository import javax.inject.Inject @@ -33,9 +35,10 @@ import kotlinx.coroutines.flow.map */ @SysUISingleton class WifiInteractor @Inject constructor( - repository: WifiRepository, + connectivityRepository: ConnectivityRepository, + wifiRepository: WifiRepository, ) { - private val ssid: Flow<String?> = repository.wifiNetwork.map { info -> + private val ssid: Flow<String?> = wifiRepository.wifiNetwork.map { info -> when (info) { is WifiNetworkModel.Inactive -> null is WifiNetworkModel.CarrierMerged -> null @@ -49,10 +52,16 @@ class WifiInteractor @Inject constructor( } /** Our current wifi network. See [WifiNetworkModel]. */ - val wifiNetwork: Flow<WifiNetworkModel> = repository.wifiNetwork + val wifiNetwork: Flow<WifiNetworkModel> = wifiRepository.wifiNetwork + + /** True if we're configured to force-hide the wifi icon and false otherwise. */ + val isForceHidden: Flow<Boolean> = connectivityRepository.forceHiddenSlots.map { + it.contains(ConnectivitySlot.WIFI) + } /** True if our wifi network has activity in (download), and false otherwise. */ - val hasActivityIn: Flow<Boolean> = combine(repository.wifiActivity, ssid) { activity, ssid -> + val hasActivityIn: Flow<Boolean> = + combine(wifiRepository.wifiActivity, ssid) { activity, ssid -> activity.hasActivityIn && ssid != null } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/binder/WifiViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/binder/WifiViewBinder.kt index 7607ddf4fe8c..4fad3274d12f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/binder/WifiViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/binder/WifiViewBinder.kt @@ -24,6 +24,7 @@ import androidx.core.view.isVisible import androidx.lifecycle.Lifecycle import androidx.lifecycle.repeatOnLifecycle import com.android.systemui.R +import com.android.systemui.common.ui.binder.IconViewBinder import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel.WifiViewModel import kotlinx.coroutines.InternalCoroutinesApi @@ -54,14 +55,15 @@ object WifiViewBinder { view.repeatWhenAttached { repeatOnLifecycle(Lifecycle.State.STARTED) { launch { - viewModel.wifiIconResId.distinctUntilChanged().collect { iconResId -> - iconView.setImageDrawable( - if (iconResId != null && iconResId > 0) { - iconView.context.getDrawable(iconResId) - } else { - null - } - ) + viewModel.wifiIcon.distinctUntilChanged().collect { wifiIcon -> + // TODO(b/238425913): Right now, if !isVisible, there's just an empty space + // where the wifi icon would be. We need to pipe isVisible through to + // [ModernStatusBarWifiView.isIconVisible], which is what actually makes + // the view GONE. + view.isVisible = wifiIcon != null + wifiIcon?.let { + IconViewBinder.bind(wifiIcon, iconView) + } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModel.kt index 4fdcc44f1802..3c243ac90831 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/pipeline/wifi/ui/viewmodel/WifiViewModel.kt @@ -16,8 +16,16 @@ package com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel +import android.content.Context import android.graphics.Color import androidx.annotation.DrawableRes +import androidx.annotation.StringRes +import androidx.annotation.VisibleForTesting +import com.android.settingslib.AccessibilityContentDescriptions.WIFI_CONNECTION_STRENGTH +import com.android.settingslib.AccessibilityContentDescriptions.WIFI_NO_CONNECTION +import com.android.systemui.R +import com.android.systemui.common.shared.model.ContentDescription +import com.android.systemui.common.shared.model.Icon import com.android.systemui.statusbar.connectivity.WifiIcons.WIFI_FULL_ICONS import com.android.systemui.statusbar.connectivity.WifiIcons.WIFI_NO_INTERNET_ICONS import com.android.systemui.statusbar.connectivity.WifiIcons.WIFI_NO_NETWORK @@ -29,6 +37,7 @@ import com.android.systemui.statusbar.pipeline.wifi.domain.interactor.WifiIntera import com.android.systemui.statusbar.pipeline.wifi.shared.WifiConstants import javax.inject.Inject import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.emptyFlow import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map @@ -39,6 +48,7 @@ import kotlinx.coroutines.flow.map class WifiViewModel @Inject constructor( statusBarPipelineFlags: StatusBarPipelineFlags, private val constants: WifiConstants, + private val context: Context, private val logger: ConnectivityPipelineLogger, private val interactor: WifiInteractor, ) { @@ -46,7 +56,7 @@ class WifiViewModel @Inject constructor( * The drawable resource ID to use for the wifi icon. Null if we shouldn't display any icon. */ @DrawableRes - val wifiIconResId: Flow<Int?> = interactor.wifiNetwork.map { + private val iconResId: Flow<Int?> = interactor.wifiNetwork.map { when (it) { is WifiNetworkModel.CarrierMerged -> null is WifiNetworkModel.Inactive -> WIFI_NO_NETWORK @@ -59,6 +69,49 @@ class WifiViewModel @Inject constructor( } } + /** The content description for the wifi icon. */ + private val contentDescription: Flow<ContentDescription?> = interactor.wifiNetwork.map { + when (it) { + is WifiNetworkModel.CarrierMerged -> null + is WifiNetworkModel.Inactive -> + ContentDescription.Loaded( + "${context.getString(WIFI_NO_CONNECTION)},${context.getString(NO_INTERNET)}" + ) + is WifiNetworkModel.Active -> + when (it.level) { + null -> null + else -> { + val levelDesc = context.getString(WIFI_CONNECTION_STRENGTH[it.level]) + when { + it.isValidated -> ContentDescription.Loaded(levelDesc) + else -> ContentDescription.Loaded( + "$levelDesc,${context.getString(NO_INTERNET)}" + ) + } + } + } + } + } + + /** + * The wifi icon that should be displayed. Null if we shouldn't display any icon. + */ + val wifiIcon: Flow<Icon?> = combine( + interactor.isForceHidden, + iconResId, + contentDescription, + ) { isForceHidden, iconResId, contentDescription -> + when { + isForceHidden || + iconResId == null || + iconResId <= 0 -> null + else -> Icon.Resource(iconResId, contentDescription) + } + } + + /** + * True if the activity in icon should be displayed and false otherwise. + */ val isActivityInVisible: Flow<Boolean> get() = if (!constants.shouldShowActivityConfig) { @@ -74,4 +127,10 @@ class WifiViewModel @Inject constructor( } else { flowOf(Color.CYAN) } + + companion object { + @StringRes + @VisibleForTesting + internal val NO_INTERNET = R.string.data_connection_no_internet + } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java index e7fa6d239012..aae0f93a0e19 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java @@ -27,7 +27,6 @@ import android.os.Looper; import android.os.Message; import android.os.UserHandle; import android.os.UserManager; -import android.util.Log; import androidx.annotation.NonNull; @@ -37,6 +36,7 @@ import com.android.settingslib.bluetooth.CachedBluetoothDevice; import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.settingslib.bluetooth.LocalBluetoothProfile; import com.android.settingslib.bluetooth.LocalBluetoothProfileManager; +import com.android.systemui.bluetooth.BluetoothLogger; import com.android.systemui.dagger.SysUISingleton; import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; @@ -57,9 +57,9 @@ import javax.inject.Inject; public class BluetoothControllerImpl implements BluetoothController, BluetoothCallback, CachedBluetoothDevice.Callback, LocalBluetoothProfileManager.ServiceListener { private static final String TAG = "BluetoothController"; - private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); private final DumpManager mDumpManager; + private final BluetoothLogger mLogger; private final LocalBluetoothManager mLocalBluetoothManager; private final UserManager mUserManager; private final int mCurrentUser; @@ -70,6 +70,7 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa private final List<CachedBluetoothDevice> mConnectedDevices = new ArrayList<>(); private boolean mEnabled; + @ConnectionState private int mConnectionState = BluetoothAdapter.STATE_DISCONNECTED; private boolean mAudioProfileOnly; private boolean mIsActive; @@ -83,10 +84,12 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa public BluetoothControllerImpl( Context context, DumpManager dumpManager, + BluetoothLogger logger, @Background Looper bgLooper, @Main Looper mainLooper, @Nullable LocalBluetoothManager localBluetoothManager) { mDumpManager = dumpManager; + mLogger = logger; mLocalBluetoothManager = localBluetoothManager; mBgHandler = new Handler(bgLooper); mHandler = new H(mainLooper); @@ -116,7 +119,7 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa return; } pw.print(" mEnabled="); pw.println(mEnabled); - pw.print(" mConnectionState="); pw.println(stateToString(mConnectionState)); + pw.print(" mConnectionState="); pw.println(connectionStateToString(mConnectionState)); pw.print(" mAudioProfileOnly="); pw.println(mAudioProfileOnly); pw.print(" mIsActive="); pw.println(mIsActive); pw.print(" mConnectedDevices="); pw.println(getConnectedDevices()); @@ -127,7 +130,7 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa } } - private static String stateToString(int state) { + private static String connectionStateToString(@ConnectionState int state) { switch (state) { case BluetoothAdapter.STATE_CONNECTED: return "CONNECTED"; @@ -320,8 +323,8 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa } @Override - public void onBluetoothStateChanged(int bluetoothState) { - if (DEBUG) Log.d(TAG, "BluetoothStateChanged=" + stateToString(bluetoothState)); + public void onBluetoothStateChanged(@AdapterState int bluetoothState) { + mLogger.logStateChange(BluetoothAdapter.nameForState(bluetoothState)); mEnabled = bluetoothState == BluetoothAdapter.STATE_ON || bluetoothState == BluetoothAdapter.STATE_TURNING_ON; mState = bluetoothState; @@ -330,24 +333,25 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa } @Override - public void onDeviceAdded(CachedBluetoothDevice cachedDevice) { - if (DEBUG) Log.d(TAG, "DeviceAdded=" + cachedDevice.getAddress()); + public void onDeviceAdded(@NonNull CachedBluetoothDevice cachedDevice) { + mLogger.logDeviceAdded(cachedDevice.getAddress()); cachedDevice.registerCallback(this); updateConnected(); mHandler.sendEmptyMessage(H.MSG_PAIRED_DEVICES_CHANGED); } @Override - public void onDeviceDeleted(CachedBluetoothDevice cachedDevice) { - if (DEBUG) Log.d(TAG, "DeviceDeleted=" + cachedDevice.getAddress()); + public void onDeviceDeleted(@NonNull CachedBluetoothDevice cachedDevice) { + mLogger.logDeviceDeleted(cachedDevice.getAddress()); mCachedState.remove(cachedDevice); updateConnected(); mHandler.sendEmptyMessage(H.MSG_PAIRED_DEVICES_CHANGED); } @Override - public void onDeviceBondStateChanged(CachedBluetoothDevice cachedDevice, int bondState) { - if (DEBUG) Log.d(TAG, "DeviceBondStateChanged=" + cachedDevice.getAddress()); + public void onDeviceBondStateChanged( + @NonNull CachedBluetoothDevice cachedDevice, int bondState) { + mLogger.logBondStateChange(cachedDevice.getAddress(), bondState); mCachedState.remove(cachedDevice); updateConnected(); mHandler.sendEmptyMessage(H.MSG_PAIRED_DEVICES_CHANGED); @@ -355,50 +359,47 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa @Override public void onDeviceAttributesChanged() { - if (DEBUG) Log.d(TAG, "DeviceAttributesChanged"); + mLogger.logDeviceAttributesChanged(); updateConnected(); mHandler.sendEmptyMessage(H.MSG_PAIRED_DEVICES_CHANGED); } @Override - public void onConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) { - if (DEBUG) { - Log.d(TAG, "ConnectionStateChanged=" + cachedDevice.getAddress() + " " - + stateToString(state)); - } + public void onConnectionStateChanged( + @Nullable CachedBluetoothDevice cachedDevice, + @ConnectionState int state) { + mLogger.logDeviceConnectionStateChanged( + getAddressOrNull(cachedDevice), connectionStateToString(state)); mCachedState.remove(cachedDevice); updateConnected(); mHandler.sendEmptyMessage(H.MSG_STATE_CHANGED); } @Override - public void onProfileConnectionStateChanged(CachedBluetoothDevice cachedDevice, - int state, int bluetoothProfile) { - if (DEBUG) { - Log.d(TAG, "ProfileConnectionStateChanged=" + cachedDevice.getAddress() + " " - + stateToString(state) + " profileId=" + bluetoothProfile); - } + public void onProfileConnectionStateChanged( + @NonNull CachedBluetoothDevice cachedDevice, + @ConnectionState int state, + int bluetoothProfile) { + mLogger.logProfileConnectionStateChanged( + cachedDevice.getAddress(), connectionStateToString(state), bluetoothProfile); mCachedState.remove(cachedDevice); updateConnected(); mHandler.sendEmptyMessage(H.MSG_STATE_CHANGED); } @Override - public void onActiveDeviceChanged(CachedBluetoothDevice activeDevice, int bluetoothProfile) { - if (DEBUG) { - Log.d(TAG, "ActiveDeviceChanged=" + activeDevice.getAddress() - + " profileId=" + bluetoothProfile); - } + public void onActiveDeviceChanged( + @Nullable CachedBluetoothDevice activeDevice, int bluetoothProfile) { + mLogger.logActiveDeviceChanged(getAddressOrNull(activeDevice), bluetoothProfile); updateActive(); mHandler.sendEmptyMessage(H.MSG_STATE_CHANGED); } @Override - public void onAclConnectionStateChanged(CachedBluetoothDevice cachedDevice, int state) { - if (DEBUG) { - Log.d(TAG, "ACLConnectionStateChanged=" + cachedDevice.getAddress() + " " - + stateToString(state)); - } + public void onAclConnectionStateChanged( + @NonNull CachedBluetoothDevice cachedDevice, int state) { + mLogger.logAclConnectionStateChanged( + cachedDevice.getAddress(), connectionStateToString(state)); mCachedState.remove(cachedDevice); updateConnected(); mHandler.sendEmptyMessage(H.MSG_STATE_CHANGED); @@ -415,6 +416,11 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa return state; } + @Nullable + private String getAddressOrNull(@Nullable CachedBluetoothDevice device) { + return device == null ? null : device.getAddress(); + } + @Override public void onServiceConnected() { updateConnected(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java index bdac88837969..f4d08e01d5c3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java @@ -31,6 +31,7 @@ import androidx.annotation.VisibleForTesting; import com.android.internal.widget.LockPatternUtils; import com.android.keyguard.KeyguardUpdateMonitor; import com.android.keyguard.KeyguardUpdateMonitorCallback; +import com.android.keyguard.logging.KeyguardUpdateMonitorLogger; import com.android.systemui.Dumpable; import com.android.systemui.R; import com.android.systemui.dagger.SysUISingleton; @@ -60,6 +61,7 @@ public class KeyguardStateControllerImpl implements KeyguardStateController, Dum private final KeyguardUpdateMonitorCallback mKeyguardUpdateMonitorCallback = new UpdateMonitorCallback(); private final Lazy<KeyguardUnlockAnimationController> mUnlockAnimationControllerLazy; + private final KeyguardUpdateMonitorLogger mLogger; private boolean mCanDismissLockScreen; private boolean mShowing; @@ -107,8 +109,10 @@ public class KeyguardStateControllerImpl implements KeyguardStateController, Dum KeyguardUpdateMonitor keyguardUpdateMonitor, LockPatternUtils lockPatternUtils, Lazy<KeyguardUnlockAnimationController> keyguardUnlockAnimationController, + KeyguardUpdateMonitorLogger logger, DumpManager dumpManager) { mContext = context; + mLogger = logger; mKeyguardUpdateMonitor = keyguardUpdateMonitor; mLockPatternUtils = lockPatternUtils; mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateMonitorCallback); @@ -245,6 +249,8 @@ public class KeyguardStateControllerImpl implements KeyguardStateController, Dum mTrusted = trusted; mTrustManaged = trustManaged; mFaceAuthEnabled = faceAuthEnabled; + mLogger.logKeyguardStateUpdate( + mSecure, mCanDismissLockScreen, mTrusted, mTrustManaged); notifyUnlockedChanged(); } Trace.endSection(); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java index a5bcb538cd8c..1d5b88e7dee0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java @@ -86,6 +86,7 @@ import com.android.systemui.statusbar.phone.SystemUIDialog; import com.android.systemui.telephony.TelephonyListenerManager; import com.android.systemui.user.CreateUserActivity; import com.android.systemui.user.data.source.UserRecord; +import com.android.systemui.user.legacyhelper.ui.LegacyUserUiHelper; import com.android.systemui.util.settings.GlobalSettings; import com.android.systemui.util.settings.SecureSettings; @@ -100,14 +101,20 @@ import java.util.function.Consumer; import javax.inject.Inject; +import kotlinx.coroutines.flow.Flow; +import kotlinx.coroutines.flow.MutableStateFlow; +import kotlinx.coroutines.flow.StateFlowKt; + /** * Keeps a list of all users on the device for user switching. */ @SysUISingleton public class UserSwitcherController implements Dumpable { - public static final float USER_SWITCH_ENABLED_ALPHA = 1.0f; - public static final float USER_SWITCH_DISABLED_ALPHA = 0.38f; + public static final float USER_SWITCH_ENABLED_ALPHA = + LegacyUserUiHelper.USER_SWITCHER_USER_VIEW_SELECTABLE_ALPHA; + public static final float USER_SWITCH_DISABLED_ALPHA = + LegacyUserUiHelper.USER_SWITCHER_USER_VIEW_NOT_SELECTABLE_ALPHA; private static final String TAG = "UserSwitcherController"; private static final boolean DEBUG = false; @@ -155,7 +162,8 @@ public class UserSwitcherController implements Dumpable { private boolean mSimpleUserSwitcher; // When false, there won't be any visual affordance to add a new user from the keyguard even if // the user is unlocked - private boolean mAddUsersFromLockScreen; + private final MutableStateFlow<Boolean> mAddUsersFromLockScreen = + StateFlowKt.MutableStateFlow(false); private boolean mUserSwitcherEnabled; @VisibleForTesting boolean mPauseRefreshUsers; @@ -258,8 +266,11 @@ public class UserSwitcherController implements Dumpable { @Override public void onChange(boolean selfChange) { mSimpleUserSwitcher = shouldUseSimpleUserSwitcher(); - mAddUsersFromLockScreen = mGlobalSettings.getIntForUser( - Settings.Global.ADD_USERS_WHEN_LOCKED, 0, UserHandle.USER_SYSTEM) != 0; + mAddUsersFromLockScreen.setValue( + mGlobalSettings.getIntForUser( + Settings.Global.ADD_USERS_WHEN_LOCKED, + 0, + UserHandle.USER_SYSTEM) != 0); mUserSwitcherEnabled = mGlobalSettings.getIntForUser( Settings.Global.USER_SWITCHER_ENABLED, 0, UserHandle.USER_SYSTEM) != 0; refreshUsers(UserHandle.USER_NULL); @@ -323,7 +334,6 @@ public class UserSwitcherController implements Dumpable { } mForcePictureLoadForUserId.clear(); - final boolean addUsersWhenLocked = mAddUsersFromLockScreen; mBgExecutor.execute(() -> { List<UserInfo> infos = mUserManager.getAliveUsers(); if (infos == null) { @@ -434,7 +444,7 @@ public class UserSwitcherController implements Dumpable { } boolean anyoneCanCreateUsers() { - return systemCanCreateUsers() && mAddUsersFromLockScreen; + return systemCanCreateUsers() && mAddUsersFromLockScreen.getValue(); } boolean canCreateGuest(boolean hasExistingGuest) { @@ -450,7 +460,7 @@ public class UserSwitcherController implements Dumpable { } boolean createIsRestricted() { - return !mAddUsersFromLockScreen; + return !mAddUsersFromLockScreen.getValue(); } boolean canCreateSupervisedUser() { @@ -516,17 +526,48 @@ public class UserSwitcherController implements Dumpable { return null; } + /** + * Notifies that a user has been selected. + * + * <p>This will trigger the right user journeys to create a guest user, switch users, and/or + * navigate to the correct destination. + * + * <p>If a user with the given ID is not found, this method is a no-op. + * + * @param userId The ID of the user to switch to. + * @param dialogShower An optional {@link DialogShower} in case we need to show dialogs. + */ + public void onUserSelected(int userId, @Nullable DialogShower dialogShower) { + UserRecord userRecord = mUsers.stream() + .filter(x -> x.resolveId() == userId) + .findFirst() + .orElse(null); + if (userRecord == null) { + return; + } + + onUserListItemClicked(userRecord, dialogShower); + } + + /** Whether it is allowed to add users while the device is locked. */ + public Flow<Boolean> getAddUsersFromLockScreen() { + return mAddUsersFromLockScreen; + } + + /** Returns {@code true} if the guest user is configured to always be present on the device. */ + public boolean isGuestUserAutoCreated() { + return mGuestUserAutoCreated; + } + + /** Returns {@code true} if the guest user is currently being reset. */ + public boolean isGuestUserResetting() { + return mGuestIsResetting.get(); + } + @VisibleForTesting void onUserListItemClicked(UserRecord record, DialogShower dialogShower) { if (record.isGuest && record.info == null) { - // No guest user. Create one. - createGuestAsync(guestId -> { - // guestId may be USER_NULL if we haven't reloaded the user list yet. - if (guestId != UserHandle.USER_NULL) { - mUiEventLogger.log(QSUserSwitcherEvent.QS_USER_GUEST_ADD); - onUserListItemClicked(guestId, record, dialogShower); - } - }); + createAndSwitchToGuestUser(dialogShower); } else if (record.isAddUser) { showAddUserDialog(dialogShower); } else if (record.isAddSupervisedUser) { @@ -604,7 +645,23 @@ public class UserSwitcherController implements Dumpable { } } - private void showAddUserDialog(DialogShower dialogShower) { + /** + * Creates and switches to the guest user. + */ + public void createAndSwitchToGuestUser(@Nullable DialogShower dialogShower) { + createGuestAsync(guestId -> { + // guestId may be USER_NULL if we haven't reloaded the user list yet. + if (guestId != UserHandle.USER_NULL) { + mUiEventLogger.log(QSUserSwitcherEvent.QS_USER_GUEST_ADD); + onUserListItemClicked(guestId, UserRecord.createForGuest(), dialogShower); + } + }); + } + + /** + * Shows the add user dialog. + */ + public void showAddUserDialog(@Nullable DialogShower dialogShower) { if (mAddUserDialog != null && mAddUserDialog.isShowing()) { mAddUserDialog.cancel(); } @@ -620,7 +677,10 @@ public class UserSwitcherController implements Dumpable { } } - private void startSupervisedUserActivity() { + /** + * Starts an activity to add a supervised user to the device. + */ + public void startSupervisedUserActivity() { final Intent intent = new Intent() .setAction(UserManager.ACTION_CREATE_SUPERVISED_USER) .setPackage(mCreateSupervisedUserPackage) @@ -772,7 +832,7 @@ public class UserSwitcherController implements Dumpable { * Removes guest user and switches to target user. The guest must be the current user and its id * must be {@code guestUserId}. * - * <p>If {@code targetUserId} is {@link UserHandle.USER_NULL}, then create a new guest user in + * <p>If {@code targetUserId} is {@link UserHandle#USER_NULL}, then create a new guest user in * the foreground, and immediately switch to it. This is used for wiping the current guest and * replacing it with a new one. * @@ -782,11 +842,11 @@ public class UserSwitcherController implements Dumpable { * <p>If device is configured with {@link * com.android.internal.R.bool.config_guestUserAutoCreated}, then after guest user is removed, a * new one is created in the background. This has no effect if {@code targetUserId} is {@link - * UserHandle.USER_NULL}. + * UserHandle#USER_NULL}. * * @param guestUserId id of the guest user to remove * @param targetUserId id of the user to switch to after guest is removed. If {@link - * UserHandle.USER_NULL}, then switch immediately to the newly created guest user. + * UserHandle#USER_NULL}, then switch immediately to the newly created guest user. */ public void removeGuestUser(@UserIdInt int guestUserId, @UserIdInt int targetUserId) { UserInfo currentUser = mUserTracker.getUserInfo(); @@ -839,7 +899,7 @@ public class UserSwitcherController implements Dumpable { * user. * * @param guestUserId user id of the guest user to exit - * @param targetUserId user id of the guest user to exit, set to UserHandle.USER_NULL when + * @param targetUserId user id of the guest user to exit, set to UserHandle#USER_NULL when * target user id is not known * @param forceRemoveGuestOnExit true: remove guest before switching user, * false: remove guest only if its ephemeral, else keep guest @@ -952,7 +1012,7 @@ public class UserSwitcherController implements Dumpable { * {@link UserManager} to create a new one. * * @return The multi-user user ID of the newly created guest user, or - * {@link UserHandle.USER_NULL} if the guest couldn't be created. + * {@link UserHandle#USER_NULL} if the guest couldn't be created. */ public @UserIdInt int createGuest() { UserInfo guest; @@ -1062,38 +1122,19 @@ public class UserSwitcherController implements Dumpable { } public String getName(Context context, UserRecord item) { - if (item.isGuest) { - if (item.isCurrent) { - return context.getString( - com.android.settingslib.R.string.guest_exit_quick_settings_button); - } else { - if (item.info != null) { - return context.getString(com.android.internal.R.string.guest_name); - } else { - if (mController.mGuestUserAutoCreated) { - // If mGuestIsResetting=true, we expect the guest user to be created - // shortly, so display a "Resetting guest..." as an indicator that we - // are busy. Otherwise, if mGuestIsResetting=false, we probably failed - // to create a guest at some point. In this case, always show guest - // nickname instead of "Add guest" to make it seem as though the device - // always has a guest ready for use. - return context.getString( - mController.mGuestIsResetting.get() - ? com.android.settingslib.R.string.guest_resetting - : com.android.internal.R.string.guest_name); - } else { - // we always show "guest" as string, instead of "add guest" - return context.getString(com.android.internal.R.string.guest_name); - } - } - } - } else if (item.isAddUser) { - return context.getString(com.android.settingslib.R.string.user_add_user); - } else if (item.isAddSupervisedUser) { - return context.getString(R.string.add_user_supervised); - } else { - return item.info.name; - } + return getName(context, item, false); + } + + /** + * Returns the name for the given {@link UserRecord}. + */ + public String getName(Context context, UserRecord item, boolean isTablet) { + return LegacyUserUiHelper.getUserRecordName( + context, + item, + mController.isGuestUserAutoCreated(), + mController.isGuestUserResetting(), + isTablet); } protected static ColorFilter getDisabledUserAvatarColorFilter() { @@ -1103,17 +1144,12 @@ public class UserSwitcherController implements Dumpable { } protected static Drawable getIconDrawable(Context context, UserRecord item) { - int iconRes; - if (item.isAddUser) { - iconRes = R.drawable.ic_add; - } else if (item.isGuest) { - iconRes = R.drawable.ic_account_circle; - } else if (item.isAddSupervisedUser) { - iconRes = R.drawable.ic_add_supervised_user; - } else { - iconRes = R.drawable.ic_avatar_user; - } - + return getIconDrawable(context, item, false); + } + protected static Drawable getIconDrawable(Context context, UserRecord item, + boolean isTablet) { + int iconRes = LegacyUserUiHelper.getUserSwitcherActionIconResourceId( + item.isAddUser, item.isGuest, item.isAddSupervisedUser, isTablet); return context.getDrawable(iconRes); } diff --git a/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayController.kt b/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayController.kt new file mode 100644 index 000000000000..a52e2aff52c1 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayController.kt @@ -0,0 +1,206 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.temporarydisplay + +import android.annotation.LayoutRes +import android.annotation.SuppressLint +import android.content.Context +import android.graphics.PixelFormat +import android.graphics.drawable.Drawable +import android.os.PowerManager +import android.os.SystemClock +import android.view.LayoutInflater +import android.view.ViewGroup +import android.view.WindowManager +import android.view.accessibility.AccessibilityManager +import android.view.accessibility.AccessibilityManager.FLAG_CONTENT_CONTROLS +import android.view.accessibility.AccessibilityManager.FLAG_CONTENT_ICONS +import android.view.accessibility.AccessibilityManager.FLAG_CONTENT_TEXT +import androidx.annotation.CallSuper +import com.android.systemui.dagger.qualifiers.Main +import com.android.systemui.statusbar.policy.ConfigurationController +import com.android.systemui.util.concurrency.DelayableExecutor + +/** + * A generic controller that can temporarily display a new view in a new window. + * + * Subclasses need to override and implement [updateView], which is where they can control what + * gets displayed to the user. + * + * The generic type T is expected to contain all the information necessary for the subclasses to + * display the view in a certain state, since they receive <T> in [updateView]. + * + * @property windowTitle the title to use for the window that displays the temporary view. Should be + * normally cased, like "Window Title". + * @property wakeReason a string used for logging if we needed to wake the screen in order to + * display the temporary view. Should be screaming snake cased, like WAKE_REASON. + */ +abstract class TemporaryViewDisplayController<T : TemporaryViewInfo, U : TemporaryViewLogger>( + internal val context: Context, + internal val logger: U, + internal val windowManager: WindowManager, + @Main private val mainExecutor: DelayableExecutor, + private val accessibilityManager: AccessibilityManager, + private val configurationController: ConfigurationController, + private val powerManager: PowerManager, + @LayoutRes private val viewLayoutRes: Int, + private val windowTitle: String, + private val wakeReason: String, +) { + /** + * Window layout params that will be used as a starting point for the [windowLayoutParams] of + * all subclasses. + */ + @SuppressLint("WrongConstant") // We're allowed to use TYPE_VOLUME_OVERLAY + internal val commonWindowLayoutParams = WindowManager.LayoutParams().apply { + width = WindowManager.LayoutParams.WRAP_CONTENT + height = WindowManager.LayoutParams.WRAP_CONTENT + type = WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY + flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL + title = windowTitle + format = PixelFormat.TRANSLUCENT + setTrustedOverlay() + } + + /** + * The window layout parameters we'll use when attaching the view to a window. + * + * Subclasses must override this to provide their specific layout params, and they should use + * [commonWindowLayoutParams] as part of their layout params. + */ + internal abstract val windowLayoutParams: WindowManager.LayoutParams + + /** The view currently being displayed. Null if the view is not being displayed. */ + private var view: ViewGroup? = null + + /** The info currently being displayed. Null if the view is not being displayed. */ + internal var info: T? = null + + /** A [Runnable] that, when run, will cancel the pending timeout of the view. */ + private var cancelViewTimeout: Runnable? = null + + /** + * Displays the view with the provided [newInfo]. + * + * This method handles inflating and attaching the view, then delegates to [updateView] to + * display the correct information in the view. + */ + fun displayView(newInfo: T) { + val currentView = view + + if (currentView != null) { + updateView(newInfo, currentView) + } else { + // The view is new, so set up all our callbacks and inflate the view + configurationController.addCallback(displayScaleListener) + // Wake the screen if necessary so the user will see the view. (Per b/239426653, we want + // the view to show over the dream state, so we should only wake up if the screen is + // completely off.) + if (!powerManager.isScreenOn) { + powerManager.wakeUp( + SystemClock.uptimeMillis(), + PowerManager.WAKE_REASON_APPLICATION, + "com.android.systemui:$wakeReason", + ) + } + logger.logChipAddition() + inflateAndUpdateView(newInfo) + } + + // Cancel and re-set the view timeout each time we get a new state. + val timeout = accessibilityManager.getRecommendedTimeoutMillis( + newInfo.getTimeoutMs().toInt(), + // Not all views have controls so FLAG_CONTENT_CONTROLS might be superfluous, but + // include it just to be safe. + FLAG_CONTENT_ICONS or FLAG_CONTENT_TEXT or FLAG_CONTENT_CONTROLS + ) + cancelViewTimeout?.run() + cancelViewTimeout = mainExecutor.executeDelayed( + { removeView(TemporaryDisplayRemovalReason.REASON_TIMEOUT) }, + timeout.toLong() + ) + } + + /** Inflates a new view, updates it with [newInfo], and adds the view to the window. */ + private fun inflateAndUpdateView(newInfo: T) { + val newView = LayoutInflater + .from(context) + .inflate(viewLayoutRes, null) as ViewGroup + view = newView + updateView(newInfo, newView) + windowManager.addView(newView, windowLayoutParams) + animateViewIn(newView) + } + + /** Removes then re-inflates the view. */ + private fun reinflateView() { + val currentInfo = info + if (view == null || currentInfo == null) { return } + + windowManager.removeView(view) + inflateAndUpdateView(currentInfo) + } + + private val displayScaleListener = object : ConfigurationController.ConfigurationListener { + override fun onDensityOrFontScaleChanged() { + reinflateView() + } + } + + /** + * Hides the view. + * + * @param removalReason a short string describing why the view was removed (timeout, state + * change, etc.) + */ + open fun removeView(removalReason: String) { + if (view == null) { return } + logger.logChipRemoval(removalReason) + configurationController.removeCallback(displayScaleListener) + windowManager.removeView(view) + view = null + info = null + // No need to time the view out since it's already gone + cancelViewTimeout?.run() + } + + /** + * A method implemented by subclasses to update [currentView] based on [newInfo]. + */ + @CallSuper + open fun updateView(newInfo: T, currentView: ViewGroup) { + info = newInfo + } + + /** + * A method that can be implemented by subclasses to do custom animations for when the view + * appears. + */ + open fun animateViewIn(view: ViewGroup) {} +} + +object TemporaryDisplayRemovalReason { + const val REASON_TIMEOUT = "TIMEOUT" + const val REASON_SCREEN_TAP = "SCREEN_TAP" +} + +private data class IconInfo( + val iconName: String, + val icon: Drawable, + /** True if [icon] is the app's icon, and false if [icon] is some generic default icon. */ + val isAppIcon: Boolean +) diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/ChipInfoCommon.kt b/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewInfo.kt index a29c5883118c..4fe753a80faf 100644 --- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/common/ChipInfoCommon.kt +++ b/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewInfo.kt @@ -14,17 +14,17 @@ * limitations under the License. */ -package com.android.systemui.media.taptotransfer.common +package com.android.systemui.temporarydisplay /** - * A superclass chip state that will be subclassed by the sender chip and receiver chip. + * A superclass view state used with [TemporaryViewDisplayController]. */ -interface ChipInfoCommon { +interface TemporaryViewInfo { /** - * Returns the amount of time the given chip state should display on the screen before it times + * Returns the amount of time the given view state should display on the screen before it times * out and disappears. */ - fun getTimeoutMs(): Long + fun getTimeoutMs(): Long = DEFAULT_TIMEOUT_MILLIS } const val DEFAULT_TIMEOUT_MILLIS = 10000L diff --git a/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewLogger.kt b/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewLogger.kt new file mode 100644 index 000000000000..606a11a84686 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/temporarydisplay/TemporaryViewLogger.kt @@ -0,0 +1,36 @@ +/* + * 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.temporarydisplay + +import com.android.systemui.log.LogBuffer +import com.android.systemui.log.LogLevel + +/** A logger for temporary view changes -- see [TemporaryViewDisplayController]. */ +open class TemporaryViewLogger( + internal val buffer: LogBuffer, + internal val tag: String, +) { + /** Logs that we added the chip to a new window. */ + fun logChipAddition() { + buffer.log(tag, LogLevel.DEBUG, {}, { "Chip added" }) + } + + /** Logs that we removed the chip for the given [reason]. */ + fun logChipRemoval(reason: String) { + buffer.log(tag, LogLevel.DEBUG, { str1 = reason }, { "Chip removed due to $str1" }) + } +} diff --git a/packages/SystemUI/src/com/android/systemui/unfold/FoldAodAnimationController.kt b/packages/SystemUI/src/com/android/systemui/unfold/FoldAodAnimationController.kt index 8f127fd1fcb4..0f0614414a3f 100644 --- a/packages/SystemUI/src/com/android/systemui/unfold/FoldAodAnimationController.kt +++ b/packages/SystemUI/src/com/android/systemui/unfold/FoldAodAnimationController.kt @@ -18,22 +18,31 @@ package com.android.systemui.unfold import android.content.Context import android.hardware.devicestate.DeviceStateManager -import android.os.Handler import android.os.PowerManager import android.provider.Settings +import androidx.annotation.VisibleForTesting import androidx.core.view.OneShotPreDrawListener +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.repeatOnLifecycle import com.android.internal.util.LatencyTracker import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.keyguard.WakefulnessLifecycle +import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor +import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.statusbar.LightRevealScrim import com.android.systemui.statusbar.phone.CentralSurfaces import com.android.systemui.statusbar.phone.ScreenOffAnimation import com.android.systemui.statusbar.policy.CallbackController import com.android.systemui.unfold.FoldAodAnimationController.FoldAodAnimationStatus +import com.android.systemui.util.concurrency.DelayableExecutor import com.android.systemui.util.settings.GlobalSettings -import java.util.concurrent.Executor +import dagger.Lazy import java.util.function.Consumer import javax.inject.Inject +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Job +import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.launch /** * Controls folding to AOD animation: when AOD is enabled and foldable device is folded we play a @@ -43,16 +52,16 @@ import javax.inject.Inject class FoldAodAnimationController @Inject constructor( - @Main private val handler: Handler, - @Main private val executor: Executor, + @Main private val executor: DelayableExecutor, private val context: Context, private val deviceStateManager: DeviceStateManager, private val wakefulnessLifecycle: WakefulnessLifecycle, private val globalSettings: GlobalSettings, private val latencyTracker: LatencyTracker, + private val keyguardInteractor: Lazy<KeyguardInteractor>, ) : CallbackController<FoldAodAnimationStatus>, ScreenOffAnimation, WakefulnessLifecycle.Observer { - private lateinit var mCentralSurfaces: CentralSurfaces + private lateinit var centralSurfaces: CentralSurfaces private var isFolded = false private var isFoldHandled = true @@ -64,12 +73,13 @@ constructor( private var shouldPlayAnimation = false private var isAnimationPlaying = false + private var cancelAnimation: Runnable? = null private val statusListeners = arrayListOf<FoldAodAnimationStatus>() private val foldToAodLatencyTracker = FoldToAodLatencyTracker() private val startAnimationRunnable = Runnable { - mCentralSurfaces.notificationPanelViewController.startFoldToAodAnimation( + centralSurfaces.notificationPanelViewController.startFoldToAodAnimation( /* startAction= */ { foldToAodLatencyTracker.onAnimationStarted() }, /* endAction= */ { setAnimationState(playing = false) }, /* cancelAction= */ { setAnimationState(playing = false) }, @@ -77,10 +87,14 @@ constructor( } override fun initialize(centralSurfaces: CentralSurfaces, lightRevealScrim: LightRevealScrim) { - this.mCentralSurfaces = centralSurfaces + this.centralSurfaces = centralSurfaces deviceStateManager.registerCallback(executor, FoldListener()) wakefulnessLifecycle.addObserver(this) + + centralSurfaces.notificationPanelViewController.view.repeatWhenAttached { + repeatOnLifecycle(Lifecycle.State.STARTED) { listenForDozing(this) } + } } /** Returns true if we should run fold to AOD animation */ @@ -94,7 +108,7 @@ constructor( override fun startAnimation(): Boolean = if (shouldStartAnimation()) { setAnimationState(playing = true) - mCentralSurfaces.notificationPanelViewController.prepareFoldToAodAnimation() + centralSurfaces.notificationPanelViewController.prepareFoldToAodAnimation() true } else { setAnimationState(playing = false) @@ -104,8 +118,8 @@ constructor( override fun onStartedWakingUp() { if (isAnimationPlaying) { foldToAodLatencyTracker.cancel() - handler.removeCallbacks(startAnimationRunnable) - mCentralSurfaces.notificationPanelViewController.cancelFoldToAodAnimation() + cancelAnimation?.run() + centralSurfaces.notificationPanelViewController.cancelFoldToAodAnimation() } setAnimationState(playing = false) @@ -138,13 +152,13 @@ constructor( // We should play the folding to AOD animation setAnimationState(playing = true) - mCentralSurfaces.notificationPanelViewController.prepareFoldToAodAnimation() + centralSurfaces.notificationPanelViewController.prepareFoldToAodAnimation() // We don't need to wait for the scrim as it is already displayed // but we should wait for the initial animation preparations to be drawn // (setting initial alpha/translation) OneShotPreDrawListener.add( - mCentralSurfaces.notificationPanelViewController.view, + centralSurfaces.notificationPanelViewController.view, onReady ) } else { @@ -165,18 +179,14 @@ constructor( fun onScreenTurnedOn() { if (shouldPlayAnimation) { - handler.removeCallbacks(startAnimationRunnable) + cancelAnimation?.run() // Post starting the animation to the next frame to avoid junk due to inset changes - handler.post(startAnimationRunnable) + cancelAnimation = executor.executeDelayed(startAnimationRunnable, /* delayMillis= */ 0) shouldPlayAnimation = false } } - fun setIsDozing(dozing: Boolean) { - isDozing = dozing - } - override fun isAnimationPlaying(): Boolean = isAnimationPlaying override fun isKeyguardHideDelayed(): Boolean = isAnimationPlaying() @@ -204,6 +214,11 @@ constructor( statusListeners.remove(listener) } + @VisibleForTesting + internal suspend fun listenForDozing(scope: CoroutineScope): Job { + return scope.launch { keyguardInteractor.get().isDozing.collect { isDozing = it } } + } + interface FoldAodAnimationStatus { fun onFoldToAodAnimationChanged() } diff --git a/packages/SystemUI/src/com/android/systemui/user/UserModule.java b/packages/SystemUI/src/com/android/systemui/user/UserModule.java index 469d54ff8ffa..5b522dcc4885 100644 --- a/packages/SystemUI/src/com/android/systemui/user/UserModule.java +++ b/packages/SystemUI/src/com/android/systemui/user/UserModule.java @@ -19,6 +19,7 @@ package com.android.systemui.user; import android.app.Activity; import com.android.settingslib.users.EditUserInfoController; +import com.android.systemui.user.data.repository.UserRepositoryModule; import dagger.Binds; import dagger.Module; @@ -29,7 +30,11 @@ import dagger.multibindings.IntoMap; /** * Dagger module for User related classes. */ -@Module +@Module( + includes = { + UserRepositoryModule.class, + } +) public abstract class UserModule { private static final String FILE_PROVIDER_AUTHORITY = "com.android.systemui.fileprovider"; diff --git a/packages/SystemUI/src/com/android/systemui/user/UserSwitcherActivity.kt b/packages/SystemUI/src/com/android/systemui/user/UserSwitcherActivity.kt index ff0f0d48a7c5..5e2dde6be046 100644 --- a/packages/SystemUI/src/com/android/systemui/user/UserSwitcherActivity.kt +++ b/packages/SystemUI/src/com/android/systemui/user/UserSwitcherActivity.kt @@ -27,6 +27,7 @@ import android.graphics.drawable.LayerDrawable import android.os.Bundle import android.os.UserManager import android.provider.Settings +import android.util.Log import android.view.LayoutInflater import android.view.MotionEvent import android.view.View @@ -35,8 +36,11 @@ import android.widget.AdapterView import android.widget.ArrayAdapter import android.widget.ImageView import android.widget.TextView +import android.window.OnBackInvokedCallback +import android.window.OnBackInvokedDispatcher import androidx.activity.ComponentActivity import androidx.constraintlayout.helper.widget.Flow +import androidx.lifecycle.ViewModelProvider import com.android.internal.annotations.VisibleForTesting import com.android.internal.util.UserIcons import com.android.settingslib.Utils @@ -44,6 +48,8 @@ import com.android.systemui.Gefingerpoken import com.android.systemui.R import com.android.systemui.broadcast.BroadcastDispatcher 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.FalsingManager.LOW_PENALTY import com.android.systemui.settings.UserTracker @@ -52,6 +58,9 @@ import com.android.systemui.statusbar.policy.UserSwitcherController.BaseUserAdap import com.android.systemui.statusbar.policy.UserSwitcherController.USER_SWITCH_DISABLED_ALPHA import com.android.systemui.statusbar.policy.UserSwitcherController.USER_SWITCH_ENABLED_ALPHA import com.android.systemui.user.data.source.UserRecord +import com.android.systemui.user.ui.binder.UserSwitcherViewBinder +import com.android.systemui.user.ui.viewmodel.UserSwitcherViewModel +import dagger.Lazy import javax.inject.Inject import kotlin.math.ceil @@ -60,14 +69,15 @@ private const val USER_VIEW = "user_view" /** * Support a fullscreen user switcher */ -class UserSwitcherActivity @Inject constructor( +open class UserSwitcherActivity @Inject constructor( private val userSwitcherController: UserSwitcherController, private val broadcastDispatcher: BroadcastDispatcher, - private val layoutInflater: LayoutInflater, private val falsingCollector: FalsingCollector, private val falsingManager: FalsingManager, private val userManager: UserManager, - private val userTracker: UserTracker + private val userTracker: UserTracker, + private val flags: FeatureFlags, + private val viewModelFactory: Lazy<UserSwitcherViewModel.Factory>, ) : ComponentActivity() { private lateinit var parent: UserSwitcherRootView @@ -75,6 +85,7 @@ class UserSwitcherActivity @Inject constructor( private var popupMenu: UserSwitcherPopupMenu? = null private lateinit var addButton: View private var addUserRecords = mutableListOf<UserRecord>() + private val onBackCallback = OnBackInvokedCallback { finish() } private val userSwitchedCallback: UserTracker.Callback = object : UserTracker.Callback { override fun onUserChanged(newUser: Int, userContext: Context) { finish() @@ -93,119 +104,35 @@ class UserSwitcherActivity @Inject constructor( false /* isAddSupervisedUser */ ) - private val adapter = object : BaseUserAdapter(userSwitcherController) { - override fun getView(position: Int, convertView: View?, parent: ViewGroup): View { - val item = getItem(position) - var view = convertView as ViewGroup? - if (view == null) { - view = layoutInflater.inflate( - R.layout.user_switcher_fullscreen_item, - parent, - false - ) as ViewGroup - } - (view.getChildAt(0) as ImageView).apply { - setImageDrawable(getDrawable(item)) - } - (view.getChildAt(1) as TextView).apply { - setText(getName(getContext(), item)) - } - - view.setEnabled(item.isSwitchToEnabled) - view.setAlpha( - if (view.isEnabled()) { - USER_SWITCH_ENABLED_ALPHA - } else { - USER_SWITCH_DISABLED_ALPHA - } - ) - view.setTag(USER_VIEW) - return view - } - - override fun getName(context: Context, item: UserRecord): String { - return if (item == manageUserRecord) { - getString(R.string.manage_users) - } else { - super.getName(context, item) - } - } - - fun findUserIcon(item: UserRecord): Drawable { - if (item == manageUserRecord) { - return getDrawable(R.drawable.ic_manage_users) - } - if (item.info == null) { - return getIconDrawable(this@UserSwitcherActivity, item) - } - val userIcon = userManager.getUserIcon(item.info.id) - if (userIcon != null) { - return BitmapDrawable(userIcon) - } - return UserIcons.getDefaultUserIcon(resources, item.info.id, false) - } - - fun getTotalUserViews(): Int { - return users.count { item -> - !doNotRenderUserView(item) - } - } - - fun doNotRenderUserView(item: UserRecord): Boolean { - return item.isAddUser || - item.isAddSupervisedUser || - item.isGuest && item.info == null - } - - private fun getDrawable(item: UserRecord): Drawable { - var drawable = if (item.isGuest) { - getDrawable(R.drawable.ic_account_circle) - } else { - findUserIcon(item) - } - drawable.mutate() - - if (!item.isCurrent && !item.isSwitchToEnabled) { - drawable.setTint( - resources.getColor( - R.color.kg_user_switcher_restricted_avatar_icon_color, - getTheme() - ) - ) - } - - val ld = getDrawable(R.drawable.user_switcher_icon_large).mutate() - as LayerDrawable - if (item == userSwitcherController.getCurrentUserRecord()) { - (ld.findDrawableByLayerId(R.id.ring) as GradientDrawable).apply { - val stroke = resources - .getDimensionPixelSize(R.dimen.user_switcher_icon_selected_width) - val color = Utils.getColorAttrDefaultColor( - this@UserSwitcherActivity, - com.android.internal.R.attr.colorAccentPrimary - ) - - setStroke(stroke, color) - } - } - - ld.setDrawableByLayerId(R.id.user_avatar, drawable) - return ld - } - - override fun notifyDataSetChanged() { - super.notifyDataSetChanged() - buildUserViews() - } - } + private val adapter: UserAdapter by lazy { UserAdapter() } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + createActivity() + } + @VisibleForTesting + fun createActivity() { setContentView(R.layout.user_switcher_fullscreen) - window.decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE - or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION - or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) + window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE + or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) + if (isUsingModernArchitecture()) { + Log.d(TAG, "Using modern architecture.") + val viewModel = ViewModelProvider( + this, viewModelFactory.get())[UserSwitcherViewModel::class.java] + UserSwitcherViewBinder.bind( + view = requireViewById(R.id.user_switcher_root), + viewModel = viewModel, + lifecycleOwner = this, + layoutInflater = layoutInflater, + falsingCollector = falsingCollector, + onFinish = this::finish, + ) + return + } else { + Log.d(TAG, "Not using modern architecture.") + } parent = requireViewById<UserSwitcherRootView>(R.id.user_switcher_root) @@ -228,6 +155,9 @@ class UserSwitcherActivity @Inject constructor( } } + onBackInvokedDispatcher.registerOnBackInvokedCallback( + OnBackInvokedDispatcher.PRIORITY_DEFAULT, onBackCallback) + userSwitcherController.init(parent) initBroadcastReceiver() @@ -243,8 +173,8 @@ class UserSwitcherActivity @Inject constructor( this, R.layout.user_switcher_fullscreen_popup_item, layoutInflater, - { item: UserRecord -> adapter.getName(this@UserSwitcherActivity, item) }, - { item: UserRecord -> adapter.findUserIcon(item).mutate().apply { + { item: UserRecord -> adapter.getName(this@UserSwitcherActivity, item, true) }, + { item: UserRecord -> adapter.findUserIcon(item, true).mutate().apply { setTint(resources.getColor( R.color.user_switcher_fullscreen_popup_item_tint, getTheme() @@ -346,12 +276,24 @@ class UserSwitcherActivity @Inject constructor( } override fun onBackPressed() { + if (isUsingModernArchitecture()) { + return super.onBackPressed() + } + finish() } override fun onDestroy() { super.onDestroy() + if (isUsingModernArchitecture()) { + return + } + destroyActivity() + } + @VisibleForTesting + fun destroyActivity() { + onBackInvokedDispatcher.unregisterOnBackInvokedCallback(onBackCallback) broadcastDispatcher.unregisterReceiver(broadcastReceiver) userTracker.removeCallback(userSwitchedCallback) } @@ -376,6 +318,13 @@ class UserSwitcherActivity @Inject constructor( return if (userCount < 5) 4 else ceil(userCount / 2.0).toInt() } + private fun isUsingModernArchitecture(): Boolean { + return flags.isEnabled(Flags.MODERN_USER_SWITCHER_ACTIVITY) + } + + /** + * Provides views to populate the option menu. + */ private class ItemAdapter( val parentContext: Context, val resource: Int, @@ -398,4 +347,114 @@ class UserSwitcherActivity @Inject constructor( return view } } + + private inner class UserAdapter : BaseUserAdapter(userSwitcherController) { + override fun getView(position: Int, convertView: View?, parent: ViewGroup): View { + val item = getItem(position) + var view = convertView as ViewGroup? + if (view == null) { + view = layoutInflater.inflate( + R.layout.user_switcher_fullscreen_item, + parent, + false + ) as ViewGroup + } + (view.getChildAt(0) as ImageView).apply { + setImageDrawable(getDrawable(item)) + } + (view.getChildAt(1) as TextView).apply { + setText(getName(getContext(), item)) + } + + view.setEnabled(item.isSwitchToEnabled) + view.setAlpha( + if (view.isEnabled()) { + USER_SWITCH_ENABLED_ALPHA + } else { + USER_SWITCH_DISABLED_ALPHA + } + ) + view.setTag(USER_VIEW) + return view + } + + override fun getName(context: Context, item: UserRecord, isTablet: Boolean): String { + return if (item == manageUserRecord) { + getString(R.string.manage_users) + } else { + super.getName(context, item, isTablet) + } + } + + fun findUserIcon(item: UserRecord, isTablet: Boolean = false): Drawable { + if (item == manageUserRecord) { + return getDrawable(R.drawable.ic_manage_users) + } + if (item.info == null) { + return getIconDrawable(this@UserSwitcherActivity, item, isTablet) + } + val userIcon = userManager.getUserIcon(item.info.id) + if (userIcon != null) { + return BitmapDrawable(userIcon) + } + return UserIcons.getDefaultUserIcon(resources, item.info.id, false) + } + + fun getTotalUserViews(): Int { + return users.count { item -> + !doNotRenderUserView(item) + } + } + + fun doNotRenderUserView(item: UserRecord): Boolean { + return item.isAddUser || + item.isAddSupervisedUser || + item.isGuest && item.info == null + } + + private fun getDrawable(item: UserRecord): Drawable { + var drawable = if (item.isGuest) { + getDrawable(R.drawable.ic_account_circle) + } else { + findUserIcon(item) + } + drawable.mutate() + + if (!item.isCurrent && !item.isSwitchToEnabled) { + drawable.setTint( + resources.getColor( + R.color.kg_user_switcher_restricted_avatar_icon_color, + getTheme() + ) + ) + } + + val ld = getDrawable(R.drawable.user_switcher_icon_large).mutate() + as LayerDrawable + if (item == userSwitcherController.getCurrentUserRecord()) { + (ld.findDrawableByLayerId(R.id.ring) as GradientDrawable).apply { + val stroke = resources + .getDimensionPixelSize(R.dimen.user_switcher_icon_selected_width) + val color = Utils.getColorAttrDefaultColor( + this@UserSwitcherActivity, + com.android.internal.R.attr.colorAccentPrimary + ) + + setStroke(stroke, color) + } + } + + ld.setDrawableByLayerId(R.id.user_avatar, drawable) + return ld + } + + override fun notifyDataSetChanged() { + super.notifyDataSetChanged() + buildUserViews() + } + } + + companion object { + private const val TAG = "UserSwitcherActivity" + } } diff --git a/packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepository.kt b/packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepository.kt new file mode 100644 index 000000000000..305b5ee920a1 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepository.kt @@ -0,0 +1,166 @@ +/* + * 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.user.data.repository + +import android.content.Context +import android.graphics.drawable.BitmapDrawable +import android.graphics.drawable.Drawable +import android.os.UserManager +import androidx.appcompat.content.res.AppCompatResources +import com.android.internal.util.UserIcons +import com.android.systemui.R +import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging +import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow +import com.android.systemui.common.shared.model.Text +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.dagger.qualifiers.Application +import com.android.systemui.statusbar.policy.UserSwitcherController +import com.android.systemui.user.data.source.UserRecord +import com.android.systemui.user.legacyhelper.ui.LegacyUserUiHelper +import com.android.systemui.user.shared.model.UserActionModel +import com.android.systemui.user.shared.model.UserModel +import javax.inject.Inject +import kotlinx.coroutines.channels.awaitClose +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.map + +/** + * Acts as source of truth for user related data. + * + * Abstracts-away data sources and their schemas so the rest of the app doesn't need to worry about + * upstream changes. + */ +interface UserRepository { + /** List of all users on the device. */ + val users: Flow<List<UserModel>> + + /** The currently-selected user. */ + val selectedUser: Flow<UserModel> + + /** List of available user-related actions. */ + val actions: Flow<List<UserActionModel>> + + /** Whether actions are available even when locked. */ + val isActionableWhenLocked: Flow<Boolean> + + /** Whether the device is configured to always have a guest user available. */ + val isGuestUserAutoCreated: Boolean + + /** Whether the guest user is currently being reset. */ + val isGuestUserResetting: Boolean +} + +@SysUISingleton +class UserRepositoryImpl +@Inject +constructor( + @Application private val appContext: Context, + private val manager: UserManager, + controller: UserSwitcherController, +) : UserRepository { + + private val userRecords: Flow<List<UserRecord>> = conflatedCallbackFlow { + fun send() { + trySendWithFailureLogging( + controller.users, + TAG, + ) + } + + val callback = UserSwitcherController.UserSwitchCallback { send() } + + controller.addUserSwitchCallback(callback) + send() + + awaitClose { controller.removeUserSwitchCallback(callback) } + } + + override val users: Flow<List<UserModel>> = + userRecords.map { records -> records.filter { it.isUser() }.map { it.toUserModel() } } + + override val selectedUser: Flow<UserModel> = + users.map { users -> users.first { user -> user.isSelected } } + + override val actions: Flow<List<UserActionModel>> = + userRecords.map { records -> records.filter { it.isNotUser() }.map { it.toActionModel() } } + + override val isActionableWhenLocked: Flow<Boolean> = controller.addUsersFromLockScreen + + override val isGuestUserAutoCreated: Boolean = controller.isGuestUserAutoCreated + + override val isGuestUserResetting: Boolean = controller.isGuestUserResetting + + private fun UserRecord.isUser(): Boolean { + return when { + isAddUser -> false + isAddSupervisedUser -> false + isGuest -> info != null + else -> true + } + } + + private fun UserRecord.isNotUser(): Boolean { + return !isUser() + } + + private fun UserRecord.toUserModel(): UserModel { + return UserModel( + id = resolveId(), + name = getUserName(this), + image = getUserImage(this), + isSelected = isCurrent, + isSelectable = isSwitchToEnabled || isGuest, + ) + } + + private fun UserRecord.toActionModel(): UserActionModel { + return when { + isAddUser -> UserActionModel.ADD_USER + isAddSupervisedUser -> UserActionModel.ADD_SUPERVISED_USER + isGuest -> UserActionModel.ENTER_GUEST_MODE + else -> error("Don't know how to convert to UserActionModel: $this") + } + } + + private fun getUserName(record: UserRecord): Text { + val resourceId: Int? = LegacyUserUiHelper.getGuestUserRecordNameResourceId(record) + return if (resourceId != null) { + Text.Resource(resourceId) + } else { + Text.Loaded(checkNotNull(record.info).name) + } + } + + private fun getUserImage(record: UserRecord): Drawable { + if (record.isGuest) { + return checkNotNull( + AppCompatResources.getDrawable(appContext, R.drawable.ic_account_circle) + ) + } + + val userId = checkNotNull(record.info?.id) + return manager.getUserIcon(userId)?.let { userSelectedIcon -> + BitmapDrawable(userSelectedIcon) + } + ?: UserIcons.getDefaultUserIcon(appContext.resources, userId, /* light= */ false) + } + + companion object { + private const val TAG = "UserRepository" + } +} diff --git a/packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepositoryModule.kt b/packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepositoryModule.kt new file mode 100644 index 000000000000..18ae1070e1bb --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepositoryModule.kt @@ -0,0 +1,26 @@ +/* + * 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.user.data.repository + +import dagger.Binds +import dagger.Module + +@Module +interface UserRepositoryModule { + @Binds fun bindRepository(impl: UserRepositoryImpl): UserRepository +} diff --git a/packages/SystemUI/src/com/android/systemui/user/data/source/UserRecord.kt b/packages/SystemUI/src/com/android/systemui/user/data/source/UserRecord.kt index 6ab6d7d7891a..cf6da9a60d78 100644 --- a/packages/SystemUI/src/com/android/systemui/user/data/source/UserRecord.kt +++ b/packages/SystemUI/src/com/android/systemui/user/data/source/UserRecord.kt @@ -20,38 +20,29 @@ import android.content.pm.UserInfo import android.graphics.Bitmap import android.os.UserHandle -/** - * Encapsulates raw data for a user or an option item related to managing users on the device. - */ +/** Encapsulates raw data for a user or an option item related to managing users on the device. */ data class UserRecord( /** Relevant user information. If `null`, this record is not a user but an option item. */ - @JvmField - val info: UserInfo?, + @JvmField val info: UserInfo? = null, /** An image representing the user. */ - @JvmField - val picture: Bitmap?, + @JvmField val picture: Bitmap? = null, /** Whether this record represents an option to switch to a guest user. */ - @JvmField - val isGuest: Boolean, + @JvmField val isGuest: Boolean = false, /** Whether this record represents the currently-selected user. */ - @JvmField - val isCurrent: Boolean, + @JvmField val isCurrent: Boolean = false, /** Whether this record represents an option to add another user to the device. */ - @JvmField - val isAddUser: Boolean, - /** If true, the record is only visible to the owner and only when unlocked. */ - @JvmField - val isRestricted: Boolean, + @JvmField val isAddUser: Boolean = false, + /** + * If true, the record is only available if unlocked or if the user has granted permission to + * access this user action whilst on the device is locked. + */ + @JvmField val isRestricted: Boolean = false, /** Whether it is possible to switch to this user. */ - @JvmField - val isSwitchToEnabled: Boolean, + @JvmField val isSwitchToEnabled: Boolean = false, /** Whether this record represents an option to add another supervised user to the device. */ - @JvmField - val isAddSupervisedUser: Boolean, + @JvmField val isAddSupervisedUser: Boolean = false, ) { - /** - * Returns a new instance of [UserRecord] with its [isCurrent] set to the given value. - */ + /** Returns a new instance of [UserRecord] with its [isCurrent] set to the given value. */ fun copyWithIsCurrent(isCurrent: Boolean): UserRecord { return copy(isCurrent = isCurrent) } @@ -67,4 +58,11 @@ data class UserRecord( info.id } } + + companion object { + @JvmStatic + fun createForGuest(): UserRecord { + return UserRecord(isGuest = true) + } + } } diff --git a/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserInteractor.kt b/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserInteractor.kt new file mode 100644 index 000000000000..3c5b9697c013 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/user/domain/interactor/UserInteractor.kt @@ -0,0 +1,110 @@ +/* + * 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.user.domain.interactor + +import android.content.Intent +import android.provider.Settings +import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor +import com.android.systemui.plugins.ActivityStarter +import com.android.systemui.statusbar.policy.UserSwitcherController +import com.android.systemui.user.data.repository.UserRepository +import com.android.systemui.user.shared.model.UserActionModel +import com.android.systemui.user.shared.model.UserModel +import javax.inject.Inject +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.flatMapLatest +import kotlinx.coroutines.flow.flowOf +import kotlinx.coroutines.flow.map + +/** Encapsulates business logic to interact with user data and systems. */ +@SysUISingleton +class UserInteractor +@Inject +constructor( + repository: UserRepository, + private val controller: UserSwitcherController, + private val activityStarter: ActivityStarter, + keyguardInteractor: KeyguardInteractor, +) { + /** List of current on-device users to select from. */ + val users: Flow<List<UserModel>> = repository.users + + /** The currently-selected user. */ + val selectedUser: Flow<UserModel> = repository.selectedUser + + /** List of user-switcher related actions that are available. */ + val actions: Flow<List<UserActionModel>> = + combine( + repository.isActionableWhenLocked, + keyguardInteractor.isKeyguardShowing, + ) { isActionableWhenLocked, isLocked -> + isActionableWhenLocked || !isLocked + } + .flatMapLatest { isActionable -> + if (isActionable) { + repository.actions.map { actions -> + actions + + if (actions.isNotEmpty()) { + // If we have actions, we add NAVIGATE_TO_USER_MANAGEMENT because + // that's a user + // switcher specific action that is not known to the our data source + // or other + // features. + listOf(UserActionModel.NAVIGATE_TO_USER_MANAGEMENT) + } else { + // If no actions, don't add the navigate action. + emptyList() + } + } + } else { + // If not actionable it means that we're not allowed to show actions when locked + // and we + // are locked. Therefore, we should show no actions. + flowOf(emptyList()) + } + } + + /** Whether the device is configured to always have a guest user available. */ + val isGuestUserAutoCreated: Boolean = repository.isGuestUserAutoCreated + + /** Whether the guest user is currently being reset. */ + val isGuestUserResetting: Boolean = repository.isGuestUserResetting + + /** Switches to the user with the given user ID. */ + fun selectUser( + userId: Int, + ) { + controller.onUserSelected(userId, /* dialogShower= */ null) + } + + /** Executes the given action. */ + fun executeAction(action: UserActionModel) { + when (action) { + UserActionModel.ENTER_GUEST_MODE -> controller.createAndSwitchToGuestUser(null) + UserActionModel.ADD_USER -> controller.showAddUserDialog(null) + UserActionModel.ADD_SUPERVISED_USER -> controller.startSupervisedUserActivity() + UserActionModel.NAVIGATE_TO_USER_MANAGEMENT -> + activityStarter.startActivity( + Intent(Settings.ACTION_USER_SETTINGS), + /* dismissShade= */ false, + ) + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/user/legacyhelper/ui/LegacyUserUiHelper.kt b/packages/SystemUI/src/com/android/systemui/user/legacyhelper/ui/LegacyUserUiHelper.kt new file mode 100644 index 000000000000..15fdc352d864 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/user/legacyhelper/ui/LegacyUserUiHelper.kt @@ -0,0 +1,137 @@ +/* + * 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.user.legacyhelper.ui + +import android.content.Context +import androidx.annotation.DrawableRes +import androidx.annotation.StringRes +import com.android.systemui.R +import com.android.systemui.user.data.source.UserRecord +import kotlin.math.ceil + +/** + * Defines utility functions for helping with legacy UI code for users. + * + * We need these to avoid code duplication between logic inside the UserSwitcherController and in + * modern architecture classes such as repositories, interactors, and view-models. If we ever + * simplify UserSwitcherController (or delete it), the code here could be moved into its call-sites. + */ +object LegacyUserUiHelper { + + /** Returns the maximum number of columns for user items in the user switcher. */ + fun getMaxUserSwitcherItemColumns(userCount: Int): Int { + // TODO(b/243844097): remove this once we remove the old user switcher implementation. + return if (userCount < 5) { + 4 + } else { + ceil(userCount / 2.0).toInt() + } + } + + @JvmStatic + @DrawableRes + fun getUserSwitcherActionIconResourceId( + isAddUser: Boolean, + isGuest: Boolean, + isAddSupervisedUser: Boolean, + isTablet: Boolean = false, + ): Int { + return if (isAddUser && isTablet) { + R.drawable.ic_account_circle_filled + } else if (isAddUser) { + R.drawable.ic_add + } else if (isGuest) { + R.drawable.ic_account_circle + } else if (isAddSupervisedUser) { + R.drawable.ic_add_supervised_user + } else { + R.drawable.ic_avatar_user + } + } + + @JvmStatic + fun getUserRecordName( + context: Context, + record: UserRecord, + isGuestUserAutoCreated: Boolean, + isGuestUserResetting: Boolean, + isTablet: Boolean = false, + ): String { + val resourceId: Int? = getGuestUserRecordNameResourceId(record) + return when { + resourceId != null -> context.getString(resourceId) + record.info != null -> record.info.name + else -> + context.getString( + getUserSwitcherActionTextResourceId( + isGuest = record.isGuest, + isGuestUserAutoCreated = isGuestUserAutoCreated, + isGuestUserResetting = isGuestUserResetting, + isAddUser = record.isAddUser, + isAddSupervisedUser = record.isAddSupervisedUser, + isTablet = isTablet, + ) + ) + } + } + + /** + * Returns the resource ID for a string for the name of the guest user. + * + * If the given record is not the guest user, returns `null`. + */ + @StringRes + fun getGuestUserRecordNameResourceId(record: UserRecord): Int? { + return when { + record.isGuest && record.isCurrent -> + com.android.settingslib.R.string.guest_exit_quick_settings_button + record.isGuest && record.info != null -> com.android.internal.R.string.guest_name + else -> null + } + } + + @JvmStatic + @StringRes + fun getUserSwitcherActionTextResourceId( + isGuest: Boolean, + isGuestUserAutoCreated: Boolean, + isGuestUserResetting: Boolean, + isAddUser: Boolean, + isAddSupervisedUser: Boolean, + isTablet: Boolean = false, + ): Int { + check(isGuest || isAddUser || isAddSupervisedUser) + + return when { + isGuest && isGuestUserAutoCreated && isGuestUserResetting -> + com.android.settingslib.R.string.guest_resetting + isGuest && isTablet -> com.android.settingslib.R.string.guest_new_guest + isGuest && isGuestUserAutoCreated -> com.android.internal.R.string.guest_name + isGuest -> com.android.internal.R.string.guest_name + isAddUser -> com.android.settingslib.R.string.user_add_user + isAddSupervisedUser -> R.string.add_user_supervised + else -> error("This should never happen!") + } + } + + /** Alpha value to apply to a user view in the user switcher when it's selectable. */ + const val USER_SWITCHER_USER_VIEW_SELECTABLE_ALPHA = 1.0f + + /** Alpha value to apply to a user view in the user switcher when it's not selectable. */ + const val USER_SWITCHER_USER_VIEW_NOT_SELECTABLE_ALPHA = 0.38f +} diff --git a/packages/SystemUI/src/com/android/systemui/user/shared/model/UserActionModel.kt b/packages/SystemUI/src/com/android/systemui/user/shared/model/UserActionModel.kt new file mode 100644 index 000000000000..823bf74dc0f0 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/user/shared/model/UserActionModel.kt @@ -0,0 +1,25 @@ +/* + * 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.user.shared.model + +enum class UserActionModel { + ENTER_GUEST_MODE, + ADD_USER, + ADD_SUPERVISED_USER, + NAVIGATE_TO_USER_MANAGEMENT, +} diff --git a/packages/SystemUI/src/com/android/systemui/user/shared/model/UserModel.kt b/packages/SystemUI/src/com/android/systemui/user/shared/model/UserModel.kt new file mode 100644 index 000000000000..bf7977a600e9 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/user/shared/model/UserModel.kt @@ -0,0 +1,35 @@ +/* + * 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.user.shared.model + +import android.graphics.drawable.Drawable +import com.android.systemui.common.shared.model.Text + +/** Represents a single user on the device. */ +data class UserModel( + /** ID of the user, unique across all users on this device. */ + val id: Int, + /** Human-facing name for this user. */ + val name: Text, + /** Human-facing image for this user. */ + val image: Drawable, + /** Whether this user is the currently-selected user. */ + val isSelected: Boolean, + /** Whether this use is selectable. A non-selectable user cannot be switched to. */ + val isSelectable: Boolean, +) diff --git a/packages/SystemUI/src/com/android/systemui/user/ui/binder/UserSwitcherViewBinder.kt b/packages/SystemUI/src/com/android/systemui/user/ui/binder/UserSwitcherViewBinder.kt new file mode 100644 index 000000000000..d7ad3cefaf06 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/user/ui/binder/UserSwitcherViewBinder.kt @@ -0,0 +1,223 @@ +/* + * 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.user.ui.binder + +import android.content.Context +import android.view.LayoutInflater +import android.view.MotionEvent +import android.view.View +import android.view.ViewGroup +import android.widget.BaseAdapter +import android.widget.ImageView +import android.widget.TextView +import androidx.constraintlayout.helper.widget.Flow as FlowWidget +import androidx.core.view.isVisible +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.LifecycleOwner +import androidx.lifecycle.lifecycleScope +import androidx.lifecycle.repeatOnLifecycle +import com.android.systemui.Gefingerpoken +import com.android.systemui.R +import com.android.systemui.classifier.FalsingCollector +import com.android.systemui.user.UserSwitcherPopupMenu +import com.android.systemui.user.UserSwitcherRootView +import com.android.systemui.user.ui.viewmodel.UserActionViewModel +import com.android.systemui.user.ui.viewmodel.UserSwitcherViewModel +import com.android.systemui.util.children +import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.flow.filter +import kotlinx.coroutines.launch + +/** Binds a user switcher to its view-model. */ +object UserSwitcherViewBinder { + + private const val USER_VIEW_TAG = "user_view" + + /** Binds the given view to the given view-model. */ + fun bind( + view: ViewGroup, + viewModel: UserSwitcherViewModel, + lifecycleOwner: LifecycleOwner, + layoutInflater: LayoutInflater, + falsingCollector: FalsingCollector, + onFinish: () -> Unit, + ) { + val rootView: UserSwitcherRootView = view.requireViewById(R.id.user_switcher_root) + val flowWidget: FlowWidget = view.requireViewById(R.id.flow) + val addButton: View = view.requireViewById(R.id.add) + val cancelButton: View = view.requireViewById(R.id.cancel) + val popupMenuAdapter = MenuAdapter(layoutInflater) + var popupMenu: UserSwitcherPopupMenu? = null + + rootView.touchHandler = + object : Gefingerpoken { + override fun onTouchEvent(ev: MotionEvent?): Boolean { + falsingCollector.onTouchEvent(ev) + return false + } + } + addButton.setOnClickListener { viewModel.onOpenMenuButtonClicked() } + cancelButton.setOnClickListener { viewModel.onCancelButtonClicked() } + + lifecycleOwner.lifecycleScope.launch { + lifecycleOwner.repeatOnLifecycle(Lifecycle.State.CREATED) { + launch { + viewModel.isFinishRequested + .filter { it } + .collect { + onFinish() + viewModel.onFinished() + } + } + } + } + + lifecycleOwner.lifecycleScope.launch { + lifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) { + launch { viewModel.isOpenMenuButtonVisible.collect { addButton.isVisible = it } } + + launch { + viewModel.isMenuVisible.collect { isVisible -> + if (isVisible && popupMenu?.isShowing != true) { + popupMenu?.dismiss() + // Use post to make sure we show the popup menu *after* the activity is + // ready to show one to avoid a WindowManager$BadTokenException. + view.post { + popupMenu = + createAndShowPopupMenu( + context = view.context, + anchorView = addButton, + adapter = popupMenuAdapter, + onDismissed = viewModel::onMenuClosed, + ) + } + } else if (!isVisible && popupMenu?.isShowing == true) { + popupMenu?.dismiss() + popupMenu = null + } + } + } + + launch { + viewModel.menu.collect { menuViewModels -> + popupMenuAdapter.setItems(menuViewModels) + } + } + + launch { + viewModel.maximumUserColumns.collect { maximumColumns -> + flowWidget.setMaxElementsWrap(maximumColumns) + } + } + + launch { + viewModel.users.collect { users -> + val viewPool = + view.children.filter { it.tag == USER_VIEW_TAG }.toMutableList() + viewPool.forEach { + view.removeView(it) + flowWidget.removeView(it) + } + users.forEach { userViewModel -> + val userView = + if (viewPool.isNotEmpty()) { + viewPool.removeAt(0) + } else { + val inflatedView = + layoutInflater.inflate( + R.layout.user_switcher_fullscreen_item, + view, + false, + ) + inflatedView.tag = USER_VIEW_TAG + inflatedView + } + userView.id = View.generateViewId() + view.addView(userView) + flowWidget.addView(userView) + UserViewBinder.bind( + view = userView, + viewModel = userViewModel, + ) + } + } + } + } + } + } + + private fun createAndShowPopupMenu( + context: Context, + anchorView: View, + adapter: MenuAdapter, + onDismissed: () -> Unit, + ): UserSwitcherPopupMenu { + return UserSwitcherPopupMenu(context).apply { + this.anchorView = anchorView + setAdapter(adapter) + setOnDismissListener { onDismissed() } + setOnItemClickListener { _, _, position, _ -> + val itemPositionExcludingHeader = position - 1 + adapter.getItem(itemPositionExcludingHeader).onClicked() + } + + show() + } + } + + /** Adapter for the menu that can be opened. */ + private class MenuAdapter( + private val layoutInflater: LayoutInflater, + ) : BaseAdapter() { + + private val items = mutableListOf<UserActionViewModel>() + + override fun getCount(): Int { + return items.size + } + + override fun getItem(position: Int): UserActionViewModel { + return items[position] + } + + override fun getItemId(position: Int): Long { + return getItem(position).viewKey + } + + override fun getView(position: Int, convertView: View?, parent: ViewGroup): View { + val view = + convertView + ?: layoutInflater.inflate( + R.layout.user_switcher_fullscreen_popup_item, + parent, + false + ) + val viewModel = getItem(position) + view.requireViewById<ImageView>(R.id.icon).setImageResource(viewModel.iconResourceId) + view.requireViewById<TextView>(R.id.text).text = + view.resources.getString(viewModel.textResourceId) + return view + } + + fun setItems(items: List<UserActionViewModel>) { + this.items.clear() + this.items.addAll(items) + notifyDataSetChanged() + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/user/ui/binder/UserViewBinder.kt b/packages/SystemUI/src/com/android/systemui/user/ui/binder/UserViewBinder.kt new file mode 100644 index 000000000000..e78807e675b3 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/user/ui/binder/UserViewBinder.kt @@ -0,0 +1,77 @@ +/* + * 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.user.ui.binder + +import android.content.Context +import android.graphics.drawable.Drawable +import android.graphics.drawable.GradientDrawable +import android.graphics.drawable.LayerDrawable +import android.view.View +import android.widget.ImageView +import androidx.core.content.res.ResourcesCompat +import com.android.settingslib.Utils +import com.android.systemui.R +import com.android.systemui.common.ui.binder.TextViewBinder +import com.android.systemui.user.ui.viewmodel.UserViewModel + +/** Binds a user view to its view-model. */ +object UserViewBinder { + /** Binds the given view to the given view-model. */ + fun bind(view: View, viewModel: UserViewModel) { + TextViewBinder.bind(view.requireViewById(R.id.user_switcher_text), viewModel.name) + view + .requireViewById<ImageView>(R.id.user_switcher_icon) + .setImageDrawable(getSelectableDrawable(view.context, viewModel)) + view.alpha = viewModel.alpha + if (viewModel.onClicked != null) { + view.setOnClickListener { viewModel.onClicked.invoke() } + } else { + view.setOnClickListener(null) + } + } + + private fun getSelectableDrawable(context: Context, viewModel: UserViewModel): Drawable { + val layerDrawable = + checkNotNull( + ResourcesCompat.getDrawable( + context.resources, + R.drawable.user_switcher_icon_large, + context.theme, + ) + ) + .mutate() as LayerDrawable + if (viewModel.isSelectionMarkerVisible) { + (layerDrawable.findDrawableByLayerId(R.id.ring) as GradientDrawable).apply { + val stroke = + context.resources.getDimensionPixelSize( + R.dimen.user_switcher_icon_selected_width + ) + val color = + Utils.getColorAttrDefaultColor( + context, + com.android.internal.R.attr.colorAccentPrimary + ) + + setStroke(stroke, color) + } + } + + layerDrawable.setDrawableByLayerId(R.id.user_avatar, viewModel.image) + return layerDrawable + } +} diff --git a/packages/SystemUI/src/com/android/systemui/user/ui/viewmodel/UserActionViewModel.kt b/packages/SystemUI/src/com/android/systemui/user/ui/viewmodel/UserActionViewModel.kt new file mode 100644 index 000000000000..149b1ffdaff0 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/user/ui/viewmodel/UserActionViewModel.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.user.ui.viewmodel + +import androidx.annotation.DrawableRes +import androidx.annotation.StringRes + +/** Models UI state for an action that can be performed on a user. */ +data class UserActionViewModel( + /** + * Key to use with the view or compose system to keep track of the view/composable across + * changes to the collection of [UserActionViewModel] instances. + */ + val viewKey: Long, + @DrawableRes val iconResourceId: Int, + @StringRes val textResourceId: Int, + val onClicked: () -> Unit, +) 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 new file mode 100644 index 000000000000..398341d256d2 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModel.kt @@ -0,0 +1,200 @@ +/* + * 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.user.ui.viewmodel + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider +import com.android.systemui.R +import com.android.systemui.common.ui.drawable.CircularDrawable +import com.android.systemui.power.domain.interactor.PowerInteractor +import com.android.systemui.user.domain.interactor.UserInteractor +import com.android.systemui.user.legacyhelper.ui.LegacyUserUiHelper +import com.android.systemui.user.shared.model.UserActionModel +import com.android.systemui.user.shared.model.UserModel +import javax.inject.Inject +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.map + +/** Models UI state for the user switcher feature. */ +class UserSwitcherViewModel +private constructor( + private val userInteractor: UserInteractor, + private val powerInteractor: PowerInteractor, +) : ViewModel() { + + /** On-device users. */ + val users: Flow<List<UserViewModel>> = + userInteractor.users.map { models -> models.map { user -> toViewModel(user) } } + + /** The maximum number of columns that the user selection grid should use. */ + val maximumUserColumns: Flow<Int> = + users.map { LegacyUserUiHelper.getMaxUserSwitcherItemColumns(it.size) } + + /** Whether the button to open the user action menu is visible. */ + val isOpenMenuButtonVisible: Flow<Boolean> = userInteractor.actions.map { it.isNotEmpty() } + + private val _isMenuVisible = MutableStateFlow(false) + /** + * Whether the user action menu should be shown. Once the action menu is dismissed/closed, the + * consumer must invoke [onMenuClosed]. + */ + val isMenuVisible: Flow<Boolean> = _isMenuVisible + /** The user action menu. */ + val menu: Flow<List<UserActionViewModel>> = + userInteractor.actions.map { actions -> actions.map { action -> toViewModel(action) } } + + private val hasCancelButtonBeenClicked = MutableStateFlow(false) + + /** + * Whether the observer should finish the experience. Once consumed, [onFinished] must be called + * by the consumer. + */ + val isFinishRequested: Flow<Boolean> = createFinishRequestedFlow() + + /** Notifies that the user has clicked the cancel button. */ + fun onCancelButtonClicked() { + hasCancelButtonBeenClicked.value = true + } + + /** + * Notifies that the user experience is finished. + * + * Call this after consuming [isFinishRequested] with a `true` value in order to mark it as + * consumed such that the next consumer doesn't immediately finish itself. + */ + fun onFinished() { + hasCancelButtonBeenClicked.value = false + } + + /** Notifies that the user has clicked the "open menu" button. */ + fun onOpenMenuButtonClicked() { + _isMenuVisible.value = true + } + + /** + * Notifies that the user has dismissed or closed the user action menu. + * + * Call this after consuming [isMenuVisible] with a `true` value in order to reset it to `false` + * such that the next consumer doesn't immediately show the menu again. + */ + fun onMenuClosed() { + _isMenuVisible.value = false + } + + private fun createFinishRequestedFlow(): Flow<Boolean> { + var mostRecentSelectedUserId: Int? = null + var mostRecentIsInteractive: Boolean? = null + + return combine( + // When the user is switched, we should finish. + userInteractor.selectedUser + .map { it.id } + .map { + val selectedUserChanged = + mostRecentSelectedUserId != null && mostRecentSelectedUserId != it + mostRecentSelectedUserId = it + selectedUserChanged + }, + // When the screen turns off, we should finish. + powerInteractor.isInteractive.map { + val screenTurnedOff = mostRecentIsInteractive == true && !it + mostRecentIsInteractive = it + screenTurnedOff + }, + // When the cancel button is clicked, we should finish. + hasCancelButtonBeenClicked, + ) { selectedUserChanged, screenTurnedOff, cancelButtonClicked -> + selectedUserChanged || screenTurnedOff || cancelButtonClicked + } + } + + private fun toViewModel( + model: UserModel, + ): UserViewModel { + return UserViewModel( + viewKey = model.id, + name = model.name, + image = CircularDrawable(model.image), + isSelectionMarkerVisible = model.isSelected, + alpha = + if (model.isSelectable) { + LegacyUserUiHelper.USER_SWITCHER_USER_VIEW_SELECTABLE_ALPHA + } else { + LegacyUserUiHelper.USER_SWITCHER_USER_VIEW_NOT_SELECTABLE_ALPHA + }, + onClicked = createOnSelectedCallback(model), + ) + } + + private fun toViewModel( + model: UserActionModel, + ): UserActionViewModel { + return UserActionViewModel( + viewKey = model.ordinal.toLong(), + iconResourceId = + if (model == UserActionModel.NAVIGATE_TO_USER_MANAGEMENT) { + R.drawable.ic_manage_users + } else { + LegacyUserUiHelper.getUserSwitcherActionIconResourceId( + isAddSupervisedUser = model == UserActionModel.ADD_SUPERVISED_USER, + isAddUser = model == UserActionModel.ADD_USER, + isGuest = model == UserActionModel.ENTER_GUEST_MODE, + ) + }, + textResourceId = + if (model == UserActionModel.NAVIGATE_TO_USER_MANAGEMENT) { + R.string.manage_users + } else { + LegacyUserUiHelper.getUserSwitcherActionTextResourceId( + isGuest = model == UserActionModel.ENTER_GUEST_MODE, + isGuestUserAutoCreated = userInteractor.isGuestUserAutoCreated, + isGuestUserResetting = userInteractor.isGuestUserResetting, + isAddSupervisedUser = model == UserActionModel.ADD_SUPERVISED_USER, + isAddUser = model == UserActionModel.ADD_USER, + ) + }, + onClicked = { userInteractor.executeAction(action = model) }, + ) + } + + private fun createOnSelectedCallback(model: UserModel): (() -> Unit)? { + return if (!model.isSelectable) { + null + } else { + { userInteractor.selectUser(model.id) } + } + } + + class Factory + @Inject + constructor( + private val userInteractor: UserInteractor, + private val powerInteractor: PowerInteractor, + ) : ViewModelProvider.Factory { + override fun <T : ViewModel> create(modelClass: Class<T>): T { + @Suppress("UNCHECKED_CAST") + return UserSwitcherViewModel( + userInteractor = userInteractor, + powerInteractor = powerInteractor, + ) + as T + } + } +} diff --git a/packages/SystemUI/src/com/android/systemui/user/ui/viewmodel/UserViewModel.kt b/packages/SystemUI/src/com/android/systemui/user/ui/viewmodel/UserViewModel.kt new file mode 100644 index 000000000000..d57bba0fa86a --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/user/ui/viewmodel/UserViewModel.kt @@ -0,0 +1,36 @@ +/* + * 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.user.ui.viewmodel + +import android.graphics.drawable.Drawable +import com.android.systemui.common.shared.model.Text + +/** Models UI state for representing a single user. */ +data class UserViewModel( + /** + * Key to use with the view or compose system to keep track of the view/composable across + * changes to the collection of [UserViewModel] instances. + */ + val viewKey: Int, + val name: Text, + val image: Drawable, + /** Whether a marker should be shown to highlight that this user is the selected one. */ + val isSelectionMarkerVisible: Boolean, + val alpha: Float, + val onClicked: (() -> Unit)?, +) diff --git a/packages/SystemUI/src/com/android/systemui/util/kotlin/Flow.kt b/packages/SystemUI/src/com/android/systemui/util/kotlin/Flow.kt index 7baebf4ef600..f71d596ff835 100644 --- a/packages/SystemUI/src/com/android/systemui/util/kotlin/Flow.kt +++ b/packages/SystemUI/src/com/android/systemui/util/kotlin/Flow.kt @@ -16,11 +16,15 @@ package com.android.systemui.util.kotlin +import java.util.concurrent.atomic.AtomicReference +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.distinctUntilChanged -import kotlinx.coroutines.flow.drop +import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.onStart -import kotlinx.coroutines.flow.zip +import kotlinx.coroutines.launch /** * Returns a new [Flow] that combines the two most recent emissions from [this] using [transform]. @@ -29,15 +33,16 @@ import kotlinx.coroutines.flow.zip * * Useful for code that needs to compare the current value to the previous value. */ -fun <T, R> Flow<T>.pairwiseBy(transform: suspend (old: T, new: T) -> R): Flow<R> { - // same as current flow, but with the very first event skipped - val nextEvents = drop(1) - // zip current flow and nextEvents; transform will receive a pair of old and new value. This - // works because zip will suppress emissions until both flows have emitted something; since in - // this case both flows are emitting at the same rate, but the current flow just has one extra - // thing emitted at the start, the effect is that zip will cache the most recent value while - // waiting for the next emission from nextEvents. - return zip(nextEvents, transform) +fun <T, R> Flow<T>.pairwiseBy(transform: suspend (old: T, new: T) -> R): Flow<R> = flow { + val noVal = Any() + var previousValue: Any? = noVal + collect { newVal -> + if (previousValue != noVal) { + @Suppress("UNCHECKED_CAST") + emit(transform(previousValue as T, newVal)) + } + previousValue = newVal + } } /** @@ -74,10 +79,19 @@ data class WithPrev<T>(val previousValue: T, val newValue: T) /** * Returns a new [Flow] that combines the [Set] changes between each emission from [this] using * [transform]. + * + * If [emitFirstEvent] is `true`, then the first [Set] emitted from the upstream [Flow] will cause + * a change event to be emitted that contains no removals, and all elements from that first [Set] + * as additions. + * + * If [emitFirstEvent] is `false`, then the first emission is ignored and no changes are emitted + * until a second [Set] has been emitted from the upstream [Flow]. */ fun <T, R> Flow<Set<T>>.setChangesBy( transform: suspend (removed: Set<T>, added: Set<T>) -> R, -): Flow<R> = onStart { emit(emptySet()) }.distinctUntilChanged() + emitFirstEvent: Boolean = true, +): Flow<R> = (if (emitFirstEvent) onStart { emit(emptySet()) } else this) + .distinctUntilChanged() .pairwiseBy { old: Set<T>, new: Set<T> -> // If an element was present in the old set, but not the new one, then it was removed val removed = old - new @@ -86,8 +100,18 @@ fun <T, R> Flow<Set<T>>.setChangesBy( transform(removed, added) } -/** Returns a new [Flow] that produces the [Set] changes between each emission from [this]. */ -fun <T> Flow<Set<T>>.setChanges(): Flow<SetChanges<T>> = setChangesBy(::SetChanges) +/** + * Returns a new [Flow] that produces the [Set] changes between each emission from [this]. + * + * If [emitFirstEvent] is `true`, then the first [Set] emitted from the upstream [Flow] will cause + * a change event to be emitted that contains no removals, and all elements from that first [Set] + * as additions. + * + * If [emitFirstEvent] is `false`, then the first emission is ignored and no changes are emitted + * until a second [Set] has been emitted from the upstream [Flow]. + */ +fun <T> Flow<Set<T>>.setChanges(emitFirstEvent: Boolean = true): Flow<SetChanges<T>> = + setChangesBy(::SetChanges, emitFirstEvent) /** Contains the difference in elements between two [Set]s. */ data class SetChanges<T>( @@ -96,3 +120,35 @@ data class SetChanges<T>( /** Elements that are present in the second [Set] but not in the first. */ val added: Set<T>, ) + +/** + * Returns a new [Flow] that emits at the same rate as [this], but combines the emitted value with + * the most recent emission from [other] using [transform]. + * + * Note that the returned Flow will not emit anything until [other] has emitted at least one value. + */ +fun <A, B, C> Flow<A>.sample(other: Flow<B>, transform: suspend (A, B) -> C): Flow<C> = flow { + coroutineScope { + val noVal = Any() + val sampledRef = AtomicReference(noVal) + val job = launch(Dispatchers.Unconfined) { + other.collect { sampledRef.set(it) } + } + collect { + val sampled = sampledRef.get() + if (sampled != noVal) { + @Suppress("UNCHECKED_CAST") + emit(transform(it, sampled as B)) + } + } + job.cancel() + } +} + +/** + * Returns a new [Flow] that emits at the same rate as [this], but emits the most recently emitted + * value from [other] instead. + * + * Note that the returned Flow will not emit anything until [other] has emitted at least one value. + */ +fun <A> Flow<*>.sample(other: Flow<A>): Flow<A> = sample(other) { _, a -> a } diff --git a/packages/SystemUI/src/com/android/systemui/util/kotlin/Suspend.kt b/packages/SystemUI/src/com/android/systemui/util/kotlin/Suspend.kt new file mode 100644 index 000000000000..2e551f1e1bee --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/util/kotlin/Suspend.kt @@ -0,0 +1,35 @@ +/* + * 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.util.kotlin + +import kotlinx.coroutines.CompletableDeferred +import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.launch + +/** + * Runs the given [blocks] in parallel, returning the result of the first one to complete, and + * cancelling all others. + */ +suspend fun <R> race(vararg blocks: suspend () -> R): R = coroutineScope { + val completion = CompletableDeferred<R>() + val raceJob = launch { + for (block in blocks) { + launch { completion.complete(block()) } + } + } + completion.await().also { raceJob.cancel() } +} diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumePanelDialog.java b/packages/SystemUI/src/com/android/systemui/volume/VolumePanelDialog.java index 2c74fb911688..87a167baf9bf 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumePanelDialog.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumePanelDialog.java @@ -52,6 +52,7 @@ import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.settingslib.bluetooth.LocalBluetoothProfileManager; import com.android.settingslib.media.MediaOutputConstants; import com.android.systemui.R; +import com.android.systemui.plugins.ActivityStarter; import com.android.systemui.statusbar.phone.SystemUIDialog; import java.util.ArrayList; @@ -69,6 +70,7 @@ public class VolumePanelDialog extends SystemUIDialog implements LifecycleOwner private static final int DURATION_SLICE_BINDING_TIMEOUT_MS = 200; private static final int DEFAULT_SLICE_SIZE = 4; + private final ActivityStarter mActivityStarter; private RecyclerView mVolumePanelSlices; private VolumePanelSlicesAdapter mVolumePanelSlicesAdapter; private final LifecycleRegistry mLifecycleRegistry; @@ -78,8 +80,10 @@ public class VolumePanelDialog extends SystemUIDialog implements LifecycleOwner private boolean mSlicesReadyToLoad; private LocalBluetoothProfileManager mProfileManager; - public VolumePanelDialog(Context context, boolean aboveStatusBar) { + public VolumePanelDialog(Context context, + ActivityStarter activityStarter, boolean aboveStatusBar) { super(context); + mActivityStarter = activityStarter; mLifecycleRegistry = new LifecycleRegistry(this); if (!aboveStatusBar) { getWindow().setType(WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY); @@ -100,9 +104,11 @@ public class VolumePanelDialog extends SystemUIDialog implements LifecycleOwner doneButton.setOnClickListener(v -> dismiss()); Button settingsButton = dialogView.findViewById(R.id.settings_button); settingsButton.setOnClickListener(v -> { - getContext().startActivity(new Intent(Settings.ACTION_SOUND_SETTINGS).addFlags( - Intent.FLAG_ACTIVITY_NEW_TASK)); dismiss(); + + Intent intent = new Intent(Settings.ACTION_SOUND_SETTINGS); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + mActivityStarter.startActivity(intent, /* dismissShade= */ true); }); LocalBluetoothManager localBluetoothManager = LocalBluetoothManager.getInstance( diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumePanelFactory.kt b/packages/SystemUI/src/com/android/systemui/volume/VolumePanelFactory.kt index c2fafbf9f55b..0debe0e4cd80 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumePanelFactory.kt +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumePanelFactory.kt @@ -21,6 +21,7 @@ import android.util.Log import android.view.View import com.android.systemui.animation.DialogLaunchAnimator import com.android.systemui.dagger.SysUISingleton +import com.android.systemui.plugins.ActivityStarter import javax.inject.Inject private const val TAG = "VolumePanelFactory" @@ -33,6 +34,7 @@ private val DEBUG = Log.isLoggable(TAG, Log.DEBUG) @SysUISingleton class VolumePanelFactory @Inject constructor( private val context: Context, + private val activityStarter: ActivityStarter, private val dialogLaunchAnimator: DialogLaunchAnimator ) { companion object { @@ -45,7 +47,7 @@ class VolumePanelFactory @Inject constructor( return } - val dialog = VolumePanelDialog(context, aboveStatusBar) + val dialog = VolumePanelDialog(context, activityStarter, aboveStatusBar) volumePanelDialog = dialog // Show the dialog. diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java index 8ff90f780c99..2878ad90835b 100644 --- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java +++ b/packages/SystemUI/src/com/android/systemui/wallpapers/ImageWallpaper.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui; +package com.android.systemui.wallpapers; import android.app.WallpaperColors; import android.graphics.Bitmap; @@ -37,8 +37,8 @@ import android.view.WindowManager; import androidx.annotation.NonNull; import com.android.internal.annotations.VisibleForTesting; -import com.android.systemui.glwallpaper.EglHelper; -import com.android.systemui.glwallpaper.ImageWallpaperRenderer; +import com.android.systemui.wallpapers.gl.EglHelper; +import com.android.systemui.wallpapers.gl.ImageWallpaperRenderer; import java.io.FileDescriptor; import java.io.PrintWriter; diff --git a/packages/SystemUI/src/com/android/systemui/wallpapers/OWNERS b/packages/SystemUI/src/com/android/systemui/wallpapers/OWNERS new file mode 100644 index 000000000000..731c7984b9ea --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/wallpapers/OWNERS @@ -0,0 +1,6 @@ +set noparent + +cinek@google.com +dupin@google.com +pomini@google.com +santie@google.com diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/EglHelper.java b/packages/SystemUI/src/com/android/systemui/wallpapers/gl/EglHelper.java index 11e215d0d358..f9ddce8e3b2e 100644 --- a/packages/SystemUI/src/com/android/systemui/glwallpaper/EglHelper.java +++ b/packages/SystemUI/src/com/android/systemui/wallpapers/gl/EglHelper.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui.glwallpaper; +package com.android.systemui.wallpapers.gl; import static android.opengl.EGL14.EGL_ALPHA_SIZE; import static android.opengl.EGL14.EGL_BLUE_SIZE; diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/GLWallpaperRenderer.java b/packages/SystemUI/src/com/android/systemui/wallpapers/gl/GLWallpaperRenderer.java index 61524900b89b..692ced08f613 100644 --- a/packages/SystemUI/src/com/android/systemui/glwallpaper/GLWallpaperRenderer.java +++ b/packages/SystemUI/src/com/android/systemui/wallpapers/gl/GLWallpaperRenderer.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui.glwallpaper; +package com.android.systemui.wallpapers.gl; import android.util.Size; diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLProgram.java b/packages/SystemUI/src/com/android/systemui/wallpapers/gl/ImageGLProgram.java index d03b00bcfc85..d34eca4831db 100644 --- a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLProgram.java +++ b/packages/SystemUI/src/com/android/systemui/wallpapers/gl/ImageGLProgram.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui.glwallpaper; +package com.android.systemui.wallpapers.gl; import static android.opengl.GLES20.GL_FRAGMENT_SHADER; import static android.opengl.GLES20.GL_VERTEX_SHADER; diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLWallpaper.java b/packages/SystemUI/src/com/android/systemui/wallpapers/gl/ImageGLWallpaper.java index 1a53c28c0fc5..f1659b9a8723 100644 --- a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageGLWallpaper.java +++ b/packages/SystemUI/src/com/android/systemui/wallpapers/gl/ImageGLWallpaper.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui.glwallpaper; +package com.android.systemui.wallpapers.gl; import static android.opengl.GLES20.GL_FLOAT; import static android.opengl.GLES20.GL_LINEAR; diff --git a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java b/packages/SystemUI/src/com/android/systemui/wallpapers/gl/ImageWallpaperRenderer.java index 7c0b93b7eebc..e393786e29d9 100644 --- a/packages/SystemUI/src/com/android/systemui/glwallpaper/ImageWallpaperRenderer.java +++ b/packages/SystemUI/src/com/android/systemui/wallpapers/gl/ImageWallpaperRenderer.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui.glwallpaper; +package com.android.systemui.wallpapers.gl; import static android.opengl.GLES20.GL_COLOR_BUFFER_BIT; import static android.opengl.GLES20.glClear; diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java b/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java index 8c41374fd058..4e7751464564 100644 --- a/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java +++ b/packages/SystemUI/src/com/android/systemui/wmshell/BubblesManager.java @@ -311,18 +311,6 @@ public class BubblesManager { } @Override - public void notifyMaybeCancelSummary(String key) { - sysuiMainExecutor.execute(() -> { - final NotificationEntry entry = mCommonNotifCollection.getEntry(key); - if (entry != null) { - for (NotifCallback cb : mCallbacks) { - cb.maybeCancelSummary(entry); - } - } - }); - } - - @Override public void updateNotificationBubbleButton(String key) { sysuiMainExecutor.execute(() -> { final NotificationEntry entry = mCommonNotifCollection.getEntry(key); @@ -646,15 +634,5 @@ public class BubblesManager { * filtered from the shade. */ void invalidateNotifications(@NonNull String reason); - - /** - * Called on a bubbled entry that has been removed when there are no longer - * bubbled entries in its group. - * - * Checks whether its group has any other (non-bubbled) children. If it doesn't, - * removes all remnants of the group's summary from the notification pipeline. - * TODO: (b/145659174) Only old pipeline needs this - delete post-migration. - */ - void maybeCancelSummary(@NonNull NotificationEntry entry); } } diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardMessageAreaTest.java b/packages/SystemUI/tests/src/com/android/keyguard/AuthKeyguardMessageAreaTest.java index 013c298d69d7..0a9c745525c2 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardMessageAreaTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/AuthKeyguardMessageAreaTest.java @@ -33,14 +33,14 @@ import org.mockito.MockitoAnnotations; @SmallTest @RunWith(AndroidTestingRunner.class) @RunWithLooper -public class KeyguardMessageAreaTest extends SysuiTestCase { +public class AuthKeyguardMessageAreaTest extends SysuiTestCase { private KeyguardMessageArea mKeyguardMessageArea; @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); - mKeyguardMessageArea = new KeyguardMessageArea(mContext, null); - mKeyguardMessageArea.setBouncerShowing(true); + mKeyguardMessageArea = new AuthKeyguardMessageArea(mContext, null); + mKeyguardMessageArea.setIsVisible(true); } @Test @@ -53,7 +53,7 @@ public class KeyguardMessageAreaTest extends SysuiTestCase { @Test public void testHiddenWhenBouncerHidden() { - mKeyguardMessageArea.setBouncerShowing(false); + mKeyguardMessageArea.setIsVisible(false); mKeyguardMessageArea.setVisibility(View.INVISIBLE); mKeyguardMessageArea.setMessage("oobleck"); assertThat(mKeyguardMessageArea.getVisibility()).isEqualTo(View.INVISIBLE); diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardAbsKeyInputViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardAbsKeyInputViewControllerTest.java index 90f7fda69663..8bbaf3dff1e5 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardAbsKeyInputViewControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardAbsKeyInputViewControllerTest.java @@ -56,7 +56,7 @@ public class KeyguardAbsKeyInputViewControllerTest extends SysuiTestCase { @Mock private PasswordTextView mPasswordEntry; @Mock - private KeyguardMessageArea mKeyguardMessageArea; + private BouncerKeyguardMessageArea mKeyguardMessageArea; @Mock private KeyguardUpdateMonitor mKeyguardUpdateMonitor; @Mock @@ -85,7 +85,7 @@ public class KeyguardAbsKeyInputViewControllerTest extends SysuiTestCase { when(mAbsKeyInputView.getPasswordTextViewId()).thenReturn(1); when(mAbsKeyInputView.findViewById(1)).thenReturn(mPasswordEntry); when(mAbsKeyInputView.isAttachedToWindow()).thenReturn(true); - when(mAbsKeyInputView.findViewById(R.id.keyguard_message_area)) + when(mAbsKeyInputView.requireViewById(R.id.bouncer_message_area)) .thenReturn(mKeyguardMessageArea); mKeyguardAbsKeyInputViewController = new KeyguardAbsKeyInputViewController(mAbsKeyInputView, mKeyguardUpdateMonitor, mSecurityMode, mLockPatternUtils, mKeyguardSecurityCallback, diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt index 0bf038d45af0..2714cf427e19 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt @@ -90,6 +90,8 @@ private fun faceModel(user: Int) = KeyguardFaceListenModel( onlyFaceEnrolled = false, faceAuthenticated = false, faceDisabled = false, + faceLockedOut = false, + fpLockedOut = false, goingToSleep = false, keyguardAwakeExcludingBouncerShowing = false, keyguardGoingAway = false, @@ -99,5 +101,5 @@ private fun faceModel(user: Int) = KeyguardFaceListenModel( scanningAllowedByStrongAuth = false, secureCameraLaunched = false, switchingUser = false, - udfpsBouncerShowing = false + udfpsBouncerShowing = false, ) diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardMessageAreaControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardMessageAreaControllerTest.java index 8293cc21f3d1..69524e5a4537 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardMessageAreaControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardMessageAreaControllerTest.java @@ -89,8 +89,8 @@ public class KeyguardMessageAreaControllerTest extends SysuiTestCase { @Test public void testSetBouncerVisible() { - mMessageAreaController.setBouncerShowing(true); - verify(mKeyguardMessageArea).setBouncerShowing(true); + mMessageAreaController.setIsVisible(true); + verify(mKeyguardMessageArea).setIsVisible(true); } @Test diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt index ec856031c23c..b89dbd98968a 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPasswordViewControllerTest.kt @@ -64,9 +64,10 @@ class KeyguardPasswordViewControllerTest : SysuiTestCase() { @Mock lateinit var keyguardViewController: KeyguardViewController @Mock - private lateinit var mKeyguardMessageArea: KeyguardMessageArea + private lateinit var mKeyguardMessageArea: BouncerKeyguardMessageArea @Mock - private lateinit var mKeyguardMessageAreaController: KeyguardMessageAreaController + private lateinit var mKeyguardMessageAreaController: + KeyguardMessageAreaController<BouncerKeyguardMessageArea> private lateinit var keyguardPasswordViewController: KeyguardPasswordViewController @@ -74,7 +75,8 @@ class KeyguardPasswordViewControllerTest : SysuiTestCase() { fun setup() { MockitoAnnotations.initMocks(this) Mockito.`when`( - keyguardPasswordView.findViewById<KeyguardMessageArea>(R.id.keyguard_message_area) + keyguardPasswordView + .requireViewById<BouncerKeyguardMessageArea>(R.id.bouncer_message_area) ).thenReturn(mKeyguardMessageArea) Mockito.`when`(messageAreaControllerFactory.create(mKeyguardMessageArea)) .thenReturn(mKeyguardMessageAreaController) diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt index 616a1056d161..3262a77b7711 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPatternViewControllerTest.kt @@ -66,10 +66,11 @@ class KeyguardPatternViewControllerTest : SysuiTestCase() { var mKeyguardMessageAreaControllerFactory: KeyguardMessageAreaController.Factory @Mock - private lateinit var mKeyguardMessageArea: KeyguardMessageArea + private lateinit var mKeyguardMessageArea: BouncerKeyguardMessageArea @Mock - private lateinit var mKeyguardMessageAreaController: KeyguardMessageAreaController + private lateinit var mKeyguardMessageAreaController: + KeyguardMessageAreaController<BouncerKeyguardMessageArea> @Mock private lateinit var mLockPatternView: LockPatternView @@ -83,7 +84,8 @@ class KeyguardPatternViewControllerTest : SysuiTestCase() { fun setup() { MockitoAnnotations.initMocks(this) `when`(mKeyguardPatternView.isAttachedToWindow).thenReturn(true) - `when`(mKeyguardPatternView.findViewById<KeyguardMessageArea>(R.id.keyguard_message_area)) + `when`(mKeyguardPatternView + .requireViewById<BouncerKeyguardMessageArea>(R.id.bouncer_message_area)) .thenReturn(mKeyguardMessageArea) `when`(mKeyguardPatternView.findViewById<LockPatternView>(R.id.lockPatternView)) .thenReturn(mLockPatternView) diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinBasedInputViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinBasedInputViewControllerTest.java index 7bc8e8a722f0..97d556b04aa4 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinBasedInputViewControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinBasedInputViewControllerTest.java @@ -51,7 +51,7 @@ public class KeyguardPinBasedInputViewControllerTest extends SysuiTestCase { @Mock private PasswordTextView mPasswordEntry; @Mock - private KeyguardMessageArea mKeyguardMessageArea; + private BouncerKeyguardMessageArea mKeyguardMessageArea; @Mock private KeyguardUpdateMonitor mKeyguardUpdateMonitor; @Mock @@ -90,7 +90,7 @@ public class KeyguardPinBasedInputViewControllerTest extends SysuiTestCase { when(mPinBasedInputView.findViewById(1)).thenReturn(mPasswordEntry); when(mPinBasedInputView.isAttachedToWindow()).thenReturn(true); when(mPinBasedInputView.getButtons()).thenReturn(mButtons); - when(mPinBasedInputView.findViewById(R.id.keyguard_message_area)) + when(mPinBasedInputView.requireViewById(R.id.bouncer_message_area)) .thenReturn(mKeyguardMessageArea); when(mPinBasedInputView.findViewById(R.id.delete_button)) .thenReturn(mDeleteButton); diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt new file mode 100644 index 000000000000..9e5bfe53ea05 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPinViewControllerTest.kt @@ -0,0 +1,103 @@ +/* + * 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.keyguard + +import android.testing.AndroidTestingRunner +import android.testing.TestableLooper +import android.view.View +import androidx.test.filters.SmallTest +import com.android.internal.util.LatencyTracker +import com.android.internal.widget.LockPatternUtils +import com.android.keyguard.KeyguardSecurityModel.SecurityMode +import com.android.systemui.R +import com.android.systemui.SysuiTestCase +import com.android.systemui.classifier.FalsingCollector +import com.android.systemui.classifier.FalsingCollectorFake +import com.android.systemui.statusbar.policy.DevicePostureController +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mock +import org.mockito.Mockito +import org.mockito.Mockito.any +import org.mockito.Mockito.verify +import org.mockito.MockitoAnnotations + +@SmallTest +@RunWith(AndroidTestingRunner::class) +@TestableLooper.RunWithLooper +class KeyguardPinViewControllerTest : SysuiTestCase() { + @Mock private lateinit var keyguardPinView: KeyguardPINView + + @Mock private lateinit var keyguardMessageArea: BouncerKeyguardMessageArea + + @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor + + @Mock private lateinit var securityMode: SecurityMode + + @Mock private lateinit var lockPatternUtils: LockPatternUtils + + @Mock private lateinit var mKeyguardSecurityCallback: KeyguardSecurityCallback + + @Mock + private lateinit var keyguardMessageAreaControllerFactory: KeyguardMessageAreaController.Factory + + @Mock + private lateinit var keyguardMessageAreaController: + KeyguardMessageAreaController<BouncerKeyguardMessageArea> + + @Mock private lateinit var mLatencyTracker: LatencyTracker + + @Mock private lateinit var liftToActivateListener: LiftToActivateListener + + @Mock private val mEmergencyButtonController: EmergencyButtonController? = null + private val falsingCollector: FalsingCollector = FalsingCollectorFake() + @Mock lateinit var postureController: DevicePostureController + + lateinit var pinViewController: KeyguardPinViewController + + @Before + fun setup() { + MockitoAnnotations.initMocks(this) + Mockito.`when`(keyguardPinView.requireViewById<View>(R.id.bouncer_message_area)) + .thenReturn(keyguardMessageArea) + Mockito.`when`( + keyguardMessageAreaControllerFactory.create(any(KeyguardMessageArea::class.java)) + ) + .thenReturn(keyguardMessageAreaController) + pinViewController = + KeyguardPinViewController( + keyguardPinView, + keyguardUpdateMonitor, + securityMode, + lockPatternUtils, + mKeyguardSecurityCallback, + keyguardMessageAreaControllerFactory, + mLatencyTracker, + liftToActivateListener, + mEmergencyButtonController, + falsingCollector, + postureController + ) + } + + @Test + fun startAppearAnimation() { + pinViewController.startAppearAnimation() + verify(keyguardMessageAreaController).setMessageIfEmpty(R.string.keyguard_enter_your_pin) + } +} diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java index d68e8bd36c40..c6ebaa8bb46c 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java @@ -41,6 +41,7 @@ import android.content.res.Resources; import android.hardware.biometrics.BiometricSourceType; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; +import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.WindowInsetsController; @@ -117,7 +118,7 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase { @Mock private KeyguardMessageAreaController mKeyguardMessageAreaController; @Mock - private KeyguardMessageArea mKeyguardMessageArea; + private BouncerKeyguardMessageArea mKeyguardMessageArea; @Mock private ConfigurationController mConfigurationController; @Mock @@ -163,9 +164,10 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase { when(mAdminSecondaryLockScreenControllerFactory.create(any(KeyguardSecurityCallback.class))) .thenReturn(mAdminSecondaryLockScreenController); when(mSecurityViewFlipper.getWindowInsetsController()).thenReturn(mWindowInsetsController); - mKeyguardPasswordView = spy(new KeyguardPasswordView(getContext())); + mKeyguardPasswordView = spy((KeyguardPasswordView) LayoutInflater.from(mContext).inflate( + R.layout.keyguard_password_view, null)); when(mKeyguardPasswordView.getRootView()).thenReturn(mSecurityViewFlipper); - when(mKeyguardPasswordView.findViewById(R.id.keyguard_message_area)) + when(mKeyguardPasswordView.requireViewById(R.id.bouncer_message_area)) .thenReturn(mKeyguardMessageArea); when(mKeyguardMessageAreaControllerFactory.create(any(KeyguardMessageArea.class))) .thenReturn(mKeyguardMessageAreaController); diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java index 763a63e102df..0275152c680e 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java @@ -17,7 +17,9 @@ package com.android.keyguard; import static android.app.StatusBarManager.SESSION_KEYGUARD; +import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_START; import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ERROR_LOCKOUT; +import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ERROR_LOCKOUT_PERMANENT; import static android.telephony.SubscriptionManager.DATA_ROAMING_DISABLE; import static android.telephony.SubscriptionManager.NAME_SOURCE_CARRIER_ID; @@ -30,6 +32,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.atLeastOnce; @@ -72,6 +75,7 @@ import android.os.Bundle; import android.os.CancellationSignal; import android.os.Handler; import android.os.IRemoteCallback; +import android.os.PowerManager; import android.os.RemoteException; import android.os.UserHandle; import android.os.UserManager; @@ -197,6 +201,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { private SessionTracker mSessionTracker; @Mock private UiEventLogger mUiEventLogger; + @Mock + private PowerManager mPowerManager; private final int mCurrentUserId = 100; private final UserInfo mCurrentUserInfo = new UserInfo(mCurrentUserId, "Test user", 0); @@ -745,8 +751,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { mTestableLooper.processAllMessages(); mKeyguardUpdateMonitor.onKeyguardVisibilityChanged(true); - mKeyguardUpdateMonitor.mFaceAuthenticationCallback - .onAuthenticationError(FaceManager.FACE_ERROR_LOCKOUT_PERMANENT, ""); + faceAuthLockedOut(); verify(mLockPatternUtils, never()).requireStrongAuth(anyInt(), anyInt()); } @@ -758,7 +763,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { mKeyguardUpdateMonitor.onKeyguardVisibilityChanged(true); mKeyguardUpdateMonitor.mFingerprintAuthenticationCallback - .onAuthenticationError(FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT, ""); + .onAuthenticationError(FINGERPRINT_ERROR_LOCKOUT_PERMANENT, ""); verify(mLockPatternUtils).requireStrongAuth(anyInt(), anyInt()); } @@ -769,10 +774,9 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { mTestableLooper.processAllMessages(); mKeyguardUpdateMonitor.onKeyguardVisibilityChanged(true); - mKeyguardUpdateMonitor.mFaceAuthenticationCallback - .onAuthenticationError(FaceManager.FACE_ERROR_LOCKOUT_PERMANENT, ""); + faceAuthLockedOut(); mKeyguardUpdateMonitor.mFingerprintAuthenticationCallback - .onAuthenticationError(FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT, ""); + .onAuthenticationError(FINGERPRINT_ERROR_LOCKOUT_PERMANENT, ""); verify(mLockPatternUtils).requireStrongAuth(anyInt(), anyInt()); } @@ -1211,7 +1215,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { public void testShouldListenForFace_whenFpIsLockedOut_returnsFalse() throws RemoteException { // Face auth should run when the following is true. keyguardNotGoingAway(); - bouncerFullyVisibleAndNotGoingToSleep(); + occludingAppRequestsFaceAuth(); currentUserIsPrimary(); strongAuthNotRequired(); biometricsEnabledForCurrentUser(); @@ -1219,6 +1223,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { biometricsNotDisabledThroughDevicePolicyManager(); userNotCurrentlySwitching(); mTestableLooper.processAllMessages(); + assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isTrue(); // Fingerprint is locked out. fingerprintErrorLockedOut(); @@ -1494,6 +1499,27 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { } @Test + public void testShouldListenForFace_whenFaceIsLockedOut_returnsFalse() + throws RemoteException { + // Preconditions for face auth to run + keyguardNotGoingAway(); + currentUserIsPrimary(); + currentUserDoesNotHaveTrust(); + biometricsNotDisabledThroughDevicePolicyManager(); + biometricsEnabledForCurrentUser(); + userNotCurrentlySwitching(); + mKeyguardUpdateMonitor.setUdfpsBouncerShowing(true); + mTestableLooper.processAllMessages(); + assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isTrue(); + + // Face is locked out. + faceAuthLockedOut(); + mTestableLooper.processAllMessages(); + + assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse(); + } + + @Test public void testBouncerVisibility_whenBothFingerprintAndFaceIsEnrolled_stopsFaceAuth() throws RemoteException { // Both fingerprint and face are enrolled by default @@ -1559,6 +1585,33 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { assertThat(mKeyguardUpdateMonitor.shouldListenForFingerprint(anyBoolean())).isEqualTo(true); } + @Test + public void testFingerAcquired_wakesUpPowerManager() { + mContext.getOrCreateTestableResources().addOverride( + com.android.internal.R.bool.kg_wake_on_acquire_start, true); + mSpiedContext = spy(mContext); + mKeyguardUpdateMonitor = new TestableKeyguardUpdateMonitor(mSpiedContext); + fingerprintAcquireStart(); + + verify(mPowerManager).wakeUp(anyLong(), anyInt(), anyString()); + } + + @Test + public void testFingerAcquired_doesNotWakeUpPowerManager() { + mContext.getOrCreateTestableResources().addOverride( + com.android.internal.R.bool.kg_wake_on_acquire_start, false); + mSpiedContext = spy(mContext); + mKeyguardUpdateMonitor = new TestableKeyguardUpdateMonitor(mSpiedContext); + fingerprintAcquireStart(); + + verify(mPowerManager, never()).wakeUp(anyLong(), anyInt(), anyString()); + } + + private void faceAuthLockedOut() { + mKeyguardUpdateMonitor.mFaceAuthenticationCallback + .onAuthenticationError(FaceManager.FACE_ERROR_LOCKOUT_PERMANENT, ""); + } + private void faceAuthEnabled() { // this ensures KeyguardUpdateMonitor updates the cached mIsFaceEnrolled flag using the // face manager mock wire-up in setup() @@ -1607,6 +1660,11 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { .onAuthenticationError(FINGERPRINT_ERROR_LOCKOUT, "Fingerprint locked out"); } + private void fingerprintAcquireStart() { + mKeyguardUpdateMonitor.mFingerprintAuthenticationCallback + .onAuthenticationAcquired(FINGERPRINT_ACQUIRED_START); + } + private void triggerSuccessfulFaceAuth() { mKeyguardUpdateMonitor.requestFaceAuth(true, FaceAuthApiRequestReason.UDFPS_POINTER_DOWN); verify(mFaceManager).authenticate(any(), @@ -1728,7 +1786,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { mStatusBarStateController, mLockPatternUtils, mAuthController, mTelephonyListenerManager, mInteractionJankMonitor, mLatencyTracker, mActiveUnlockConfig, - mKeyguardUpdateMonitorLogger, mUiEventLogger, () -> mSessionTracker); + mKeyguardUpdateMonitorLogger, mUiEventLogger, () -> mSessionTracker, + mPowerManager); setStrongAuthTracker(KeyguardUpdateMonitorTest.this.mStrongAuthTracker); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt index e2790e47fe06..a61cd23b60fc 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/animation/ActivityLaunchAnimatorTest.kt @@ -161,7 +161,18 @@ class ActivityLaunchAnimatorTest : SysuiTestCase() { runner.onAnimationStart(0, emptyArray(), emptyArray(), emptyArray(), iCallback) waitForIdleSync() - verify(controller).onLaunchAnimationCancelled() + verify(controller).onLaunchAnimationCancelled(false /* newKeyguardOccludedState */) + verify(controller, never()).onLaunchAnimationStart(anyBoolean()) + } + + @Test + fun passesOccludedStateToLaunchAnimationCancelled_ifTrue() { + val runner = activityLaunchAnimator.createRunner(controller) + runner.onAnimationCancelled(true /* isKeyguardOccluded */) + runner.onAnimationStart(0, emptyArray(), emptyArray(), emptyArray(), iCallback) + + waitForIdleSync() + verify(controller).onLaunchAnimationCancelled(true /* newKeyguardOccludedState */) verify(controller, never()).onLaunchAnimationStart(anyBoolean()) } @@ -253,7 +264,7 @@ private class TestLaunchAnimatorController(override var launchContainer: ViewGro assertOnMainThread() } - override fun onLaunchAnimationCancelled() { + override fun onLaunchAnimationCancelled(newKeyguardOccludedState: Boolean?) { assertOnMainThread() } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/FaceHelpMessageDeferralTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/FaceHelpMessageDeferralTest.kt new file mode 100644 index 000000000000..c9ccdb36da89 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/FaceHelpMessageDeferralTest.kt @@ -0,0 +1,188 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.biometrics + +import android.testing.AndroidTestingRunner +import androidx.test.filters.SmallTest +import com.android.keyguard.logging.BiometricMessageDeferralLogger +import com.android.systemui.SysuiTestCase +import com.android.systemui.dump.DumpManager +import org.junit.Assert.assertEquals +import org.junit.Assert.assertFalse +import org.junit.Assert.assertNull +import org.junit.Assert.assertTrue +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mock +import org.mockito.Mockito.verify +import org.mockito.MockitoAnnotations + +@SmallTest +@RunWith(AndroidTestingRunner::class) +class FaceHelpMessageDeferralTest : SysuiTestCase() { + val threshold = .75f + @Mock lateinit var logger: BiometricMessageDeferralLogger + @Mock lateinit var dumpManager: DumpManager + + @Before + fun setUp() { + MockitoAnnotations.initMocks(this) + } + + @Test + fun testProcessFrame_logs() { + val biometricMessageDeferral = createMsgDeferral(setOf(1)) + biometricMessageDeferral.processFrame(1) + verify(logger).logFrameProcessed(1, 1, "1") + } + + @Test + fun testUpdateMessage_logs() { + val biometricMessageDeferral = createMsgDeferral(setOf(1)) + biometricMessageDeferral.updateMessage(1, "hi") + verify(logger).logUpdateMessage(1, "hi") + } + + @Test + fun testReset_logs() { + val biometricMessageDeferral = createMsgDeferral(setOf(1)) + biometricMessageDeferral.reset() + verify(logger).reset() + } + + @Test + fun testProcessNoMessages_noDeferredMessage() { + val biometricMessageDeferral = createMsgDeferral(emptySet()) + + assertNull(biometricMessageDeferral.getDeferredMessage()) + } + + @Test + fun testProcessNonDeferredMessages_noDeferredMessage() { + val biometricMessageDeferral = createMsgDeferral(setOf(1, 2)) + + // WHEN there are no deferred messages processed + for (i in 0..3) { + biometricMessageDeferral.processFrame(4) + biometricMessageDeferral.updateMessage(4, "test") + } + + // THEN getDeferredMessage is null + assertNull(biometricMessageDeferral.getDeferredMessage()) + } + + @Test + fun testProcessMessagesWithDeferredMessage_deferredMessageWasNeverGivenAString() { + val biometricMessageDeferral = createMsgDeferral(setOf(1, 2)) + + biometricMessageDeferral.processFrame(1) + + assertNull(biometricMessageDeferral.getDeferredMessage()) + } + + @Test + fun testAllProcessedMessagesWereDeferred() { + val biometricMessageDeferral = createMsgDeferral(setOf(1)) + + // WHEN all the processed messages are a deferred message + for (i in 0..3) { + biometricMessageDeferral.processFrame(1) + biometricMessageDeferral.updateMessage(1, "test") + } + + // THEN deferredMessage will return the string associated with the deferred msgId + assertEquals("test", biometricMessageDeferral.getDeferredMessage()) + } + + @Test + fun testReturnsMostFrequentDeferredMessage() { + val biometricMessageDeferral = createMsgDeferral(setOf(1, 2)) + + // WHEN there's 80%of the messages are msgId=1 and 20% is msgId=2 + biometricMessageDeferral.processFrame(1) + biometricMessageDeferral.processFrame(1) + biometricMessageDeferral.processFrame(1) + biometricMessageDeferral.processFrame(1) + biometricMessageDeferral.updateMessage(1, "msgId-1") + + biometricMessageDeferral.processFrame(2) + biometricMessageDeferral.updateMessage(2, "msgId-2") + + // THEN the most frequent deferred message is that meets the threshold is returned + assertEquals("msgId-1", biometricMessageDeferral.getDeferredMessage()) + } + + @Test + fun testDeferredMessage_mustMeetThreshold() { + val biometricMessageDeferral = createMsgDeferral(setOf(1)) + + // WHEN more nonDeferredMessages are shown than the deferred message + val totalMessages = 10 + val nonDeferredMessagesCount = (totalMessages * threshold).toInt() + 1 + for (i in 0 until nonDeferredMessagesCount) { + biometricMessageDeferral.processFrame(4) + biometricMessageDeferral.updateMessage(4, "non-deferred-msg") + } + for (i in nonDeferredMessagesCount until totalMessages) { + biometricMessageDeferral.processFrame(1) + biometricMessageDeferral.updateMessage(1, "msgId-1") + } + + // THEN there's no deferred message because it didn't meet the threshold + assertNull(biometricMessageDeferral.getDeferredMessage()) + } + + @Test + fun testResetClearsOutCounts() { + val biometricMessageDeferral = createMsgDeferral(setOf(1, 2)) + + // GIVEN two msgId=1 events processed + biometricMessageDeferral.processFrame( + 1, + ) + biometricMessageDeferral.updateMessage(1, "msgId-1") + biometricMessageDeferral.processFrame(1) + biometricMessageDeferral.updateMessage(1, "msgId-1") + + // WHEN counts are reset and then a single deferred message is processed (msgId=2) + biometricMessageDeferral.reset() + biometricMessageDeferral.processFrame(2) + biometricMessageDeferral.updateMessage(2, "msgId-2") + + // THEN msgId-2 is the deferred message since the two msgId=1 events were reset + assertEquals("msgId-2", biometricMessageDeferral.getDeferredMessage()) + } + + @Test + fun testShouldDefer() { + // GIVEN should defer msgIds 1 and 2 + val biometricMessageDeferral = createMsgDeferral(setOf(1, 2)) + + // THEN shouldDefer returns true for ids 1 & 2 + assertTrue(biometricMessageDeferral.shouldDefer(1)) + assertTrue(biometricMessageDeferral.shouldDefer(2)) + + // THEN should defer returns false for ids 3 & 4 + assertFalse(biometricMessageDeferral.shouldDefer(3)) + assertFalse(biometricMessageDeferral.shouldDefer(4)) + } + + private fun createMsgDeferral(messagesToDefer: Set<Int>): BiometricMessageDeferral { + return BiometricMessageDeferral(messagesToDefer, threshold, logger, dumpManager) + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingCollectorImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingCollectorImplTest.java index acb5622c9790..3e9cf1e51b63 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingCollectorImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingCollectorImplTest.java @@ -229,7 +229,10 @@ public class FalsingCollectorImplTest extends SysuiTestCase { } @Test - public void testAvoidDozingNotPulsing() { + public void testGestureWhenDozing() { + // We check the FalsingManager for taps during the transition to AoD (dozing=true, + // pulsing=false), so the FalsingCollector needs to continue to analyze events that occur + // while the device is dozing. MotionEvent down = MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 0, 0); MotionEvent up = MotionEvent.obtain(0, 0, MotionEvent.ACTION_UP, 0, 0, 0); @@ -239,13 +242,13 @@ public class FalsingCollectorImplTest extends SysuiTestCase { mFalsingCollector.onTouchEvent(down); verify(mFalsingDataProvider, never()).onMotionEvent(any(MotionEvent.class)); - // Up event would normally flush the up event, but doesn't. + // Up event flushes mFalsingCollector.onTouchEvent(up); - verify(mFalsingDataProvider, never()).onMotionEvent(any(MotionEvent.class)); + verify(mFalsingDataProvider, times(2)).onMotionEvent(any(MotionEvent.class)); } @Test - public void testAvoidDozingButPulsing() { + public void testGestureWhenPulsing() { MotionEvent down = MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN, 0, 0, 0); MotionEvent up = MotionEvent.obtain(0, 0, MotionEvent.ACTION_UP, 0, 0, 0); diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java index 7f6b79b48939..4ebae98d1246 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStatusBarViewControllerTest.java @@ -310,7 +310,7 @@ public class DreamOverlayStatusBarViewControllerTest extends SysuiTestCase { @Test public void testOnViewDetachedRemovesViews() { mController.onViewDetached(); - verify(mView).removeAllStatusBarItemViews(); + verify(mView).removeAllExtraStatusBarItemViews(); } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardUnlockAnimationControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardUnlockAnimationControllerTest.kt index a4d223853b12..a78c902a1f30 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardUnlockAnimationControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardUnlockAnimationControllerTest.kt @@ -60,7 +60,18 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() { @Mock private lateinit var launcherUnlockAnimationController: ILauncherUnlockAnimationController.Stub - private lateinit var remoteAnimationTarget: RemoteAnimationTarget + private var surfaceControl1 = mock(SurfaceControl::class.java) + private var remoteTarget1 = RemoteAnimationTarget( + 0 /* taskId */, 0, surfaceControl1, false, Rect(), Rect(), 0, Point(), Rect(), Rect(), + mock(WindowConfiguration::class.java), false, surfaceControl1, Rect(), + mock(ActivityManager.RunningTaskInfo::class.java), false) + + private var surfaceControl2 = mock(SurfaceControl::class.java) + private var remoteTarget2 = RemoteAnimationTarget( + 1 /* taskId */, 0, surfaceControl2, false, Rect(), Rect(), 0, Point(), Rect(), Rect(), + mock(WindowConfiguration::class.java), false, surfaceControl2, Rect(), + mock(ActivityManager.RunningTaskInfo::class.java), false) + private lateinit var remoteAnimationTargets: Array<RemoteAnimationTarget> @Before fun setUp() { @@ -77,10 +88,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() { // All of these fields are final, so we can't mock them, but are needed so that the surface // appear amount setter doesn't short circuit. - remoteAnimationTarget = RemoteAnimationTarget( - 0, 0, null, false, Rect(), Rect(), 0, Point(), Rect(), Rect(), - mock(WindowConfiguration::class.java), false, mock(SurfaceControl::class.java), Rect(), - mock(ActivityManager.RunningTaskInfo::class.java), false) + remoteAnimationTargets = arrayOf(remoteTarget1) // Set the surface applier to our mock so that we can verify the arguments passed to it. // This applier does not have any side effects within the unlock animation controller, so @@ -99,7 +107,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() { `when`(biometricUnlockController.isWakeAndUnlock).thenReturn(true) keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation( - remoteAnimationTarget, + remoteAnimationTargets, 0 /* startTime */, false /* requestedShowSurfaceBehindKeyguard */ ) @@ -130,7 +138,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() { `when`(biometricUnlockController.isWakeAndUnlock).thenReturn(false) keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation( - remoteAnimationTarget, + remoteAnimationTargets, 0 /* startTime */, false /* requestedShowSurfaceBehindKeyguard */ ) @@ -154,7 +162,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() { `when`(keyguardStateController.isFlingingToDismissKeyguard).thenReturn(false) keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation( - remoteAnimationTarget, + remoteAnimationTargets, 0 /* startTime */, true /* requestedShowSurfaceBehindKeyguard */ ) @@ -176,7 +184,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() { `when`(keyguardStateController.isFlingingToDismissKeyguard).thenReturn(true) keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation( - remoteAnimationTarget, + remoteAnimationTargets, 0 /* startTime */, true /* requestedShowSurfaceBehindKeyguard */ ) @@ -196,7 +204,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() { @Test fun playCannedUnlockAnimation_ifDidNotRequestShowSurface() { keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation( - remoteAnimationTarget, + remoteAnimationTargets, 0 /* startTime */, false /* requestedShowSurfaceBehindKeyguard */ ) @@ -210,7 +218,7 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() { `when`(notificationShadeWindowController.isLaunchingActivity).thenReturn(true) keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation( - remoteAnimationTarget, + remoteAnimationTargets, 0 /* startTime */, true /* requestedShowSurfaceBehindKeyguard */ ) @@ -218,4 +226,53 @@ class KeyguardUnlockAnimationControllerTest : SysuiTestCase() { assertFalse(keyguardUnlockAnimationController.canPerformInWindowLauncherAnimations()) assertFalse(keyguardUnlockAnimationController.isPlayingCannedUnlockAnimation()) } -}
\ No newline at end of file + + @Test + fun playCannedUnlockAnimation_nullSmartspaceView_doesNotThrowExecption() { + keyguardUnlockAnimationController.lockscreenSmartspace = null + keyguardUnlockAnimationController.willUnlockWithInWindowLauncherAnimations = true + + keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation( + remoteAnimationTargets, + 0 /* startTime */, + false /* requestedShowSurfaceBehindKeyguard */ + ) + + assertTrue(keyguardUnlockAnimationController.isPlayingCannedUnlockAnimation()) + } + + /** + * If we are not wake and unlocking, we expect the unlock animation to play normally. + */ + @Test + fun surfaceAnimation_multipleTargets() { + keyguardUnlockAnimationController.notifyStartSurfaceBehindRemoteAnimation( + arrayOf(remoteTarget1, remoteTarget2), + 0 /* startTime */, + false /* requestedShowSurfaceBehindKeyguard */ + ) + + // Set appear to 50%, we'll just verify that we're not applying the identity matrix which + // means an animation is in progress. + keyguardUnlockAnimationController.setSurfaceBehindAppearAmount(0.5f) + + val captor = forClass(SyncRtSurfaceTransactionApplier.SurfaceParams::class.java) + verify(surfaceTransactionApplier, times(2)).scheduleApply(captor.capture()) + + val allParams = captor.allValues + + val remainingTargets = mutableListOf(surfaceControl1, surfaceControl2) + allParams.forEach { params -> + assertTrue(!params.matrix.isIdentity) + remainingTargets.remove(params.surface) + } + + // Make sure we called applyParams with each of the surface controls once. The order does + // not matter, so don't explicitly check for that. + assertTrue(remainingTargets.isEmpty()) + + // Since the animation is running, we should not have finished the remote animation. + verify(keyguardViewMediator, times(0)).onKeyguardExitRemoteAnimationFinished( + false /* cancelled */) + } +} 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 3aa22669bbf2..ba1e168bc316 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 @@ -19,6 +19,7 @@ package com.android.systemui.keyguard.data.repository import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.common.shared.model.Position +import com.android.systemui.doze.DozeHost import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.util.mockito.argumentCaptor @@ -40,6 +41,7 @@ import org.mockito.MockitoAnnotations class KeyguardRepositoryImplTest : SysuiTestCase() { @Mock private lateinit var statusBarStateController: StatusBarStateController + @Mock private lateinit var dozeHost: DozeHost @Mock private lateinit var keyguardStateController: KeyguardStateController private lateinit var underTest: KeyguardRepositoryImpl @@ -48,7 +50,12 @@ class KeyguardRepositoryImplTest : SysuiTestCase() { fun setUp() { MockitoAnnotations.initMocks(this) - underTest = KeyguardRepositoryImpl(statusBarStateController, keyguardStateController) + underTest = + KeyguardRepositoryImpl( + statusBarStateController, + keyguardStateController, + dozeHost, + ) } @Test @@ -129,8 +136,8 @@ class KeyguardRepositoryImplTest : SysuiTestCase() { var latest: Boolean? = null val job = underTest.isDozing.onEach { latest = it }.launchIn(this) - val captor = argumentCaptor<StatusBarStateController.StateListener>() - verify(statusBarStateController).addCallback(captor.capture()) + val captor = argumentCaptor<DozeHost.Callback>() + verify(dozeHost).addCallback(captor.capture()) captor.value.onDozingChanged(true) assertThat(latest).isTrue() @@ -139,7 +146,7 @@ class KeyguardRepositoryImplTest : SysuiTestCase() { assertThat(latest).isFalse() job.cancel() - verify(statusBarStateController).removeCallback(captor.value) + verify(dozeHost).removeCallback(captor.value) } @Test diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest.kt index 9acd21cc6398..9a91ea91f3a2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest.kt @@ -51,18 +51,19 @@ class HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest : SysuiTes @Parameters( name = "feature enabled = {0}, has favorites = {1}, has service infos = {2}, can show" + - " while locked = {3} - expected visible = {4}" + " while locked = {3}, visibility is AVAILABLE {4} - expected visible = {5}" ) @JvmStatic fun data() = - (0 until 16) + (0 until 32) .map { combination -> arrayOf( - /* isFeatureEnabled= */ combination and 0b1000 != 0, - /* hasFavorites= */ combination and 0b0100 != 0, - /* hasServiceInfos= */ combination and 0b0010 != 0, - /* canShowWhileLocked= */ combination and 0b0001 != 0, - /* isVisible= */ combination == 0b1111, + /* isFeatureEnabled= */ combination and 0b10000 != 0, + /* hasFavorites= */ combination and 0b01000 != 0, + /* hasServiceInfos= */ combination and 0b00100 != 0, + /* canShowWhileLocked= */ combination and 0b00010 != 0, + /* visibilityAvailable= */ combination and 0b00001 != 0, + /* isVisible= */ combination == 0b11111, ) } .toList() @@ -81,7 +82,8 @@ class HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest : SysuiTes @JvmField @Parameter(1) var hasFavorites: Boolean = false @JvmField @Parameter(2) var hasServiceInfos: Boolean = false @JvmField @Parameter(3) var canShowWhileLocked: Boolean = false - @JvmField @Parameter(4) var isVisible: Boolean = false + @JvmField @Parameter(4) var isVisibilityAvailable: Boolean = false + @JvmField @Parameter(5) var isVisibleExpected: Boolean = false @Before fun setUp() { @@ -93,6 +95,14 @@ class HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest : SysuiTes .thenReturn(Optional.of(controlsListingController)) whenever(component.canShowWhileLockedSetting) .thenReturn(MutableStateFlow(canShowWhileLocked)) + whenever(component.getVisibility()) + .thenReturn( + if (isVisibilityAvailable) { + ControlsComponent.Visibility.AVAILABLE + } else { + ControlsComponent.Visibility.UNAVAILABLE + } + ) underTest = HomeControlsKeyguardQuickAffordanceConfig( @@ -128,7 +138,7 @@ class HomeControlsKeyguardQuickAffordanceConfigParameterizedStateTest : SysuiTes assertThat(values.last()) .isInstanceOf( - if (isVisible) { + if (isVisibleExpected) { KeyguardQuickAffordanceConfig.State.Visible::class.java } else { KeyguardQuickAffordanceConfig.State.Hidden::class.java diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigTest.kt index 059487dfdbc8..dede4ec0210c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/quickaffordance/HomeControlsKeyguardQuickAffordanceConfigTest.kt @@ -69,6 +69,7 @@ class HomeControlsKeyguardQuickAffordanceConfigTest : SysuiTestCase() { val controlsController = mock<ControlsController>() whenever(component.getControlsController()).thenReturn(Optional.of(controlsController)) whenever(component.getControlsListingController()).thenReturn(Optional.empty()) + whenever(component.getVisibility()).thenReturn(ControlsComponent.Visibility.AVAILABLE) whenever(controlsController.getFavorites()).thenReturn(listOf(mock())) val values = mutableListOf<KeyguardQuickAffordanceConfig.State>() @@ -87,6 +88,7 @@ class HomeControlsKeyguardQuickAffordanceConfigTest : SysuiTestCase() { val controlsController = mock<ControlsController>() whenever(component.getControlsController()).thenReturn(Optional.of(controlsController)) whenever(component.getControlsListingController()).thenReturn(Optional.empty()) + whenever(component.getVisibility()).thenReturn(ControlsComponent.Visibility.AVAILABLE) whenever(controlsController.getFavorites()).thenReturn(listOf(mock())) val values = mutableListOf<KeyguardQuickAffordanceConfig.State>() diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/usecase/KeyguardQuickAffordanceInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/usecase/KeyguardQuickAffordanceInteractorTest.kt index d3fc29f1a0f1..19d841222a01 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/usecase/KeyguardQuickAffordanceInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/usecase/KeyguardQuickAffordanceInteractorTest.kt @@ -36,6 +36,7 @@ import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.test.runBlockingTest +import kotlinx.coroutines.yield import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -110,6 +111,10 @@ class KeyguardQuickAffordanceInteractorTest : SysuiTestCase() { .quickAffordance(KeyguardQuickAffordancePosition.BOTTOM_START) .onEach { latest = it } .launchIn(this) + // The interactor has an onStart { emit(Hidden) } to cover for upstream configs that don't + // produce an initial value. We yield to give the coroutine time to emit the first real + // value from our config. + yield() assertThat(latest).isInstanceOf(KeyguardQuickAffordanceModel.Visible::class.java) val visibleModel = latest as KeyguardQuickAffordanceModel.Visible @@ -136,6 +141,10 @@ class KeyguardQuickAffordanceInteractorTest : SysuiTestCase() { .quickAffordance(KeyguardQuickAffordancePosition.BOTTOM_END) .onEach { latest = it } .launchIn(this) + // The interactor has an onStart { emit(Hidden) } to cover for upstream configs that don't + // produce an initial value. We yield to give the coroutine time to emit the first real + // value from our config. + yield() assertThat(latest).isInstanceOf(KeyguardQuickAffordanceModel.Visible::class.java) val visibleModel = latest as KeyguardQuickAffordanceModel.Visible diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModelTest.kt index 14b85b8b5e56..c612091382db 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBottomAreaViewModelTest.kt @@ -224,7 +224,10 @@ class KeyguardBottomAreaViewModelTest : SysuiTestCase() { repository.setAnimateDozingTransitions(false) yield() - assertThat(values).isEqualTo(listOf(false, true, false)) + // Note the extra false value in the beginning. This is to cover for the initial value + // inserted by the quick affordance interactor which it does to cover for config + // implementations that don't emit an initial value. + assertThat(values).isEqualTo(listOf(false, false, true, false)) job.cancel() } @@ -372,6 +375,10 @@ class KeyguardBottomAreaViewModelTest : SysuiTestCase() { var latest: KeyguardQuickAffordanceViewModel? = null val job = underTest.startButton.onEach { latest = it }.launchIn(this) + // The interactor has an onStart { emit(Hidden) } to cover for upstream configs that don't + // produce an initial value. We yield to give the coroutine time to emit the first real + // value from our config. + yield() assertQuickAffordanceViewModel( viewModel = latest, diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt index 1bc197232da6..5a50a9f64487 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaCarouselControllerTest.kt @@ -30,6 +30,7 @@ import com.android.systemui.statusbar.notification.collection.provider.VisualSta import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.util.animation.TransitionLayout import com.android.systemui.util.concurrency.DelayableExecutor +import com.android.systemui.util.mockito.capture import com.android.systemui.util.mockito.eq import com.android.systemui.util.time.FakeSystemClock import javax.inject.Provider @@ -38,6 +39,8 @@ import junit.framework.Assert.assertTrue import org.junit.Before import org.junit.Test import org.junit.runner.RunWith +import org.mockito.ArgumentCaptor +import org.mockito.Captor import org.mockito.Mock import org.mockito.Mockito.verify import org.mockito.Mockito.verifyNoMoreInteractions @@ -71,6 +74,10 @@ class MediaCarouselControllerTest : SysuiTestCase() { @Mock lateinit var player: TransitionLayout @Mock lateinit var recommendationViewHolder: RecommendationViewHolder @Mock lateinit var recommendations: TransitionLayout + @Mock lateinit var mediaPlayer: MediaControlPanel + @Mock lateinit var mediaViewController: MediaViewController + @Mock lateinit var smartspaceMediaData: SmartspaceMediaData + @Captor lateinit var listener: ArgumentCaptor<MediaDataManager.Listener> private val clock = FakeSystemClock() private lateinit var mediaCarouselController: MediaCarouselController @@ -94,7 +101,10 @@ class MediaCarouselControllerTest : SysuiTestCase() { logger, debugLogger ) - + verify(mediaDataManager).addListener(capture(listener)) + whenever(mediaControlPanelFactory.get()).thenReturn(mediaPlayer) + whenever(mediaPlayer.mediaViewController).thenReturn(mediaViewController) + whenever(mediaDataManager.smartspaceMediaData).thenReturn(smartspaceMediaData) MediaPlayerData.clear() } @@ -305,4 +315,63 @@ class MediaCarouselControllerTest : SysuiTestCase() { verifyNoMoreInteractions(mediaViewHolder) verify(recommendationViewHolder.recommendations).bottom = 75 } + + fun testMediaLoaded_ScrollToActivePlayer() { + listener.value.onMediaDataLoaded("playing local", + null, + DATA.copy(active = true, isPlaying = true, + playbackLocation = MediaData.PLAYBACK_LOCAL, resumption = false) + ) + listener.value.onMediaDataLoaded("paused local", + null, + DATA.copy(active = true, isPlaying = false, + playbackLocation = MediaData.PLAYBACK_LOCAL, resumption = false)) + // adding a media recommendation card. + MediaPlayerData.addMediaRecommendation(SMARTSPACE_KEY, EMPTY_SMARTSPACE_MEDIA_DATA, panel, + false, clock) + mediaCarouselController.shouldScrollToActivePlayer = true + // switching between media players. + listener.value.onMediaDataLoaded("playing local", + "playing local", + DATA.copy(active = true, isPlaying = false, + playbackLocation = MediaData.PLAYBACK_LOCAL, resumption = true) + ) + listener.value.onMediaDataLoaded("paused local", + "paused local", + DATA.copy(active = true, isPlaying = true, + playbackLocation = MediaData.PLAYBACK_LOCAL, resumption = false)) + + assertEquals( + MediaPlayerData.getMediaPlayerIndex("paused local"), + mediaCarouselController.mediaCarouselScrollHandler.visibleMediaIndex + ) + } + + @Test + fun testMediaLoadedFromRecommendationCard_ScrollToActivePlayer() { + MediaPlayerData.addMediaRecommendation(SMARTSPACE_KEY, EMPTY_SMARTSPACE_MEDIA_DATA, panel, + false, clock) + listener.value.onMediaDataLoaded("playing local", + null, + DATA.copy(active = true, isPlaying = true, + playbackLocation = MediaData.PLAYBACK_LOCAL, resumption = false) + ) + + var playerIndex = MediaPlayerData.getMediaPlayerIndex("playing local") + assertEquals( + playerIndex, + mediaCarouselController.mediaCarouselScrollHandler.visibleMediaIndex + ) + assertEquals( playerIndex, 0) + + // Replaying the same media player one more time. + // And check that the card stays in its position. + listener.value.onMediaDataLoaded("playing local", + null, + DATA.copy(active = true, isPlaying = true, + playbackLocation = MediaData.PLAYBACK_LOCAL, resumption = false) + ) + playerIndex = MediaPlayerData.getMediaPlayerIndex("playing local") + assertEquals(playerIndex, 0) + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt index 18bfd04102b7..954b4386b71d 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt @@ -29,6 +29,7 @@ import com.android.systemui.SysuiTestCase import com.android.systemui.controls.controller.ControlsControllerImplTest.Companion.eq import com.android.systemui.dreams.DreamOverlayStateController import com.android.systemui.keyguard.WakefulnessLifecycle +import com.android.systemui.media.dream.MediaDreamComplication import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.shade.testing.FakeNotifPanelEvents import com.android.systemui.statusbar.StatusBarState @@ -38,6 +39,8 @@ import com.android.systemui.statusbar.policy.FakeConfigurationController import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.util.animation.UniqueObjectHostView import com.android.systemui.util.mockito.any +import com.android.systemui.util.mockito.mock +import com.android.systemui.util.mockito.nullable import com.android.systemui.util.settings.FakeSettings import com.android.systemui.utils.os.FakeHandler import com.google.common.truth.Truth.assertThat @@ -79,6 +82,9 @@ class MediaHierarchyManagerTest : SysuiTestCase() { private lateinit var wakefullnessObserver: ArgumentCaptor<(WakefulnessLifecycle.Observer)> @Captor private lateinit var statusBarCallback: ArgumentCaptor<(StatusBarStateController.StateListener)> + @Captor + private lateinit var dreamOverlayCallback: + ArgumentCaptor<(DreamOverlayStateController.Callback)> @JvmField @Rule val mockito = MockitoJUnit.rule() @@ -113,6 +119,7 @@ class MediaHierarchyManagerTest : SysuiTestCase() { fakeHandler,) verify(wakefulnessLifecycle).addObserver(wakefullnessObserver.capture()) verify(statusBarStateController).addCallback(statusBarCallback.capture()) + verify(dreamOverlayStateController).addCallback(dreamOverlayCallback.capture()) setupHost(lockHost, MediaHierarchyManager.LOCATION_LOCKSCREEN, LOCKSCREEN_TOP) setupHost(qsHost, MediaHierarchyManager.LOCATION_QS, QS_TOP) setupHost(qqsHost, MediaHierarchyManager.LOCATION_QQS, QQS_TOP) @@ -332,6 +339,27 @@ class MediaHierarchyManagerTest : SysuiTestCase() { assertThat(mediaHierarchyManager.isCurrentlyInGuidedTransformation()).isFalse() } + @Test + fun testDream() { + goToDream() + setMediaDreamComplicationEnabled(true) + verify(mediaCarouselController).onDesiredLocationChanged( + eq(MediaHierarchyManager.LOCATION_DREAM_OVERLAY), + nullable(), + eq(false), + anyLong(), + anyLong()) + clearInvocations(mediaCarouselController) + + setMediaDreamComplicationEnabled(false) + verify(mediaCarouselController).onDesiredLocationChanged( + eq(MediaHierarchyManager.LOCATION_QQS), + any(MediaHostState::class.java), + eq(false), + anyLong(), + anyLong()) + } + private fun enableSplitShade() { context.getOrCreateTestableResources().addOverride( R.bool.config_use_split_notification_shade, true @@ -343,6 +371,8 @@ class MediaHierarchyManagerTest : SysuiTestCase() { whenever(statusBarStateController.state).thenReturn(StatusBarState.KEYGUARD) settings.putInt(Settings.Secure.MEDIA_CONTROLS_LOCK_SCREEN, 1) statusBarCallback.value.onStatePreChange(StatusBarState.SHADE, StatusBarState.KEYGUARD) + whenever(dreamOverlayStateController.isOverlayActive).thenReturn(false) + dreamOverlayCallback.value.onStateChanged() clearInvocations(mediaCarouselController) } @@ -354,6 +384,17 @@ class MediaHierarchyManagerTest : SysuiTestCase() { ) } + private fun goToDream() { + whenever(dreamOverlayStateController.isOverlayActive).thenReturn(true) + dreamOverlayCallback.value.onStateChanged() + } + + private fun setMediaDreamComplicationEnabled(enabled: Boolean) { + val complications = if (enabled) listOf(mock<MediaDreamComplication>()) else emptyList() + whenever(dreamOverlayStateController.complications).thenReturn(complications) + dreamOverlayCallback.value.onComplicationsChanged() + } + private fun expandQS() { mediaHierarchyManager.qsExpansion = 1.0f } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dream/MediaDreamSentinelTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dream/MediaDreamSentinelTest.java index 2e864dc2cda8..0bfc0344b521 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/dream/MediaDreamSentinelTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/media/dream/MediaDreamSentinelTest.java @@ -72,13 +72,13 @@ public class MediaDreamSentinelTest extends SysuiTestCase { } @Test - public void testComplicationAddition() { + public void testOnMediaDataLoaded_complicationAddition() { final MediaDreamSentinel sentinel = new MediaDreamSentinel(mContext, mMediaDataManager, mDreamOverlayStateController, mMediaEntryComplication, mFeatureFlags); - sentinel.start(); final MediaDataManager.Listener listener = captureMediaDataListener(); + when(mMediaDataManager.hasActiveMedia()).thenReturn(false); listener.onMediaDataLoaded(mKey, mOldKey, mData, /* immediately= */ true, /* receivedSmartspaceCardLatency= */ 0, /* isSsReactived= */ false); @@ -90,6 +90,19 @@ public class MediaDreamSentinelTest extends SysuiTestCase { verify(mDreamOverlayStateController).addComplication(eq(mMediaEntryComplication)); verify(mDreamOverlayStateController, never()).addComplication( not(eq(mMediaEntryComplication))); + } + + @Test + public void testOnMediaDataRemoved_complicationRemoval() { + final MediaDreamSentinel sentinel = new MediaDreamSentinel(mContext, mMediaDataManager, + mDreamOverlayStateController, mMediaEntryComplication, mFeatureFlags); + sentinel.start(); + + final MediaDataManager.Listener listener = captureMediaDataListener(); + + when(mMediaDataManager.hasActiveMedia()).thenReturn(true); + listener.onMediaDataLoaded(mKey, mOldKey, mData, /* immediately= */true, + /* receivedSmartspaceCardLatency= */0, /* isSsReactived= */ false); listener.onMediaDataRemoved(mKey); verify(mDreamOverlayStateController, never()).removeComplication(any()); @@ -100,7 +113,30 @@ public class MediaDreamSentinelTest extends SysuiTestCase { } @Test - public void testMediaDreamSentinel_mediaComplicationDisabled_doNotAddComplication() { + public void testOnMediaDataLoaded_complicationRemoval() { + final MediaDreamSentinel sentinel = new MediaDreamSentinel(mContext, mMediaDataManager, + mDreamOverlayStateController, mMediaEntryComplication, mFeatureFlags); + sentinel.start(); + + final MediaDataManager.Listener listener = captureMediaDataListener(); + + when(mMediaDataManager.hasActiveMedia()).thenReturn(true); + listener.onMediaDataLoaded(mKey, mOldKey, mData, /* immediately= */true, + /* receivedSmartspaceCardLatency= */0, /* isSsReactived= */ false); + verify(mDreamOverlayStateController, never()).removeComplication(any()); + + listener.onMediaDataLoaded(mKey, mOldKey, mData, /* immediately= */true, + /* receivedSmartspaceCardLatency= */0, /* isSsReactived= */ false); + verify(mDreamOverlayStateController, never()).removeComplication(any()); + + when(mMediaDataManager.hasActiveMedia()).thenReturn(false); + listener.onMediaDataLoaded(mKey, mOldKey, mData, /* immediately= */true, + /* receivedSmartspaceCardLatency= */0, /* isSsReactived= */ false); + verify(mDreamOverlayStateController).removeComplication(eq(mMediaEntryComplication)); + } + + @Test + public void testOnMediaDataLoaded_mediaComplicationDisabled_doesNotAddComplication() { when(mFeatureFlags.isEnabled(MEDIA_DREAM_COMPLICATION)).thenReturn(false); final MediaDreamSentinel sentinel = new MediaDreamSentinel(mContext, mMediaDataManager, diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommonTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommonTest.kt deleted file mode 100644 index f1330682b0e1..000000000000 --- a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttChipControllerCommonTest.kt +++ /dev/null @@ -1,390 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.systemui.media.taptotransfer.common - -import android.content.Context -import android.content.pm.ApplicationInfo -import android.content.pm.PackageManager -import android.graphics.drawable.Drawable -import android.os.PowerManager -import android.view.View -import android.view.ViewGroup -import android.view.WindowManager -import android.view.accessibility.AccessibilityManager -import android.widget.ImageView -import androidx.test.filters.SmallTest -import com.android.systemui.R -import com.android.systemui.SysuiTestCase -import com.android.systemui.dagger.qualifiers.Main -import com.android.systemui.statusbar.policy.ConfigurationController -import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener -import com.android.systemui.util.concurrency.DelayableExecutor -import com.android.systemui.util.concurrency.FakeExecutor -import com.android.systemui.util.mockito.any -import com.android.systemui.util.mockito.argumentCaptor -import com.android.systemui.util.mockito.capture -import com.android.systemui.util.time.FakeSystemClock -import com.android.systemui.util.view.ViewUtil -import com.google.common.truth.Truth.assertThat -import org.junit.Before -import org.junit.Test -import org.mockito.ArgumentCaptor -import org.mockito.Mock -import org.mockito.Mockito.eq -import org.mockito.Mockito.never -import org.mockito.Mockito.reset -import org.mockito.Mockito.verify -import org.mockito.Mockito.`when` as whenever -import org.mockito.MockitoAnnotations - -@SmallTest -class MediaTttChipControllerCommonTest : SysuiTestCase() { - private lateinit var controllerCommon: TestControllerCommon - - private lateinit var fakeClock: FakeSystemClock - private lateinit var fakeExecutor: FakeExecutor - - private lateinit var appIconFromPackageName: Drawable - @Mock - private lateinit var packageManager: PackageManager - @Mock - private lateinit var applicationInfo: ApplicationInfo - @Mock - private lateinit var logger: MediaTttLogger - @Mock - private lateinit var accessibilityManager: AccessibilityManager - @Mock - private lateinit var configurationController: ConfigurationController - @Mock - private lateinit var windowManager: WindowManager - @Mock - private lateinit var viewUtil: ViewUtil - @Mock - private lateinit var powerManager: PowerManager - - @Before - fun setUp() { - MockitoAnnotations.initMocks(this) - - appIconFromPackageName = context.getDrawable(R.drawable.ic_cake)!! - whenever(packageManager.getApplicationIcon(PACKAGE_NAME)).thenReturn(appIconFromPackageName) - whenever(applicationInfo.loadLabel(packageManager)).thenReturn(APP_NAME) - whenever(packageManager.getApplicationInfo( - any(), any<PackageManager.ApplicationInfoFlags>() - )).thenThrow(PackageManager.NameNotFoundException()) - whenever(packageManager.getApplicationInfo( - eq(PACKAGE_NAME), any<PackageManager.ApplicationInfoFlags>() - )).thenReturn(applicationInfo) - context.setMockPackageManager(packageManager) - - whenever(accessibilityManager.getRecommendedTimeoutMillis(any(), any())) - .thenReturn(TIMEOUT_MS.toInt()) - - fakeClock = FakeSystemClock() - fakeExecutor = FakeExecutor(fakeClock) - - controllerCommon = TestControllerCommon( - context, - logger, - windowManager, - viewUtil, - fakeExecutor, - accessibilityManager, - configurationController, - powerManager, - ) - } - - @Test - fun displayChip_chipAdded() { - controllerCommon.displayChip(getState()) - - verify(windowManager).addView(any(), any()) - } - - @Test - fun displayChip_screenOff_screenWakes() { - whenever(powerManager.isScreenOn).thenReturn(false) - - controllerCommon.displayChip(getState()) - - verify(powerManager).wakeUp(any(), any(), any()) - } - - @Test - fun displayChip_screenAlreadyOn_screenNotWoken() { - whenever(powerManager.isScreenOn).thenReturn(true) - - controllerCommon.displayChip(getState()) - - verify(powerManager, never()).wakeUp(any(), any(), any()) - } - - @Test - fun displayChip_twice_chipNotAddedTwice() { - controllerCommon.displayChip(getState()) - reset(windowManager) - - controllerCommon.displayChip(getState()) - verify(windowManager, never()).addView(any(), any()) - } - - @Test - fun displayChip_chipDoesNotDisappearsBeforeTimeout() { - val state = getState() - controllerCommon.displayChip(state) - reset(windowManager) - - fakeClock.advanceTime(TIMEOUT_MS - 1) - - verify(windowManager, never()).removeView(any()) - } - - @Test - fun displayChip_chipDisappearsAfterTimeout() { - val state = getState() - controllerCommon.displayChip(state) - reset(windowManager) - - fakeClock.advanceTime(TIMEOUT_MS + 1) - - verify(windowManager).removeView(any()) - } - - @Test - fun displayChip_calledAgainBeforeTimeout_timeoutReset() { - // First, display the chip - val state = getState() - controllerCommon.displayChip(state) - - // After some time, re-display the chip - val waitTime = 1000L - fakeClock.advanceTime(waitTime) - controllerCommon.displayChip(getState()) - - // Wait until the timeout for the first display would've happened - fakeClock.advanceTime(TIMEOUT_MS - waitTime + 1) - - // Verify we didn't hide the chip - verify(windowManager, never()).removeView(any()) - } - - @Test - fun displayChip_calledAgainBeforeTimeout_eventuallyTimesOut() { - // First, display the chip - val state = getState() - controllerCommon.displayChip(state) - - // After some time, re-display the chip - fakeClock.advanceTime(1000L) - controllerCommon.displayChip(getState()) - - // Ensure we still hide the chip eventually - fakeClock.advanceTime(TIMEOUT_MS + 1) - - verify(windowManager).removeView(any()) - } - - @Test - fun displayScaleChange_chipReinflatedWithMostRecentState() { - controllerCommon.displayChip(getState(name = "First name")) - controllerCommon.displayChip(getState(name = "Second name")) - reset(windowManager) - - getConfigurationListener().onDensityOrFontScaleChanged() - - verify(windowManager).removeView(any()) - verify(windowManager).addView(any(), any()) - assertThat(controllerCommon.mostRecentChipInfo?.name).isEqualTo("Second name") - } - - @Test - fun removeChip_chipRemovedAndRemovalLogged() { - // First, add the chip - controllerCommon.displayChip(getState()) - - // Then, remove it - val reason = "test reason" - controllerCommon.removeChip(reason) - - verify(windowManager).removeView(any()) - verify(logger).logChipRemoval(reason) - } - - @Test - fun removeChip_noAdd_viewNotRemoved() { - controllerCommon.removeChip("reason") - - verify(windowManager, never()).removeView(any()) - } - - @Test - fun setIcon_nullAppIconDrawableAndNullPackageName_stillHasIcon() { - controllerCommon.displayChip(getState()) - val chipView = getChipView() - - controllerCommon.setIcon(chipView, appPackageName = null, appIconDrawableOverride = null) - - assertThat(chipView.getAppIconView().drawable).isNotNull() - } - - @Test - fun setIcon_nullAppIconDrawableAndInvalidPackageName_stillHasIcon() { - controllerCommon.displayChip(getState()) - val chipView = getChipView() - - controllerCommon.setIcon( - chipView, appPackageName = "fakePackageName", appIconDrawableOverride = null - ) - - assertThat(chipView.getAppIconView().drawable).isNotNull() - } - - @Test - fun setIcon_nullAppIconDrawable_iconIsFromPackageName() { - controllerCommon.displayChip(getState()) - val chipView = getChipView() - - controllerCommon.setIcon(chipView, PACKAGE_NAME, appIconDrawableOverride = null, null) - - assertThat(chipView.getAppIconView().drawable).isEqualTo(appIconFromPackageName) - } - - @Test - fun setIcon_hasAppIconDrawable_iconIsDrawable() { - controllerCommon.displayChip(getState()) - val chipView = getChipView() - - val drawable = context.getDrawable(R.drawable.ic_alarm)!! - controllerCommon.setIcon(chipView, PACKAGE_NAME, drawable, null) - - assertThat(chipView.getAppIconView().drawable).isEqualTo(drawable) - } - - @Test - fun setIcon_nullAppNameAndNullPackageName_stillHasContentDescription() { - controllerCommon.displayChip(getState()) - val chipView = getChipView() - - controllerCommon.setIcon(chipView, appPackageName = null, appNameOverride = null) - - assertThat(chipView.getAppIconView().contentDescription.toString()).isNotEmpty() - } - - @Test - fun setIcon_nullAppNameAndInvalidPackageName_stillHasContentDescription() { - controllerCommon.displayChip(getState()) - val chipView = getChipView() - - controllerCommon.setIcon( - chipView, appPackageName = "fakePackageName", appNameOverride = null - ) - - assertThat(chipView.getAppIconView().contentDescription.toString()).isNotEmpty() - } - - @Test - fun setIcon_nullAppName_iconContentDescriptionIsFromPackageName() { - controllerCommon.displayChip(getState()) - val chipView = getChipView() - - controllerCommon.setIcon(chipView, PACKAGE_NAME, null, appNameOverride = null) - - assertThat(chipView.getAppIconView().contentDescription).isEqualTo(APP_NAME) - } - - @Test - fun setIcon_hasAppName_iconContentDescriptionIsAppNameOverride() { - controllerCommon.displayChip(getState()) - val chipView = getChipView() - - val appName = "Override App Name" - controllerCommon.setIcon(chipView, PACKAGE_NAME, null, appName) - - assertThat(chipView.getAppIconView().contentDescription).isEqualTo(appName) - } - - @Test - fun setIcon_iconSizeMatchesGetIconSize() { - controllerCommon.displayChip(getState()) - val chipView = getChipView() - - controllerCommon.setIcon(chipView, PACKAGE_NAME) - chipView.measure( - View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), - View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED) - ) - - assertThat(chipView.getAppIconView().measuredWidth).isEqualTo(ICON_SIZE) - assertThat(chipView.getAppIconView().measuredHeight).isEqualTo(ICON_SIZE) - } - - private fun getState(name: String = "name") = ChipInfo(name) - - private fun getChipView(): ViewGroup { - val viewCaptor = ArgumentCaptor.forClass(View::class.java) - verify(windowManager).addView(viewCaptor.capture(), any()) - return viewCaptor.value as ViewGroup - } - - private fun ViewGroup.getAppIconView() = this.requireViewById<ImageView>(R.id.app_icon) - - private fun getConfigurationListener(): ConfigurationListener { - val callbackCaptor = argumentCaptor<ConfigurationListener>() - verify(configurationController).addCallback(capture(callbackCaptor)) - return callbackCaptor.value - } - - inner class TestControllerCommon( - context: Context, - logger: MediaTttLogger, - windowManager: WindowManager, - viewUtil: ViewUtil, - @Main mainExecutor: DelayableExecutor, - accessibilityManager: AccessibilityManager, - configurationController: ConfigurationController, - powerManager: PowerManager, - ) : MediaTttChipControllerCommon<ChipInfo>( - context, - logger, - windowManager, - viewUtil, - mainExecutor, - accessibilityManager, - configurationController, - powerManager, - R.layout.media_ttt_chip, - ) { - var mostRecentChipInfo: ChipInfo? = null - - override val windowLayoutParams = commonWindowLayoutParams - override fun updateChipView(newChipInfo: ChipInfo, currentChipView: ViewGroup) { - super.updateChipView(newChipInfo, currentChipView) - mostRecentChipInfo = newChipInfo - } - override fun getIconSize(isAppIcon: Boolean): Int = ICON_SIZE - } - - inner class ChipInfo(val name: String) : ChipInfoCommon { - override fun getTimeoutMs() = 1L - } -} - -private const val PACKAGE_NAME = "com.android.systemui" -private const val APP_NAME = "Fake App Name" -private const val TIMEOUT_MS = 10000L -private const val ICON_SIZE = 47 diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttLoggerTest.kt index d95e5c48256c..1078cdaa57c4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttLoggerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttLoggerTest.kt @@ -23,11 +23,11 @@ import com.android.systemui.log.LogBuffer import com.android.systemui.log.LogBufferFactory import com.android.systemui.log.LogcatEchoTracker import com.google.common.truth.Truth.assertThat +import java.io.PrintWriter +import java.io.StringWriter import org.junit.Before import org.junit.Test import org.mockito.Mockito.mock -import java.io.PrintWriter -import java.io.StringWriter @SmallTest class MediaTttLoggerTest : SysuiTestCase() { @@ -43,32 +43,46 @@ class MediaTttLoggerTest : SysuiTestCase() { } @Test - fun logStateChange_bufferHasDeviceTypeTagAndStateNameAndId() { + fun logStateChange_bufferHasDeviceTypeTagAndParamInfo() { val stateName = "test state name" val id = "test id" + val packageName = "this.is.a.package" - logger.logStateChange(stateName, id) - - val stringWriter = StringWriter() - buffer.dump(PrintWriter(stringWriter), tailLength = 0) - val actualString = stringWriter.toString() + logger.logStateChange(stateName, id, packageName) + val actualString = getStringFromBuffer() assertThat(actualString).contains(DEVICE_TYPE_TAG) assertThat(actualString).contains(stateName) assertThat(actualString).contains(id) + assertThat(actualString).contains(packageName) } @Test - fun logChipRemoval_bufferHasDeviceTypeAndReason() { - val reason = "test reason" - logger.logChipRemoval(reason) + fun logPackageNotFound_bufferHasPackageName() { + val packageName = "this.is.a.package" + logger.logPackageNotFound(packageName) + + val actualString = getStringFromBuffer() + assertThat(actualString).contains(packageName) + } + + @Test + fun logRemovalBypass_bufferHasReasons() { + val removalReason = "fakeRemovalReason" + val bypassReason = "fakeBypassReason" + + logger.logRemovalBypass(removalReason, bypassReason) + + val actualString = getStringFromBuffer() + assertThat(actualString).contains(removalReason) + assertThat(actualString).contains(bypassReason) + } + + private fun getStringFromBuffer(): String { val stringWriter = StringWriter() buffer.dump(PrintWriter(stringWriter), tailLength = 0) - val actualString = stringWriter.toString() - - assertThat(actualString).contains(DEVICE_TYPE_TAG) - assertThat(actualString).contains(reason) + return stringWriter.toString() } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttUtilsTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttUtilsTest.kt new file mode 100644 index 000000000000..37f6434ea069 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/common/MediaTttUtilsTest.kt @@ -0,0 +1,138 @@ +/* + * 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.media.taptotransfer.common + +import android.content.pm.ApplicationInfo +import android.content.pm.PackageManager +import android.graphics.drawable.Drawable +import android.widget.FrameLayout +import androidx.test.filters.SmallTest +import com.android.internal.widget.CachingIconView +import com.android.systemui.R +import com.android.systemui.SysuiTestCase +import com.android.systemui.util.mockito.any +import com.google.common.truth.Truth.assertThat +import org.junit.Before +import org.junit.Test +import org.mockito.Mock +import org.mockito.Mockito +import org.mockito.Mockito.`when` as whenever +import org.mockito.MockitoAnnotations + +@SmallTest +class MediaTttUtilsTest : SysuiTestCase() { + + private lateinit var appIconFromPackageName: Drawable + @Mock private lateinit var packageManager: PackageManager + @Mock private lateinit var applicationInfo: ApplicationInfo + @Mock private lateinit var logger: MediaTttLogger + + @Before + fun setUp() { + MockitoAnnotations.initMocks(this) + + // Set up our package manager to give valid information for [PACKAGE_NAME] only + appIconFromPackageName = context.getDrawable(R.drawable.ic_cake)!! + whenever(packageManager.getApplicationIcon(PACKAGE_NAME)).thenReturn(appIconFromPackageName) + whenever(applicationInfo.loadLabel(packageManager)).thenReturn(APP_NAME) + whenever( + packageManager.getApplicationInfo(any(), any<PackageManager.ApplicationInfoFlags>()) + ) + .thenThrow(PackageManager.NameNotFoundException()) + whenever( + packageManager.getApplicationInfo( + Mockito.eq(PACKAGE_NAME), + any<PackageManager.ApplicationInfoFlags>() + ) + ) + .thenReturn(applicationInfo) + context.setMockPackageManager(packageManager) + } + + @Test + fun getIconInfoFromPackageName_nullPackageName_returnsDefault() { + val iconInfo = + MediaTttUtils.getIconInfoFromPackageName(context, appPackageName = null, logger) + + assertThat(iconInfo.isAppIcon).isFalse() + assertThat(iconInfo.contentDescription) + .isEqualTo(context.getString(R.string.media_output_dialog_unknown_launch_app_name)) + } + + @Test + fun getIconInfoFromPackageName_invalidPackageName_returnsDefault() { + val iconInfo = MediaTttUtils.getIconInfoFromPackageName(context, "fakePackageName", logger) + + assertThat(iconInfo.isAppIcon).isFalse() + assertThat(iconInfo.contentDescription) + .isEqualTo(context.getString(R.string.media_output_dialog_unknown_launch_app_name)) + } + + @Test + fun getIconInfoFromPackageName_validPackageName_returnsAppInfo() { + val iconInfo = MediaTttUtils.getIconInfoFromPackageName(context, PACKAGE_NAME, logger) + + assertThat(iconInfo.isAppIcon).isTrue() + assertThat(iconInfo.drawable).isEqualTo(appIconFromPackageName) + assertThat(iconInfo.contentDescription).isEqualTo(APP_NAME) + } + + @Test + fun setIcon_viewHasIconAndContentDescription() { + val view = CachingIconView(context) + val icon = context.getDrawable(R.drawable.ic_celebration)!! + val contentDescription = "Happy birthday!" + + MediaTttUtils.setIcon(view, icon, contentDescription) + + assertThat(view.drawable).isEqualTo(icon) + assertThat(view.contentDescription).isEqualTo(contentDescription) + } + + @Test + fun setIcon_iconSizeNull_viewSizeDoesNotChange() { + val view = CachingIconView(context) + val size = 456 + view.layoutParams = FrameLayout.LayoutParams(size, size) + + MediaTttUtils.setIcon(view, context.getDrawable(R.drawable.ic_cake)!!, "desc") + + assertThat(view.layoutParams.width).isEqualTo(size) + assertThat(view.layoutParams.height).isEqualTo(size) + } + + @Test + fun setIcon_iconSizeProvided_viewSizeUpdates() { + val view = CachingIconView(context) + val size = 456 + view.layoutParams = FrameLayout.LayoutParams(size, size) + + val newSize = 40 + MediaTttUtils.setIcon( + view, + context.getDrawable(R.drawable.ic_cake)!!, + "desc", + iconSize = newSize + ) + + assertThat(view.layoutParams.width).isEqualTo(newSize) + assertThat(view.layoutParams.height).isEqualTo(newSize) + } +} + +private const val PACKAGE_NAME = "com.android.systemui" +private const val APP_NAME = "Fake App Name" diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt index 171d893640d6..d41ad48676b4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/receiver/MediaTttChipControllerReceiverTest.kt @@ -41,7 +41,6 @@ import com.android.systemui.util.concurrency.FakeExecutor import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.eq import com.android.systemui.util.time.FakeSystemClock -import com.android.systemui.util.view.ViewUtil import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Test @@ -74,8 +73,6 @@ class MediaTttChipControllerReceiverTest : SysuiTestCase() { @Mock private lateinit var windowManager: WindowManager @Mock - private lateinit var viewUtil: ViewUtil - @Mock private lateinit var commandQueue: CommandQueue private lateinit var commandQueueCallback: CommandQueue.Callbacks private lateinit var fakeAppIconDrawable: Drawable @@ -102,7 +99,6 @@ class MediaTttChipControllerReceiverTest : SysuiTestCase() { context, logger, windowManager, - viewUtil, FakeExecutor(FakeSystemClock()), accessibilityManager, configurationController, @@ -177,37 +173,72 @@ class MediaTttChipControllerReceiverTest : SysuiTestCase() { null ) - verify(logger).logStateChange(any(), any()) + verify(logger).logStateChange(any(), any(), any()) + } + + @Test + fun updateView_noOverrides_usesInfoFromAppIcon() { + controllerReceiver.displayView( + ChipReceiverInfo(routeInfo, appIconDrawableOverride = null, appNameOverride = null) + ) + + val view = getChipView() + assertThat(view.getAppIconView().drawable).isEqualTo(fakeAppIconDrawable) + assertThat(view.getAppIconView().contentDescription).isEqualTo(APP_NAME) } @Test - fun setIcon_isAppIcon_usesAppIconSize() { - controllerReceiver.displayChip(getChipReceiverInfo()) + fun updateView_appIconOverride_usesOverride() { + val drawableOverride = context.getDrawable(R.drawable.ic_celebration)!! + + controllerReceiver.displayView( + ChipReceiverInfo(routeInfo, drawableOverride, appNameOverride = null) + ) + + val view = getChipView() + assertThat(view.getAppIconView().drawable).isEqualTo(drawableOverride) + } + + @Test + fun updateView_appNameOverride_usesOverride() { + val appNameOverride = "Sweet New App" + + controllerReceiver.displayView( + ChipReceiverInfo(routeInfo, appIconDrawableOverride = null, appNameOverride) + ) + + val view = getChipView() + assertThat(view.getAppIconView().contentDescription).isEqualTo(appNameOverride) + } + + @Test + fun updateView_isAppIcon_usesAppIconSize() { + controllerReceiver.displayView(getChipReceiverInfo(packageName = PACKAGE_NAME)) val chipView = getChipView() - controllerReceiver.setIcon(chipView, PACKAGE_NAME) chipView.measure( View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED) ) - val expectedSize = controllerReceiver.getIconSize(isAppIcon = true) + val expectedSize = + context.resources.getDimensionPixelSize(R.dimen.media_ttt_icon_size_receiver) assertThat(chipView.getAppIconView().measuredWidth).isEqualTo(expectedSize) assertThat(chipView.getAppIconView().measuredHeight).isEqualTo(expectedSize) } @Test - fun setIcon_notAppIcon_usesGenericIconSize() { - controllerReceiver.displayChip(getChipReceiverInfo()) + fun updateView_notAppIcon_usesGenericIconSize() { + controllerReceiver.displayView(getChipReceiverInfo(packageName = null)) val chipView = getChipView() - controllerReceiver.setIcon(chipView, appPackageName = null) chipView.measure( View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED) ) - val expectedSize = controllerReceiver.getIconSize(isAppIcon = false) + val expectedSize = + context.resources.getDimensionPixelSize(R.dimen.media_ttt_generic_icon_size_receiver) assertThat(chipView.getAppIconView().measuredWidth).isEqualTo(expectedSize) assertThat(chipView.getAppIconView().measuredHeight).isEqualTo(expectedSize) } @@ -230,8 +261,13 @@ class MediaTttChipControllerReceiverTest : SysuiTestCase() { return viewCaptor.value as ViewGroup } - private fun getChipReceiverInfo(): ChipReceiverInfo = - ChipReceiverInfo(routeInfo, null, null) + private fun getChipReceiverInfo(packageName: String?): ChipReceiverInfo { + val routeInfo = MediaRoute2Info.Builder("id", "Test route name") + .addFeature("feature") + .setClientPackageName(packageName) + .build() + return ChipReceiverInfo(routeInfo, null, null) + } private fun ViewGroup.getAppIconView() = this.requireViewById<ImageView>(R.id.app_icon) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSenderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSenderTest.kt index 1061e3c6b0d5..ff0faf98fe1e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSenderTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/taptotransfer/sender/MediaTttChipControllerSenderTest.kt @@ -42,7 +42,6 @@ import com.android.systemui.util.concurrency.FakeExecutor import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.eq import com.android.systemui.util.time.FakeSystemClock -import com.android.systemui.util.view.ViewUtil import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Test @@ -51,8 +50,8 @@ import org.mockito.ArgumentCaptor import org.mockito.Mock import org.mockito.Mockito.never import org.mockito.Mockito.verify -import org.mockito.MockitoAnnotations import org.mockito.Mockito.`when` as whenever +import org.mockito.MockitoAnnotations @SmallTest @RunWith(AndroidTestingRunner::class) @@ -75,8 +74,6 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() { @Mock private lateinit var windowManager: WindowManager @Mock - private lateinit var viewUtil: ViewUtil - @Mock private lateinit var commandQueue: CommandQueue private lateinit var commandQueueCallback: CommandQueue.Callbacks private lateinit var fakeAppIconDrawable: Drawable @@ -110,7 +107,6 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() { context, logger, windowManager, - viewUtil, fakeExecutor, accessibilityManager, configurationController, @@ -303,13 +299,13 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() { null ) - verify(logger).logStateChange(any(), any()) + verify(logger).logStateChange(any(), any(), any()) } @Test fun almostCloseToStartCast_appIcon_deviceName_noLoadingIcon_noUndo_noFailureIcon() { val state = almostCloseToStartCast() - controllerSender.displayChip(state) + controllerSender.displayView(state) val chipView = getChipView() assertThat(chipView.getAppIconView().drawable).isEqualTo(fakeAppIconDrawable) @@ -325,7 +321,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() { @Test fun almostCloseToEndCast_appIcon_deviceName_noLoadingIcon_noUndo_noFailureIcon() { val state = almostCloseToEndCast() - controllerSender.displayChip(state) + controllerSender.displayView(state) val chipView = getChipView() assertThat(chipView.getAppIconView().drawable).isEqualTo(fakeAppIconDrawable) @@ -341,7 +337,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() { @Test fun transferToReceiverTriggered_appIcon_loadingIcon_noUndo_noFailureIcon() { val state = transferToReceiverTriggered() - controllerSender.displayChip(state) + controllerSender.displayView(state) val chipView = getChipView() assertThat(chipView.getAppIconView().drawable).isEqualTo(fakeAppIconDrawable) @@ -357,7 +353,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() { @Test fun transferToThisDeviceTriggered_appIcon_loadingIcon_noUndo_noFailureIcon() { val state = transferToThisDeviceTriggered() - controllerSender.displayChip(state) + controllerSender.displayView(state) val chipView = getChipView() assertThat(chipView.getAppIconView().drawable).isEqualTo(fakeAppIconDrawable) @@ -373,7 +369,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() { @Test fun transferToReceiverSucceeded_appIcon_deviceName_noLoadingIcon_noFailureIcon() { val state = transferToReceiverSucceeded() - controllerSender.displayChip(state) + controllerSender.displayView(state) val chipView = getChipView() assertThat(chipView.getAppIconView().drawable).isEqualTo(fakeAppIconDrawable) @@ -387,7 +383,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() { @Test fun transferToReceiverSucceeded_nullUndoRunnable_noUndo() { - controllerSender.displayChip(transferToReceiverSucceeded(undoCallback = null)) + controllerSender.displayView(transferToReceiverSucceeded(undoCallback = null)) val chipView = getChipView() assertThat(chipView.getUndoButton().visibility).isEqualTo(View.GONE) @@ -398,7 +394,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() { val undoCallback = object : IUndoMediaTransferCallback.Stub() { override fun onUndoTriggered() {} } - controllerSender.displayChip(transferToReceiverSucceeded(undoCallback)) + controllerSender.displayView(transferToReceiverSucceeded(undoCallback)) val chipView = getChipView() assertThat(chipView.getUndoButton().visibility).isEqualTo(View.VISIBLE) @@ -414,7 +410,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() { } } - controllerSender.displayChip(transferToReceiverSucceeded(undoCallback)) + controllerSender.displayView(transferToReceiverSucceeded(undoCallback)) getChipView().getUndoButton().performClick() assertThat(undoCallbackCalled).isTrue() @@ -425,7 +421,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() { val undoCallback = object : IUndoMediaTransferCallback.Stub() { override fun onUndoTriggered() {} } - controllerSender.displayChip(transferToReceiverSucceeded(undoCallback)) + controllerSender.displayView(transferToReceiverSucceeded(undoCallback)) getChipView().getUndoButton().performClick() @@ -440,7 +436,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() { @Test fun transferToThisDeviceSucceeded_appIcon_deviceName_noLoadingIcon_noFailureIcon() { val state = transferToThisDeviceSucceeded() - controllerSender.displayChip(state) + controllerSender.displayView(state) val chipView = getChipView() assertThat(chipView.getAppIconView().drawable).isEqualTo(fakeAppIconDrawable) @@ -454,7 +450,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() { @Test fun transferToThisDeviceSucceeded_nullUndoRunnable_noUndo() { - controllerSender.displayChip(transferToThisDeviceSucceeded(undoCallback = null)) + controllerSender.displayView(transferToThisDeviceSucceeded(undoCallback = null)) val chipView = getChipView() assertThat(chipView.getUndoButton().visibility).isEqualTo(View.GONE) @@ -465,7 +461,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() { val undoCallback = object : IUndoMediaTransferCallback.Stub() { override fun onUndoTriggered() {} } - controllerSender.displayChip(transferToThisDeviceSucceeded(undoCallback)) + controllerSender.displayView(transferToThisDeviceSucceeded(undoCallback)) val chipView = getChipView() assertThat(chipView.getUndoButton().visibility).isEqualTo(View.VISIBLE) @@ -481,7 +477,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() { } } - controllerSender.displayChip(transferToThisDeviceSucceeded(undoCallback)) + controllerSender.displayView(transferToThisDeviceSucceeded(undoCallback)) getChipView().getUndoButton().performClick() assertThat(undoCallbackCalled).isTrue() @@ -492,7 +488,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() { val undoCallback = object : IUndoMediaTransferCallback.Stub() { override fun onUndoTriggered() {} } - controllerSender.displayChip(transferToThisDeviceSucceeded(undoCallback)) + controllerSender.displayView(transferToThisDeviceSucceeded(undoCallback)) getChipView().getUndoButton().performClick() @@ -507,7 +503,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() { @Test fun transferToReceiverFailed_appIcon_noDeviceName_noLoadingIcon_noUndo_failureIcon() { val state = transferToReceiverFailed() - controllerSender.displayChip(state) + controllerSender.displayView(state) val chipView = getChipView() assertThat(chipView.getAppIconView().drawable).isEqualTo(fakeAppIconDrawable) @@ -523,7 +519,7 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() { @Test fun transferToThisDeviceFailed_appIcon_noDeviceName_noLoadingIcon_noUndo_failureIcon() { val state = transferToThisDeviceFailed() - controllerSender.displayChip(state) + controllerSender.displayView(state) val chipView = getChipView() assertThat(chipView.getAppIconView().drawable).isEqualTo(fakeAppIconDrawable) @@ -538,24 +534,24 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() { @Test fun changeFromAlmostCloseToStartToTransferTriggered_loadingIconAppears() { - controllerSender.displayChip(almostCloseToStartCast()) - controllerSender.displayChip(transferToReceiverTriggered()) + controllerSender.displayView(almostCloseToStartCast()) + controllerSender.displayView(transferToReceiverTriggered()) assertThat(getChipView().getLoadingIconVisibility()).isEqualTo(View.VISIBLE) } @Test fun changeFromTransferTriggeredToTransferSucceeded_loadingIconDisappears() { - controllerSender.displayChip(transferToReceiverTriggered()) - controllerSender.displayChip(transferToReceiverSucceeded()) + controllerSender.displayView(transferToReceiverTriggered()) + controllerSender.displayView(transferToReceiverSucceeded()) assertThat(getChipView().getLoadingIconVisibility()).isEqualTo(View.GONE) } @Test fun changeFromTransferTriggeredToTransferSucceeded_undoButtonAppears() { - controllerSender.displayChip(transferToReceiverTriggered()) - controllerSender.displayChip( + controllerSender.displayView(transferToReceiverTriggered()) + controllerSender.displayView( transferToReceiverSucceeded( object : IUndoMediaTransferCallback.Stub() { override fun onUndoTriggered() {} @@ -568,66 +564,166 @@ class MediaTttChipControllerSenderTest : SysuiTestCase() { @Test fun changeFromTransferSucceededToAlmostCloseToStart_undoButtonDisappears() { - controllerSender.displayChip(transferToReceiverSucceeded()) - controllerSender.displayChip(almostCloseToStartCast()) + controllerSender.displayView(transferToReceiverSucceeded()) + controllerSender.displayView(almostCloseToStartCast()) assertThat(getChipView().getUndoButton().visibility).isEqualTo(View.GONE) } @Test fun changeFromTransferTriggeredToTransferFailed_failureIconAppears() { - controllerSender.displayChip(transferToReceiverTriggered()) - controllerSender.displayChip(transferToReceiverFailed()) + controllerSender.displayView(transferToReceiverTriggered()) + controllerSender.displayView(transferToReceiverFailed()) assertThat(getChipView().getFailureIcon().visibility).isEqualTo(View.VISIBLE) } @Test - fun transferToReceiverTriggeredThenRemoveChip_chipStillDisplayed() { - controllerSender.displayChip(transferToReceiverTriggered()) + fun transferToReceiverTriggeredThenRemoveView_viewStillDisplayed() { + controllerSender.displayView(transferToReceiverTriggered()) fakeClock.advanceTime(1000L) - controllerSender.removeChip("fakeRemovalReason") + controllerSender.removeView("fakeRemovalReason") fakeExecutor.runAllReady() verify(windowManager, never()).removeView(any()) + verify(logger).logRemovalBypass(any(), any()) } @Test - fun transferToReceiverTriggeredThenFarFromReceiver_eventuallyTimesOut() { - val state = transferToReceiverTriggered() - controllerSender.displayChip(state) - fakeClock.advanceTime(1000L) - controllerSender.removeChip("fakeRemovalReason") + fun transferToReceiverTriggeredThenFarFromReceiver_viewStillDisplayed() { + controllerSender.displayView(transferToReceiverTriggered()) + commandQueueCallback.updateMediaTapToTransferSenderDisplay( + StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_FAR_FROM_RECEIVER, + routeInfo, + null + ) + fakeExecutor.runAllReady() + + verify(windowManager, never()).removeView(any()) + verify(logger).logRemovalBypass(any(), any()) + } + + @Test + fun transferToReceiverTriggeredThenRemoveView_eventuallyTimesOut() { + controllerSender.displayView(transferToReceiverTriggered()) + + controllerSender.removeView("fakeRemovalReason") fakeClock.advanceTime(TIMEOUT + 1L) verify(windowManager).removeView(any()) } @Test - fun transferToThisDeviceTriggeredThenRemoveChip_chipStillDisplayed() { - controllerSender.displayChip(transferToThisDeviceTriggered()) + fun transferToThisDeviceTriggeredThenRemoveView_viewStillDisplayed() { + controllerSender.displayView(transferToThisDeviceTriggered()) fakeClock.advanceTime(1000L) - controllerSender.removeChip("fakeRemovalReason") + controllerSender.removeView("fakeRemovalReason") fakeExecutor.runAllReady() verify(windowManager, never()).removeView(any()) + verify(logger).logRemovalBypass(any(), any()) } @Test - fun transferToThisDeviceTriggeredThenFarFromReceiver_eventuallyTimesOut() { - val state = transferToThisDeviceTriggered() - controllerSender.displayChip(state) - fakeClock.advanceTime(1000L) - controllerSender.removeChip("fakeRemovalReason") + fun transferToThisDeviceTriggeredThenRemoveView_eventuallyTimesOut() { + controllerSender.displayView(transferToThisDeviceTriggered()) + controllerSender.removeView("fakeRemovalReason") fakeClock.advanceTime(TIMEOUT + 1L) verify(windowManager).removeView(any()) } + @Test + fun transferToThisDeviceTriggeredThenFarFromReceiver_viewStillDisplayed() { + controllerSender.displayView(transferToThisDeviceTriggered()) + + commandQueueCallback.updateMediaTapToTransferSenderDisplay( + StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_FAR_FROM_RECEIVER, + routeInfo, + null + ) + fakeExecutor.runAllReady() + + verify(windowManager, never()).removeView(any()) + verify(logger).logRemovalBypass(any(), any()) + } + + @Test + fun transferToReceiverSucceededThenRemoveView_viewStillDisplayed() { + controllerSender.displayView(transferToReceiverSucceeded()) + + controllerSender.removeView("fakeRemovalReason") + fakeExecutor.runAllReady() + + verify(windowManager, never()).removeView(any()) + verify(logger).logRemovalBypass(any(), any()) + } + + @Test + fun transferToReceiverSucceededThenRemoveView_eventuallyTimesOut() { + controllerSender.displayView(transferToReceiverSucceeded()) + + controllerSender.removeView("fakeRemovalReason") + fakeClock.advanceTime(TIMEOUT + 1L) + + verify(windowManager).removeView(any()) + } + + @Test + fun transferToReceiverSucceededThenFarFromReceiver_viewStillDisplayed() { + controllerSender.displayView(transferToReceiverSucceeded()) + + commandQueueCallback.updateMediaTapToTransferSenderDisplay( + StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_FAR_FROM_RECEIVER, + routeInfo, + null + ) + fakeExecutor.runAllReady() + + verify(windowManager, never()).removeView(any()) + verify(logger).logRemovalBypass(any(), any()) + } + + @Test + fun transferToThisDeviceSucceededThenRemoveView_viewStillDisplayed() { + controllerSender.displayView(transferToThisDeviceSucceeded()) + + controllerSender.removeView("fakeRemovalReason") + fakeExecutor.runAllReady() + + verify(windowManager, never()).removeView(any()) + verify(logger).logRemovalBypass(any(), any()) + } + + @Test + fun transferToThisDeviceSucceededThenRemoveView_eventuallyTimesOut() { + controllerSender.displayView(transferToThisDeviceSucceeded()) + + controllerSender.removeView("fakeRemovalReason") + fakeClock.advanceTime(TIMEOUT + 1L) + + verify(windowManager).removeView(any()) + } + + @Test + fun transferToThisDeviceSucceededThenFarFromReceiver_viewStillDisplayed() { + controllerSender.displayView(transferToThisDeviceSucceeded()) + + commandQueueCallback.updateMediaTapToTransferSenderDisplay( + StatusBarManager.MEDIA_TRANSFER_SENDER_STATE_FAR_FROM_RECEIVER, + routeInfo, + null + ) + fakeExecutor.runAllReady() + + verify(windowManager, never()).removeView(any()) + verify(logger).logRemovalBypass(any(), any()) + } + private fun ViewGroup.getAppIconView() = this.requireViewById<ImageView>(R.id.app_icon) private fun ViewGroup.getChipText(): String = diff --git a/packages/SystemUI/tests/src/com/android/systemui/power/data/repository/PowerRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/power/data/repository/PowerRepositoryImplTest.kt new file mode 100644 index 000000000000..249a91b0982a --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/power/data/repository/PowerRepositoryImplTest.kt @@ -0,0 +1,181 @@ +/* + * 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.power.data.repository + +import android.content.BroadcastReceiver +import android.content.Intent +import android.content.IntentFilter +import android.os.PowerManager +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.broadcast.BroadcastDispatcher +import com.android.systemui.util.mockito.capture +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.runBlocking +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 +import org.mockito.ArgumentCaptor +import org.mockito.Captor +import org.mockito.Mock +import org.mockito.Mockito.anyInt +import org.mockito.Mockito.isNull +import org.mockito.Mockito.verify +import org.mockito.Mockito.`when` as whenever +import org.mockito.MockitoAnnotations + +@SmallTest +@RunWith(JUnit4::class) +class PowerRepositoryImplTest : SysuiTestCase() { + + @Mock private lateinit var manager: PowerManager + @Mock private lateinit var dispatcher: BroadcastDispatcher + @Captor private lateinit var receiverCaptor: ArgumentCaptor<BroadcastReceiver> + @Captor private lateinit var filterCaptor: ArgumentCaptor<IntentFilter> + + private lateinit var underTest: PowerRepositoryImpl + + private var isInteractive = true + + @Before + fun setUp() { + MockitoAnnotations.initMocks(this) + isInteractive = true + whenever(manager.isInteractive).then { isInteractive } + + underTest = PowerRepositoryImpl(manager = manager, dispatcher = dispatcher) + } + + @Test + fun `isInteractive - registers for broadcasts`() = + runBlocking(IMMEDIATE) { + val job = underTest.isInteractive.onEach {}.launchIn(this) + + verifyRegistered() + assertThat(filterCaptor.value.hasAction(Intent.ACTION_SCREEN_ON)).isTrue() + assertThat(filterCaptor.value.hasAction(Intent.ACTION_SCREEN_OFF)).isTrue() + + job.cancel() + } + + @Test + fun `isInteractive - unregisters from broadcasts`() = + runBlocking(IMMEDIATE) { + val job = underTest.isInteractive.onEach {}.launchIn(this) + verifyRegistered() + + job.cancel() + + verify(dispatcher).unregisterReceiver(receiverCaptor.value) + } + + @Test + fun `isInteractive - emits initial true value if screen was on`() = + runBlocking(IMMEDIATE) { + isInteractive = true + var value: Boolean? = null + val job = underTest.isInteractive.onEach { value = it }.launchIn(this) + + verifyRegistered() + + assertThat(value).isTrue() + job.cancel() + } + + @Test + fun `isInteractive - emits initial false value if screen was off`() = + runBlocking(IMMEDIATE) { + isInteractive = false + var value: Boolean? = null + val job = underTest.isInteractive.onEach { value = it }.launchIn(this) + + verifyRegistered() + + assertThat(value).isFalse() + job.cancel() + } + + @Test + fun `isInteractive - emits true when the screen turns on`() = + runBlocking(IMMEDIATE) { + var value: Boolean? = null + val job = underTest.isInteractive.onEach { value = it }.launchIn(this) + verifyRegistered() + + isInteractive = true + receiverCaptor.value.onReceive(context, Intent(Intent.ACTION_SCREEN_ON)) + + assertThat(value).isTrue() + job.cancel() + } + + @Test + fun `isInteractive - emits false when the screen turns off`() = + runBlocking(IMMEDIATE) { + var value: Boolean? = null + val job = underTest.isInteractive.onEach { value = it }.launchIn(this) + verifyRegistered() + + isInteractive = false + receiverCaptor.value.onReceive(context, Intent(Intent.ACTION_SCREEN_OFF)) + + assertThat(value).isFalse() + job.cancel() + } + + @Test + fun `isInteractive - emits correctly over time`() = + runBlocking(IMMEDIATE) { + val values = mutableListOf<Boolean>() + val job = underTest.isInteractive.onEach(values::add).launchIn(this) + verifyRegistered() + + isInteractive = false + receiverCaptor.value.onReceive(context, Intent(Intent.ACTION_SCREEN_OFF)) + isInteractive = true + receiverCaptor.value.onReceive(context, Intent(Intent.ACTION_SCREEN_ON)) + isInteractive = false + receiverCaptor.value.onReceive(context, Intent(Intent.ACTION_SCREEN_OFF)) + + assertThat(values).isEqualTo(listOf(true, false, true, false)) + job.cancel() + } + + private fun verifyRegistered() { + // We must verify with all arguments, even those that are optional because they have default + // values because Mockito is forcing us to. Once we can use mockito-kotlin, we should be + // able to remove this. + verify(dispatcher) + .registerReceiver( + capture(receiverCaptor), + capture(filterCaptor), + isNull(), + isNull(), + anyInt(), + isNull(), + ) + } + + companion object { + private val IMMEDIATE = Dispatchers.Main.immediate + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/power/domain/interactor/PowerInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/power/domain/interactor/PowerInteractorTest.kt new file mode 100644 index 000000000000..bf6a37ec8eff --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/power/domain/interactor/PowerInteractorTest.kt @@ -0,0 +1,78 @@ +/* + * 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.power.domain.interactor + +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.power.data.repository.FakePowerRepository +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.runBlocking +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 + +@SmallTest +@RunWith(JUnit4::class) +class PowerInteractorTest : SysuiTestCase() { + + private lateinit var underTest: PowerInteractor + private lateinit var repository: FakePowerRepository + + @Before + fun setUp() { + repository = + FakePowerRepository( + initialInteractive = true, + ) + underTest = PowerInteractor(repository = repository) + } + + @Test + fun `isInteractive - screen turns off`() = + runBlocking(IMMEDIATE) { + repository.setInteractive(true) + var value: Boolean? = null + val job = underTest.isInteractive.onEach { value = it }.launchIn(this) + + repository.setInteractive(false) + + assertThat(value).isFalse() + job.cancel() + } + + @Test + fun `isInteractive - becomes interactive`() = + runBlocking(IMMEDIATE) { + repository.setInteractive(false) + var value: Boolean? = null + val job = underTest.isInteractive.onEach { value = it }.launchIn(this) + + repository.setInteractive(true) + + assertThat(value).isTrue() + job.cancel() + } + + companion object { + private val IMMEDIATE = Dispatchers.Main.immediate + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java index f08ad2453c5f..5d5918de3d9e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java @@ -94,6 +94,7 @@ public class QSFragmentTest extends SysuiBaseFragmentTest { @Mock private QSPanel.QSTileLayout mQQsTileLayout; @Mock private QSAnimator mQSAnimator; @Mock private StatusBarStateController mStatusBarStateController; + @Mock private QSSquishinessController mSquishinessController; private View mQsFragmentView; public QSFragmentTest() { @@ -139,13 +140,15 @@ public class QSFragmentTest extends SysuiBaseFragmentTest { } @Test - public void transitionToFullShade_inSplitShade_setsAlphaBasedOnProgress() { + public void transitionToFullShade_setsAlphaUsingShadeInterpolator() { QSFragment fragment = resumeAndGetFragment(); - enableSplitShade(); - int transitionPxAmount = 123; + setStatusBarState(StatusBarState.SHADE); + boolean isTransitioningToFullShade = true; float transitionProgress = 0.5f; + float squishinessFraction = 0.5f; - fragment.setTransitionToFullShadeAmount(transitionPxAmount, transitionProgress); + fragment.setTransitionToFullShadeProgress(isTransitioningToFullShade, transitionProgress, + squishinessFraction); assertThat(mQsFragmentView.getAlpha()) .isEqualTo(ShadeInterpolation.getContentAlpha(transitionProgress)); @@ -153,31 +156,32 @@ public class QSFragmentTest extends SysuiBaseFragmentTest { @Test public void - transitionToFullShade_inSplitShade_onKeyguard_bouncerNotActive_usesShadeInterpolator() { + transitionToFullShade_onKeyguard_noBouncer_setsAlphaUsingLinearInterpolator() { QSFragment fragment = resumeAndGetFragment(); - enableSplitShade(); setStatusBarState(StatusBarState.KEYGUARD); when(mQSPanelController.isBouncerInTransit()).thenReturn(false); - int transitionPxAmount = 123; + boolean isTransitioningToFullShade = true; float transitionProgress = 0.5f; + float squishinessFraction = 0.5f; - fragment.setTransitionToFullShadeAmount(transitionPxAmount, transitionProgress); + fragment.setTransitionToFullShadeProgress(isTransitioningToFullShade, transitionProgress, + squishinessFraction); - assertThat(mQsFragmentView.getAlpha()) - .isEqualTo(ShadeInterpolation.getContentAlpha(transitionProgress)); + assertThat(mQsFragmentView.getAlpha()).isEqualTo(transitionProgress); } @Test public void - transitionToFullShade_inSplitShade_onKeyguard_bouncerActive_usesBouncerInterpolator() { + transitionToFullShade_onKeyguard_bouncerActive_setsAlphaUsingBouncerInterpolator() { QSFragment fragment = resumeAndGetFragment(); - enableSplitShade(); setStatusBarState(StatusBarState.KEYGUARD); when(mQSPanelController.isBouncerInTransit()).thenReturn(true); - int transitionPxAmount = 123; + boolean isTransitioningToFullShade = true; float transitionProgress = 0.5f; + float squishinessFraction = 0.5f; - fragment.setTransitionToFullShadeAmount(transitionPxAmount, transitionProgress); + fragment.setTransitionToFullShadeProgress(isTransitioningToFullShade, transitionProgress, + squishinessFraction); assertThat(mQsFragmentView.getAlpha()) .isEqualTo( @@ -186,28 +190,44 @@ public class QSFragmentTest extends SysuiBaseFragmentTest { } @Test - public void transitionToFullShade_notInSplitShade_alwaysSetsAlphaTo1() { + public void transitionToFullShade_inFullWidth_alwaysSetsAlphaTo1() { QSFragment fragment = resumeAndGetFragment(); - disableSplitShade(); + fragment.setIsNotificationPanelFullWidth(true); - int transitionPxAmount = 12; + boolean isTransitioningToFullShade = true; float transitionProgress = 0.1f; - fragment.setTransitionToFullShadeAmount(transitionPxAmount, transitionProgress); + float squishinessFraction = 0.5f; + fragment.setTransitionToFullShadeProgress(isTransitioningToFullShade, transitionProgress, + squishinessFraction); assertThat(mQsFragmentView.getAlpha()).isEqualTo(1); - transitionPxAmount = 123; transitionProgress = 0.5f; - fragment.setTransitionToFullShadeAmount(transitionPxAmount, transitionProgress); + fragment.setTransitionToFullShadeProgress(isTransitioningToFullShade, transitionProgress, + squishinessFraction); assertThat(mQsFragmentView.getAlpha()).isEqualTo(1); assertThat(mQsFragmentView.getAlpha()).isEqualTo(1); - transitionPxAmount = 234; transitionProgress = 0.7f; - fragment.setTransitionToFullShadeAmount(transitionPxAmount, transitionProgress); + fragment.setTransitionToFullShadeProgress(isTransitioningToFullShade, transitionProgress, + squishinessFraction); assertThat(mQsFragmentView.getAlpha()).isEqualTo(1); } @Test + public void transitionToFullShade_setsSquishinessOnController() { + QSFragment fragment = resumeAndGetFragment(); + boolean isTransitioningToFullShade = true; + float transitionProgress = 0.123f; + float squishinessFraction = 0.456f; + + fragment.setTransitionToFullShadeProgress(isTransitioningToFullShade, transitionProgress, + squishinessFraction); + + verify(mQsFragmentComponent.getQSSquishinessController()) + .setSquishiness(squishinessFraction); + } + + @Test public void setQsExpansion_inSplitShade_setsFooterActionsExpansion_basedOnPanelExpFraction() { // Random test values without any meaning. They just have to be different from each other. float expansion = 0.123f; @@ -453,6 +473,7 @@ public class QSFragmentTest extends SysuiBaseFragmentTest { when(mQsFragmentComponent.getQSFooterActionController()) .thenReturn(mQSFooterActionController); when(mQsFragmentComponent.getQSAnimator()).thenReturn(mQSAnimator); + when(mQsFragmentComponent.getQSSquishinessController()).thenReturn(mSquishinessController); } private QSFragment getFragment() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.kt index b98be75a51c7..2db58be15665 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.kt @@ -158,6 +158,13 @@ class QSPanelTest : SysuiTestCase() { assertThat(qsPanel.paddingBottom).isEqualTo(padding) } + @Test + fun testSetSquishinessFraction_noCrash() { + qsPanel.addView(qsPanel.mTileLayout as View, 0) + qsPanel.addView(FrameLayout(context)) + qsPanel.setSquishinessFraction(0.5f) + } + private infix fun View.isLeftOf(other: View): Boolean { val rect = Rect() getBoundsOnScreen(rect) 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 e4751d135035..2a4996f259dc 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 @@ -70,9 +70,13 @@ class FooterActionsViewModelTest : SysuiTestCase() { val underTest = utils.footerActionsViewModel(showPowerButton = false) val settings = underTest.settings - assertThat(settings.contentDescription) - .isEqualTo(ContentDescription.Resource(R.string.accessibility_quick_settings_settings)) - assertThat(settings.icon).isEqualTo(Icon.Resource(R.drawable.ic_settings)) + assertThat(settings.icon) + .isEqualTo( + Icon.Resource( + R.drawable.ic_settings, + ContentDescription.Resource(R.string.accessibility_quick_settings_settings) + ) + ) assertThat(settings.background).isEqualTo(R.drawable.qs_footer_action_circle) assertThat(settings.iconTint).isNull() } @@ -87,11 +91,13 @@ class FooterActionsViewModelTest : SysuiTestCase() { val underTestWithPower = utils.footerActionsViewModel(showPowerButton = true) val power = underTestWithPower.power assertThat(power).isNotNull() - assertThat(power!!.contentDescription) + assertThat(power!!.icon) .isEqualTo( - ContentDescription.Resource(R.string.accessibility_quick_settings_power_menu) + Icon.Resource( + android.R.drawable.ic_lock_power_off, + ContentDescription.Resource(R.string.accessibility_quick_settings_power_menu) + ) ) - assertThat(power.icon).isEqualTo(Icon.Resource(android.R.drawable.ic_lock_power_off)) assertThat(power.background).isEqualTo(R.drawable.qs_footer_action_circle_color) assertThat(power.iconTint) .isEqualTo( @@ -164,14 +170,13 @@ class FooterActionsViewModelTest : SysuiTestCase() { utils.setUserSwitcherEnabled(settings, true, userId) val userSwitcher = currentUserSwitcher() assertThat(userSwitcher).isNotNull() - assertThat(userSwitcher!!.contentDescription) - .isEqualTo(ContentDescription.Loaded("Signed in as foo")) - assertThat(userSwitcher.icon).isEqualTo(Icon.Loaded(picture)) + assertThat(userSwitcher!!.icon) + .isEqualTo(Icon.Loaded(picture, ContentDescription.Loaded("Signed in as foo"))) assertThat(userSwitcher.background).isEqualTo(R.drawable.qs_footer_action_circle) // Change the current user name. userSwitcherControllerWrapper.currentUserName = "bar" - assertThat(currentUserSwitcher()?.contentDescription) + assertThat(currentUserSwitcher()?.icon?.contentDescription) .isEqualTo(ContentDescription.Loaded("Signed in as bar")) fun iconTint(): Int? = currentUserSwitcher()!!.iconTint @@ -243,7 +248,7 @@ class FooterActionsViewModelTest : SysuiTestCase() { // Map any SecurityModel into a non-null SecurityButtonConfig. val buttonConfig = SecurityButtonConfig( - icon = Icon.Resource(0), + icon = Icon.Resource(res = 0, contentDescription = null), text = "foo", isClickable = true, ) @@ -340,7 +345,7 @@ class FooterActionsViewModelTest : SysuiTestCase() { assertThat(foregroundServices.displayText).isTrue() securityToConfig = { SecurityButtonConfig( - icon = Icon.Resource(0), + icon = Icon.Resource(res = 0, contentDescription = null), text = "foo", isClickable = true, ) diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorInversionTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorInversionTileTest.java index bf682a8d4e0a..3fd25019e2a5 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorInversionTileTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ColorInversionTileTest.java @@ -33,12 +33,15 @@ import androidx.test.filters.SmallTest; import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.UiEventLogger; +import com.android.systemui.R; import com.android.systemui.SysuiTestCase; import com.android.systemui.classifier.FalsingManagerFake; import com.android.systemui.plugins.ActivityStarter; +import com.android.systemui.plugins.qs.QSTile; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.qs.QSTileHost; import com.android.systemui.qs.logging.QSLogger; +import com.android.systemui.qs.tileimpl.QSTileImpl; import com.android.systemui.settings.UserTracker; import com.android.systemui.util.settings.FakeSettings; import com.android.systemui.util.settings.SecureSettings; @@ -54,6 +57,8 @@ import org.mockito.MockitoAnnotations; @TestableLooper.RunWithLooper(setAsMainLooper = true) @SmallTest public class ColorInversionTileTest extends SysuiTestCase { + private static final Integer COLOR_INVERSION_DISABLED = 0; + private static final Integer COLOR_INVERSION_ENABLED = 1; @Mock private QSTileHost mHost; @@ -113,4 +118,24 @@ public class ColorInversionTileTest extends SysuiTestCase { assertThat(IntentCaptor.getValue().getAction()).isEqualTo( Settings.ACTION_COLOR_INVERSION_SETTINGS); } + + @Test + public void testIcon_whenColorInversionDisabled_isOffState() { + QSTile.BooleanState state = new QSTile.BooleanState(); + + mTile.handleUpdateState(state, COLOR_INVERSION_DISABLED); + + assertThat(state.icon) + .isEqualTo(QSTileImpl.ResourceIcon.get(R.drawable.qs_invert_colors_icon_off)); + } + + @Test + public void testIcon_whenColorInversionEnabled_isOnState() { + QSTile.BooleanState state = new QSTile.BooleanState(); + + mTile.handleUpdateState(state, COLOR_INVERSION_ENABLED); + + assertThat(state.icon) + .isEqualTo(QSTileImpl.ResourceIcon.get(R.drawable.qs_invert_colors_icon_on)); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DataSaverTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DataSaverTileTest.kt new file mode 100644 index 000000000000..ce62f2d1cf36 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DataSaverTileTest.kt @@ -0,0 +1,106 @@ +/* + * 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.qs.tiles + +import android.os.Handler +import android.testing.AndroidTestingRunner +import android.testing.TestableLooper +import androidx.test.filters.SmallTest +import com.android.internal.logging.MetricsLogger +import com.android.internal.logging.testing.UiEventLoggerFake +import com.android.systemui.R +import com.android.systemui.SysuiTestCase +import com.android.systemui.animation.DialogLaunchAnimator +import com.android.systemui.classifier.FalsingManagerFake +import com.android.systemui.plugins.ActivityStarter +import com.android.systemui.plugins.qs.QSTile +import com.android.systemui.plugins.statusbar.StatusBarStateController +import com.android.systemui.qs.QSHost +import com.android.systemui.qs.logging.QSLogger +import com.android.systemui.qs.tileimpl.QSTileImpl +import com.android.systemui.statusbar.policy.DataSaverController +import com.google.common.truth.Truth.assertThat +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mock +import org.mockito.Mockito +import org.mockito.MockitoAnnotations + +@RunWith(AndroidTestingRunner::class) +@TestableLooper.RunWithLooper(setAsMainLooper = true) +@SmallTest +class DataSaverTileTest : SysuiTestCase() { + + @Mock private lateinit var mHost: QSHost + @Mock private lateinit var mMetricsLogger: MetricsLogger + @Mock private lateinit var mStatusBarStateController: StatusBarStateController + @Mock private lateinit var mActivityStarter: ActivityStarter + @Mock private lateinit var mQsLogger: QSLogger + private val falsingManager = FalsingManagerFake() + @Mock private lateinit var statusBarStateController: StatusBarStateController + @Mock private lateinit var activityStarter: ActivityStarter + @Mock private lateinit var dataSaverController: DataSaverController + @Mock private lateinit var dialogLaunchAnimator: DialogLaunchAnimator + + private val uiEventLogger = UiEventLoggerFake() + private lateinit var testableLooper: TestableLooper + private lateinit var tile: DataSaverTile + + @Before + fun setUp() { + MockitoAnnotations.initMocks(this) + testableLooper = TestableLooper.get(this) + + Mockito.`when`(mHost.context).thenReturn(mContext) + Mockito.`when`(mHost.uiEventLogger).thenReturn(uiEventLogger) + + tile = + DataSaverTile( + mHost, + testableLooper.looper, + Handler(testableLooper.looper), + falsingManager, + mMetricsLogger, + statusBarStateController, + activityStarter, + mQsLogger, + dataSaverController, + dialogLaunchAnimator + ) + } + + @Test + fun testIcon_whenDataSaverEnabled_isOnState() { + val state = QSTile.BooleanState() + + tile.handleUpdateState(state, true) + + assertThat(state.icon) + .isEqualTo(QSTileImpl.ResourceIcon.get(R.drawable.qs_data_saver_icon_on)) + } + + @Test + fun testIcon_whenDataSaverDisabled_isOffState() { + val state = QSTile.BooleanState() + + tile.handleUpdateState(state, false) + + assertThat(state.icon) + .isEqualTo(QSTileImpl.ResourceIcon.get(R.drawable.qs_data_saver_icon_off)) + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt index ed988810fc83..f7b9438e6535 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt @@ -33,17 +33,18 @@ import com.android.systemui.SysuiTestCase import com.android.systemui.animation.ActivityLaunchAnimator import com.android.systemui.classifier.FalsingManagerFake import com.android.systemui.controls.ControlsServiceInfo +import com.android.systemui.controls.controller.ControlInfo import com.android.systemui.controls.controller.ControlsController import com.android.systemui.controls.controller.StructureInfo import com.android.systemui.controls.dagger.ControlsComponent import com.android.systemui.controls.management.ControlsListingController +import com.android.systemui.controls.ui.ControlsActivity import com.android.systemui.controls.ui.ControlsUiController import com.android.systemui.plugins.ActivityStarter import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.qs.QSHost import com.android.systemui.qs.logging.QSLogger import com.android.systemui.qs.tileimpl.QSTileImpl -import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.capture import com.android.systemui.util.mockito.eq @@ -57,13 +58,13 @@ import org.mockito.ArgumentCaptor import org.mockito.ArgumentMatchers.anyBoolean import org.mockito.Captor import org.mockito.Mock +import org.mockito.MockitoAnnotations import org.mockito.Mockito.`when` import org.mockito.Mockito.doNothing import org.mockito.Mockito.nullable import org.mockito.Mockito.spy import org.mockito.Mockito.verify import org.mockito.Mockito.verifyZeroInteractions -import org.mockito.MockitoAnnotations import java.util.Optional @SmallTest @@ -93,8 +94,6 @@ class DeviceControlsTileTest : SysuiTestCase() { private lateinit var serviceInfo: ControlsServiceInfo @Mock private lateinit var uiEventLogger: UiEventLogger - @Mock - private lateinit var keyguardStateController: KeyguardStateController @Captor private lateinit var listingCallbackCaptor: ArgumentCaptor<ControlsListingController.ControlsListingCallback> @@ -119,7 +118,6 @@ class DeviceControlsTileTest : SysuiTestCase() { `when`(qsHost.context).thenReturn(spiedContext) `when`(qsHost.uiEventLogger).thenReturn(uiEventLogger) `when`(controlsComponent.isEnabled()).thenReturn(true) - `when`(keyguardStateController.isUnlocked()).thenReturn(true) `when`(controlsController.getPreferredStructure()) .thenReturn(StructureInfo(ComponentName("pkg", "cls"), "structure", listOf())) secureSettings.putInt(Settings.Secure.LOCKSCREEN_SHOW_CONTROLS, 1) @@ -222,12 +220,19 @@ class DeviceControlsTileTest : SysuiTestCase() { } @Test - fun testStateAvailableIfListings() { + fun testStateActiveIfListingsHasControlsFavorited() { verify(controlsListingController).observe( any(LifecycleOwner::class.java), capture(listingCallbackCaptor) ) `when`(controlsComponent.getVisibility()).thenReturn(ControlsComponent.Visibility.AVAILABLE) + `when`(controlsController.getPreferredStructure()).thenReturn( + StructureInfo( + ComponentName("pkg", "cls"), + "structure", + listOf(ControlInfo("id", "title", "subtitle", 1)) + ) + ) listingCallbackCaptor.value.onServicesUpdated(listOf(serviceInfo)) testableLooper.processAllMessages() @@ -236,6 +241,22 @@ class DeviceControlsTileTest : SysuiTestCase() { } @Test + fun testStateInactiveIfListingsHasNoControlsFavorited() { + verify(controlsListingController).observe( + any(LifecycleOwner::class.java), + capture(listingCallbackCaptor) + ) + `when`(controlsComponent.getVisibility()).thenReturn(ControlsComponent.Visibility.AVAILABLE) + `when`(controlsController.getPreferredStructure()) + .thenReturn(StructureInfo(ComponentName("pkg", "cls"), "structure", listOf())) + + listingCallbackCaptor.value.onServicesUpdated(listOf(serviceInfo)) + testableLooper.processAllMessages() + + assertThat(tile.state.state).isEqualTo(Tile.STATE_INACTIVE) + } + + @Test fun testStateInactiveIfLocked() { verify(controlsListingController).observe( any(LifecycleOwner::class.java), @@ -281,7 +302,14 @@ class DeviceControlsTileTest : SysuiTestCase() { capture(listingCallbackCaptor) ) `when`(controlsComponent.getVisibility()).thenReturn(ControlsComponent.Visibility.AVAILABLE) - `when`(keyguardStateController.isUnlocked).thenReturn(true) + `when`(controlsUiController.resolveActivity()).thenReturn(ControlsActivity::class.java) + `when`(controlsController.getPreferredStructure()).thenReturn( + StructureInfo( + ComponentName("pkg", "cls"), + "structure", + listOf(ControlInfo("id", "title", "subtitle", 1)) + ) + ) listingCallbackCaptor.value.onServicesUpdated(listOf(serviceInfo)) testableLooper.processAllMessages() @@ -305,7 +333,14 @@ class DeviceControlsTileTest : SysuiTestCase() { ) `when`(controlsComponent.getVisibility()) .thenReturn(ControlsComponent.Visibility.AVAILABLE_AFTER_UNLOCK) - `when`(keyguardStateController.isUnlocked).thenReturn(false) + `when`(controlsUiController.resolveActivity()).thenReturn(ControlsActivity::class.java) + `when`(controlsController.getPreferredStructure()).thenReturn( + StructureInfo( + ComponentName("pkg", "cls"), + "structure", + listOf(ControlInfo("id", "title", "subtitle", 1)) + ) + ) listingCallbackCaptor.value.onServicesUpdated(listOf(serviceInfo)) testableLooper.processAllMessages() @@ -345,8 +380,7 @@ class DeviceControlsTileTest : SysuiTestCase() { statusBarStateController, activityStarter, qsLogger, - controlsComponent, - keyguardStateController + controlsComponent ).also { it.initialize() testableLooper.processAllMessages() diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NightDisplayTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NightDisplayTileTest.kt new file mode 100644 index 000000000000..188c3a3d9e42 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/NightDisplayTileTest.kt @@ -0,0 +1,132 @@ +/* + * 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.qs.tiles + +import android.hardware.display.ColorDisplayManager +import android.hardware.display.NightDisplayListener +import android.os.Handler +import android.testing.AndroidTestingRunner +import android.testing.TestableLooper +import androidx.test.filters.SmallTest +import com.android.internal.logging.MetricsLogger +import com.android.internal.logging.UiEventLogger +import com.android.internal.logging.testing.UiEventLoggerFake +import com.android.systemui.R +import com.android.systemui.SysuiTestCase +import com.android.systemui.classifier.FalsingManagerFake +import com.android.systemui.dagger.NightDisplayListenerModule +import com.android.systemui.plugins.ActivityStarter +import com.android.systemui.plugins.qs.QSTile +import com.android.systemui.plugins.statusbar.StatusBarStateController +import com.android.systemui.qs.QSHost +import com.android.systemui.qs.logging.QSLogger +import com.android.systemui.qs.tileimpl.QSTileImpl +import com.android.systemui.statusbar.policy.LocationController +import com.google.common.truth.Truth +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mock +import org.mockito.Mockito.anyInt +import org.mockito.Mockito.`when` as whenever +import org.mockito.MockitoAnnotations + +@RunWith(AndroidTestingRunner::class) +@TestableLooper.RunWithLooper(setAsMainLooper = true) +@SmallTest +class NightDisplayTileTest : SysuiTestCase() { + @Mock + private lateinit var mHost: QSHost + + @Mock + private lateinit var mMetricsLogger: MetricsLogger + + @Mock + private lateinit var mStatusBarStateController: StatusBarStateController + + @Mock + private lateinit var mActivityStarter: ActivityStarter + + @Mock + private lateinit var mQsLogger: QSLogger + + @Mock + private lateinit var mLocationController: LocationController + + @Mock + private lateinit var mColorDisplayManager: ColorDisplayManager + + @Mock + private lateinit var mNightDisplayListenerBuilder: NightDisplayListenerModule.Builder + + @Mock + private lateinit var mNightDisplayListener: NightDisplayListener + + private lateinit var mTestableLooper: TestableLooper + private lateinit var mTile: NightDisplayTile + + private val mUiEventLogger: UiEventLogger = UiEventLoggerFake() + + @Before + fun setUp() { + MockitoAnnotations.initMocks(this) + mTestableLooper = TestableLooper.get(this) + whenever(mHost.context).thenReturn(mContext) + whenever(mHost.uiEventLogger).thenReturn(mUiEventLogger) + whenever(mHost.userContext).thenReturn(mContext) + whenever(mNightDisplayListenerBuilder.setUser(anyInt())).thenReturn( + mNightDisplayListenerBuilder + ) + whenever(mNightDisplayListenerBuilder.build()).thenReturn(mNightDisplayListener) + + mTile = NightDisplayTile( + mHost, + mTestableLooper.looper, + Handler(mTestableLooper.looper), + FalsingManagerFake(), + mMetricsLogger, + mStatusBarStateController, + mActivityStarter, + mQsLogger, + mLocationController, + mColorDisplayManager, + mNightDisplayListenerBuilder + ) + } + + @Test + fun testIcon_whenDisabled_showsOffState() { + whenever(mColorDisplayManager.isNightDisplayActivated).thenReturn(false) + val state = QSTile.BooleanState() + + mTile.handleUpdateState(state, /* arg= */ null) + + Truth.assertThat(state.icon) + .isEqualTo(QSTileImpl.ResourceIcon.get(R.drawable.qs_nightlight_icon_off)) + } + + @Test + fun testIcon_whenEnabled_showsOnState() { + whenever(mColorDisplayManager.isNightDisplayActivated).thenReturn(true) + val state = QSTile.BooleanState() + + mTile.handleUpdateState(state, /* arg= */ null) + + Truth.assertThat(state.icon) + .isEqualTo(QSTileImpl.ResourceIcon.get(R.drawable.qs_nightlight_icon_on)) + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UiModeNightTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UiModeNightTileTest.kt new file mode 100644 index 000000000000..ea70c263a121 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UiModeNightTileTest.kt @@ -0,0 +1,141 @@ +/* + * 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.qs.tiles + +import android.app.UiModeManager +import android.content.Context +import android.content.res.Configuration +import android.content.res.Resources +import android.os.Handler +import android.test.suitebuilder.annotation.SmallTest +import android.testing.AndroidTestingRunner +import android.testing.TestableLooper +import com.android.internal.logging.MetricsLogger +import com.android.internal.logging.testing.UiEventLoggerFake +import com.android.systemui.R +import com.android.systemui.SysuiTestCase +import com.android.systemui.classifier.FalsingManagerFake +import com.android.systemui.plugins.ActivityStarter +import com.android.systemui.plugins.qs.QSTile +import com.android.systemui.plugins.statusbar.StatusBarStateController +import com.android.systemui.qs.QSTileHost +import com.android.systemui.qs.logging.QSLogger +import com.android.systemui.qs.tileimpl.QSTileImpl +import com.android.systemui.statusbar.policy.BatteryController +import com.android.systemui.statusbar.policy.ConfigurationController +import com.android.systemui.statusbar.policy.LocationController +import com.google.common.truth.Truth.assertThat +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mock +import org.mockito.Mockito.`when` +import org.mockito.MockitoAnnotations + +@RunWith(AndroidTestingRunner::class) +@TestableLooper.RunWithLooper(setAsMainLooper = true) +@SmallTest +class UiModeNightTileTest : SysuiTestCase() { + + @Mock + private lateinit var mockContext: Context + @Mock + private lateinit var uiModeManager: UiModeManager + @Mock + private lateinit var resources: Resources + @Mock + private lateinit var qsLogger: QSLogger + @Mock + private lateinit var qsHost: QSTileHost + @Mock + private lateinit var metricsLogger: MetricsLogger + @Mock + private lateinit var statusBarStateController: StatusBarStateController + @Mock + private lateinit var activityStarter: ActivityStarter + @Mock + private lateinit var configurationController: ConfigurationController + @Mock + private lateinit var batteryController: BatteryController + @Mock + private lateinit var locationController: LocationController + + private val uiEventLogger = UiEventLoggerFake() + private val falsingManager = FalsingManagerFake() + private lateinit var testableLooper: TestableLooper + private lateinit var tile: UiModeNightTile + private lateinit var configuration: Configuration + + @Before + fun setUp() { + MockitoAnnotations.initMocks(this) + testableLooper = TestableLooper.get(this) + configuration = Configuration() + mContext.addMockSystemService(Context.UI_MODE_SERVICE, uiModeManager) + + `when`(qsHost.context).thenReturn(mockContext) + `when`(qsHost.userContext).thenReturn(mContext) + `when`(mockContext.resources).thenReturn(resources) + `when`(resources.configuration).thenReturn(configuration) + `when`(qsHost.uiEventLogger).thenReturn(uiEventLogger) + + tile = UiModeNightTile( + qsHost, + testableLooper.looper, + Handler(testableLooper.looper), + falsingManager, + metricsLogger, + statusBarStateController, + activityStarter, + qsLogger, + configurationController, + batteryController, + locationController) + } + + @Test + fun testIcon_whenNightModeOn_isOnState() { + val state = QSTile.BooleanState() + setNightModeOn() + + tile.handleUpdateState(state, /* arg= */ null) + + assertThat(state.icon) + .isEqualTo(QSTileImpl.ResourceIcon.get(R.drawable.qs_light_dark_theme_icon_on)) + } + + @Test + fun testIcon_whenNightModeOn_isOffState() { + val state = QSTile.BooleanState() + setNightModeOff() + + tile.handleUpdateState(state, /* arg= */ null) + + assertThat(state.icon) + .isEqualTo(QSTileImpl.ResourceIcon.get(R.drawable.qs_light_dark_theme_icon_off)) + } + + private fun setNightModeOn() { + `when`(uiModeManager.nightMode).thenReturn(UiModeManager.MODE_NIGHT_YES) + configuration.uiMode = Configuration.UI_MODE_NIGHT_YES + } + + private fun setNightModeOff() { + `when`(uiModeManager.nightMode).thenReturn(UiModeManager.MODE_NIGHT_NO) + configuration.uiMode = Configuration.UI_MODE_NIGHT_NO + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UserDetailViewAdapterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UserDetailViewAdapterTest.kt index 5db3b9caa007..da52a9b1a3c2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UserDetailViewAdapterTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UserDetailViewAdapterTest.kt @@ -53,7 +53,6 @@ class UserDetailViewAdapterTest : SysuiTestCase() { @Mock private lateinit var mUserDetailItemView: UserDetailItemView @Mock private lateinit var mOtherView: View @Mock private lateinit var mInflatedUserDetailItemView: UserDetailItemView - @Mock private lateinit var mUserInfo: UserInfo @Mock private lateinit var mLayoutInflater: LayoutInflater private var falsingManagerFake: FalsingManagerFake = FalsingManagerFake() private lateinit var adapter: UserDetailView.Adapter @@ -142,7 +141,7 @@ class UserDetailViewAdapterTest : SysuiTestCase() { private fun createUserRecord(current: Boolean, guest: Boolean) = UserRecord( - mUserInfo, + UserInfo(0 /* id */, "name", 0 /* flags */), mPicture, guest, current, diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerCombinedTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerCombinedTest.kt index e85ffb68de54..c4485389d646 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerCombinedTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerCombinedTest.kt @@ -23,6 +23,7 @@ import android.graphics.Rect import android.testing.AndroidTestingRunner import android.view.DisplayCutout import android.view.View +import android.view.ViewPropertyAnimator import android.view.WindowInsets import android.widget.TextView import androidx.constraintlayout.motion.widget.MotionLayout @@ -30,6 +31,7 @@ import androidx.constraintlayout.widget.ConstraintSet import androidx.test.filters.SmallTest import com.android.systemui.R import com.android.systemui.SysuiTestCase +import com.android.systemui.animation.Interpolators import com.android.systemui.animation.ShadeInterpolation import com.android.systemui.battery.BatteryMeterView import com.android.systemui.battery.BatteryMeterViewController @@ -64,6 +66,7 @@ import org.mockito.Answers import org.mockito.ArgumentCaptor import org.mockito.ArgumentMatchers import org.mockito.Mock +import org.mockito.Mockito import org.mockito.Mockito.anyBoolean import org.mockito.Mockito.anyFloat import org.mockito.Mockito.anyInt @@ -614,6 +617,34 @@ class LargeScreenShadeHeaderControllerCombinedTest : SysuiTestCase() { ) } + @Test + fun animateOutOnStartCustomizing() { + val animator = Mockito.mock(ViewPropertyAnimator::class.java, Answers.RETURNS_SELF) + val duration = 1000L + whenever(view.animate()).thenReturn(animator) + + controller.startCustomizingAnimation(show = true, duration) + + verify(animator).setDuration(duration) + verify(animator).alpha(0f) + verify(animator).setInterpolator(Interpolators.ALPHA_OUT) + verify(animator).start() + } + + @Test + fun animateInOnEndCustomizing() { + val animator = Mockito.mock(ViewPropertyAnimator::class.java, Answers.RETURNS_SELF) + val duration = 1000L + whenever(view.animate()).thenReturn(animator) + + controller.startCustomizingAnimation(show = false, duration) + + verify(animator).setDuration(duration) + verify(animator).alpha(1f) + verify(animator).setInterpolator(Interpolators.ALPHA_IN) + verify(animator).start() + } + private fun createWindowInsets( topCutout: Rect? = Rect() ): WindowInsets { diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerTest.kt index 8511443705e4..5ecfc8eb3649 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/LargeScreenShadeHeaderControllerTest.kt @@ -4,10 +4,12 @@ import android.app.StatusBarManager import android.content.Context import android.testing.AndroidTestingRunner import android.view.View +import android.view.ViewPropertyAnimator import android.widget.TextView import androidx.test.filters.SmallTest import com.android.systemui.R import com.android.systemui.SysuiTestCase +import com.android.systemui.animation.Interpolators import com.android.systemui.animation.ShadeInterpolation import com.android.systemui.battery.BatteryMeterView import com.android.systemui.battery.BatteryMeterViewController @@ -29,8 +31,10 @@ import org.junit.Before import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith +import org.mockito.Answers import org.mockito.ArgumentMatchers.anyInt import org.mockito.Mock +import org.mockito.Mockito.mock import org.mockito.Mockito.verify import org.mockito.Mockito.verifyZeroInteractions import org.mockito.Mockito.`when` as whenever @@ -198,4 +202,32 @@ class LargeScreenShadeHeaderControllerTest : SysuiTestCase() { context.getString(com.android.internal.R.string.status_bar_alarm_clock) ) } + + @Test + fun animateOutOnStartCustomizing() { + val animator = mock(ViewPropertyAnimator::class.java, Answers.RETURNS_SELF) + val duration = 1000L + whenever(view.animate()).thenReturn(animator) + + mLargeScreenShadeHeaderController.startCustomizingAnimation(show = true, duration) + + verify(animator).setDuration(duration) + verify(animator).alpha(0f) + verify(animator).setInterpolator(Interpolators.ALPHA_OUT) + verify(animator).start() + } + + @Test + fun animateInOnEndCustomizing() { + val animator = mock(ViewPropertyAnimator::class.java, Answers.RETURNS_SELF) + val duration = 1000L + whenever(view.animate()).thenReturn(animator) + + mLargeScreenShadeHeaderController.startCustomizingAnimation(show = false, duration) + + verify(animator).setDuration(duration) + verify(animator).alpha(1f) + verify(animator).setInterpolator(Interpolators.ALPHA_IN) + verify(animator).start() + } } 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 f2670131081f..b40d5ac69d7b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java @@ -42,7 +42,6 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.annotation.IdRes; -import android.app.ActivityManager; import android.content.ContentResolver; import android.content.res.Configuration; import android.content.res.Resources; @@ -57,6 +56,7 @@ import android.util.DisplayMetrics; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; +import android.view.ViewGroup; import android.view.ViewParent; import android.view.ViewPropertyAnimator; import android.view.ViewStub; @@ -107,6 +107,7 @@ import com.android.systemui.navigationbar.NavigationModeController; import com.android.systemui.plugins.FalsingManager; import com.android.systemui.plugins.qs.QS; import com.android.systemui.qrcodescanner.controller.QRCodeScannerController; +import com.android.systemui.qs.QSFragment; import com.android.systemui.screenrecord.RecordingController; import com.android.systemui.shade.transition.ShadeTransitionController; import com.android.systemui.statusbar.CommandQueue; @@ -160,8 +161,6 @@ import com.android.systemui.statusbar.policy.KeyguardUserSwitcherController; import com.android.systemui.statusbar.policy.KeyguardUserSwitcherView; import com.android.systemui.statusbar.window.StatusBarWindowStateController; import com.android.systemui.unfold.SysUIUnfoldComponent; -import com.android.systemui.util.concurrency.FakeExecutor; -import com.android.systemui.util.settings.SecureSettings; import com.android.systemui.util.time.FakeSystemClock; import com.android.systemui.util.time.SystemClock; import com.android.systemui.wallet.controller.QuickAccessWalletController; @@ -184,226 +183,136 @@ import java.util.Optional; @TestableLooper.RunWithLooper public class NotificationPanelViewControllerTest extends SysuiTestCase { + private static final int SPLIT_SHADE_FULL_TRANSITION_DISTANCE = 400; private static final int NOTIFICATION_SCRIM_TOP_PADDING_IN_SPLIT_SHADE = 50; + private static final int PANEL_WIDTH = 500; // Random value just for the test. + + @Mock private CentralSurfaces mCentralSurfaces; + @Mock private NotificationStackScrollLayout mNotificationStackScrollLayout; + @Mock private KeyguardBottomAreaView mKeyguardBottomArea; + @Mock private KeyguardBottomAreaViewController mKeyguardBottomAreaViewController; + @Mock private KeyguardBottomAreaView mQsFrame; + @Mock private NotificationIconAreaController mNotificationAreaController; + @Mock private HeadsUpManagerPhone mHeadsUpManager; + @Mock private NotificationShelfController mNotificationShelfController; + @Mock private KeyguardStatusBarView mKeyguardStatusBar; + @Mock private KeyguardUserSwitcherView mUserSwitcherView; + @Mock private ViewStub mUserSwitcherStubView; + @Mock private HeadsUpTouchHelper.Callback mHeadsUpCallback; + @Mock private KeyguardUpdateMonitor mUpdateMonitor; + @Mock private KeyguardBypassController mKeyguardBypassController; + @Mock private DozeParameters mDozeParameters; + @Mock private ScreenOffAnimationController mScreenOffAnimationController; + @Mock private NotificationPanelView mView; + @Mock private LayoutInflater mLayoutInflater; + @Mock private FeatureFlags mFeatureFlags; + @Mock private DynamicPrivacyController mDynamicPrivacyController; + @Mock private StatusBarTouchableRegionManager mStatusBarTouchableRegionManager; + @Mock private KeyguardStateController mKeyguardStateController; + @Mock private DozeLog mDozeLog; + @Mock private ShadeLogger mShadeLog; + @Mock private CommandQueue mCommandQueue; + @Mock private VibratorHelper mVibratorHelper; + @Mock private LatencyTracker mLatencyTracker; + @Mock private PowerManager mPowerManager; + @Mock private AccessibilityManager mAccessibilityManager; + @Mock private MetricsLogger mMetricsLogger; + @Mock private Resources mResources; + @Mock private Configuration mConfiguration; + @Mock private KeyguardClockSwitch mKeyguardClockSwitch; + @Mock private MediaHierarchyManager mMediaHiearchyManager; + @Mock private ConversationNotificationManager mConversationNotificationManager; + @Mock private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; + @Mock private KeyguardStatusViewComponent.Factory mKeyguardStatusViewComponentFactory; + @Mock private KeyguardQsUserSwitchComponent.Factory mKeyguardQsUserSwitchComponentFactory; + @Mock private KeyguardQsUserSwitchComponent mKeyguardQsUserSwitchComponent; + @Mock private KeyguardQsUserSwitchController mKeyguardQsUserSwitchController; + @Mock private KeyguardUserSwitcherComponent.Factory mKeyguardUserSwitcherComponentFactory; + @Mock private KeyguardUserSwitcherComponent mKeyguardUserSwitcherComponent; + @Mock private KeyguardUserSwitcherController mKeyguardUserSwitcherController; + @Mock private KeyguardStatusViewComponent mKeyguardStatusViewComponent; + @Mock private KeyguardStatusBarViewComponent.Factory mKeyguardStatusBarViewComponentFactory; + @Mock private KeyguardStatusBarViewComponent mKeyguardStatusBarViewComponent; + @Mock private KeyguardClockSwitchController mKeyguardClockSwitchController; + @Mock private KeyguardStatusViewController mKeyguardStatusViewController; + @Mock private KeyguardStatusBarViewController mKeyguardStatusBarViewController; + @Mock private NotificationStackScrollLayoutController mNotificationStackScrollLayoutController; + @Mock private NotificationShadeDepthController mNotificationShadeDepthController; + @Mock private LockscreenShadeTransitionController mLockscreenShadeTransitionController; + @Mock private AuthController mAuthController; + @Mock private ScrimController mScrimController; + @Mock private MediaDataManager mMediaDataManager; + @Mock private AmbientState mAmbientState; + @Mock private UserManager mUserManager; + @Mock private UiEventLogger mUiEventLogger; + @Mock private LockIconViewController mLockIconViewController; + @Mock private KeyguardMediaController mKeyguardMediaController; + @Mock private PrivacyDotViewController mPrivacyDotViewController; + @Mock private NavigationModeController mNavigationModeController; + @Mock private LargeScreenShadeHeaderController mLargeScreenShadeHeaderController; + @Mock private ContentResolver mContentResolver; + @Mock private TapAgainViewController mTapAgainViewController; + @Mock private KeyguardIndicationController mKeyguardIndicationController; + @Mock private FragmentService mFragmentService; + @Mock private FragmentHostManager mFragmentHostManager; + @Mock private QuickAccessWalletController mQuickAccessWalletController; + @Mock private QRCodeScannerController mQrCodeScannerController; + @Mock private NotificationRemoteInputManager mNotificationRemoteInputManager; + @Mock private RecordingController mRecordingController; + @Mock private ControlsComponent mControlsComponent; + @Mock private LockscreenGestureLogger mLockscreenGestureLogger; + @Mock private DumpManager mDumpManager; + @Mock private InteractionJankMonitor mInteractionJankMonitor; + @Mock private NotificationsQSContainerController mNotificationsQSContainerController; + @Mock private QsFrameTranslateController mQsFrameTranslateController; + @Mock private StatusBarWindowStateController mStatusBarWindowStateController; + @Mock private KeyguardUnlockAnimationController mKeyguardUnlockAnimationController; + @Mock private NotificationShadeWindowController mNotificationShadeWindowController; + @Mock private SysUiState mSysUiState; + @Mock private NotificationListContainer mNotificationListContainer; + @Mock private NotificationStackSizeCalculator mNotificationStackSizeCalculator; + @Mock private UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController; + @Mock private ShadeTransitionController mShadeTransitionController; + @Mock private QS mQs; + @Mock private QSFragment mQSFragment; + @Mock private ViewGroup mQsHeader; + @Mock private ViewParent mViewParent; + @Mock private ViewTreeObserver mViewTreeObserver; + @Mock private KeyguardBottomAreaViewModel mKeyguardBottomAreaViewModel; + @Mock private KeyguardBottomAreaInteractor mKeyguardBottomAreaInteractor; - @Mock - private CentralSurfaces mCentralSurfaces; - @Mock - private NotificationStackScrollLayout mNotificationStackScrollLayout; - @Mock - private KeyguardBottomAreaView mKeyguardBottomArea; - @Mock - private KeyguardBottomAreaViewController mKeyguardBottomAreaViewController; - @Mock - private KeyguardBottomAreaView mQsFrame; - private KeyguardStatusView mKeyguardStatusView; - @Mock - private NotificationIconAreaController mNotificationAreaController; - @Mock - private HeadsUpManagerPhone mHeadsUpManager; - @Mock - private NotificationShelfController mNotificationShelfController; - @Mock - private KeyguardStatusBarView mKeyguardStatusBar; - @Mock - private KeyguardUserSwitcherView mUserSwitcherView; - @Mock - private ViewStub mUserSwitcherStubView; - @Mock - private HeadsUpTouchHelper.Callback mHeadsUpCallback; - @Mock - private KeyguardUpdateMonitor mUpdateMonitor; - @Mock - private KeyguardBypassController mKeyguardBypassController; - @Mock - private DozeParameters mDozeParameters; - @Mock - private ScreenOffAnimationController mScreenOffAnimationController; - @Mock - private NotificationPanelView mView; - @Mock - private LayoutInflater mLayoutInflater; - @Mock - private FeatureFlags mFeatureFlags; - @Mock - private DynamicPrivacyController mDynamicPrivacyController; - @Mock - private StatusBarTouchableRegionManager mStatusBarTouchableRegionManager; - @Mock - private KeyguardStateController mKeyguardStateController; - @Mock - private DozeLog mDozeLog; - @Mock - private ShadeLogger mShadeLog; - @Mock - private CommandQueue mCommandQueue; - @Mock - private VibratorHelper mVibratorHelper; - @Mock - private LatencyTracker mLatencyTracker; - @Mock - private PowerManager mPowerManager; - @Mock - private AccessibilityManager mAccessibilityManager; - @Mock - private MetricsLogger mMetricsLogger; - @Mock - private ActivityManager mActivityManager; - @Mock - private Resources mResources; - @Mock - private Configuration mConfiguration; - private DisplayMetrics mDisplayMetrics = new DisplayMetrics(); - @Mock - private KeyguardClockSwitch mKeyguardClockSwitch; private NotificationPanelViewController.TouchHandler mTouchHandler; private ConfigurationController mConfigurationController; - @Mock - private MediaHierarchyManager mMediaHiearchyManager; - @Mock - private ConversationNotificationManager mConversationNotificationManager; - @Mock - private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; - @Mock - private KeyguardStatusViewComponent.Factory mKeyguardStatusViewComponentFactory; - @Mock - private KeyguardQsUserSwitchComponent.Factory mKeyguardQsUserSwitchComponentFactory; - @Mock - private KeyguardQsUserSwitchComponent mKeyguardQsUserSwitchComponent; - @Mock - private KeyguardQsUserSwitchController mKeyguardQsUserSwitchController; - @Mock - private KeyguardUserSwitcherComponent.Factory mKeyguardUserSwitcherComponentFactory; - @Mock - private KeyguardUserSwitcherComponent mKeyguardUserSwitcherComponent; - @Mock - private KeyguardUserSwitcherController mKeyguardUserSwitcherController; - @Mock - private KeyguardStatusViewComponent mKeyguardStatusViewComponent; - @Mock - private KeyguardStatusBarViewComponent.Factory mKeyguardStatusBarViewComponentFactory; - @Mock - private KeyguardStatusBarViewComponent mKeyguardStatusBarViewComponent; - @Mock - private KeyguardClockSwitchController mKeyguardClockSwitchController; - @Mock - private KeyguardStatusViewController mKeyguardStatusViewController; - @Mock - private KeyguardStatusBarViewController mKeyguardStatusBarViewController; - @Mock - private NotificationStackScrollLayoutController mNotificationStackScrollLayoutController; - @Mock - private NotificationShadeDepthController mNotificationShadeDepthController; - @Mock - private LockscreenShadeTransitionController mLockscreenShadeTransitionController; - @Mock - private AuthController mAuthController; - @Mock - private ScrimController mScrimController; - @Mock - private MediaDataManager mMediaDataManager; - @Mock - private AmbientState mAmbientState; - @Mock - private UserManager mUserManager; - @Mock - private UiEventLogger mUiEventLogger; - @Mock - private LockIconViewController mLockIconViewController; - @Mock - private KeyguardMediaController mKeyguardMediaController; - @Mock - private PrivacyDotViewController mPrivacyDotViewController; - @Mock - private NavigationModeController mNavigationModeController; - @Mock - private SecureSettings mSecureSettings; - @Mock - private LargeScreenShadeHeaderController mLargeScreenShadeHeaderController; - @Mock - private ContentResolver mContentResolver; - @Mock - private TapAgainViewController mTapAgainViewController; - @Mock - private KeyguardIndicationController mKeyguardIndicationController; - @Mock - private FragmentService mFragmentService; - @Mock - private FragmentHostManager mFragmentHostManager; - @Mock - private QuickAccessWalletController mQuickAccessWalletController; - @Mock - private QRCodeScannerController mQrCodeScannerController; - @Mock - private NotificationRemoteInputManager mNotificationRemoteInputManager; - @Mock - private RecordingController mRecordingController; - @Mock - private ControlsComponent mControlsComponent; - @Mock - private LockscreenGestureLogger mLockscreenGestureLogger; - @Mock - private DumpManager mDumpManager; - @Mock - private InteractionJankMonitor mInteractionJankMonitor; - @Mock - private NotificationsQSContainerController mNotificationsQSContainerController; - @Mock - private QsFrameTranslateController mQsFrameTranslateController; - @Mock - private StatusBarWindowStateController mStatusBarWindowStateController; - @Mock - private KeyguardUnlockAnimationController mKeyguardUnlockAnimationController; - @Mock - private NotificationShadeWindowController mNotificationShadeWindowController; - @Mock - private SysUiState mSysUiState; - @Mock - private NotificationListContainer mNotificationListContainer; - @Mock - private NotificationStackSizeCalculator mNotificationStackSizeCalculator; - @Mock - private UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController; - @Mock - private ShadeTransitionController mShadeTransitionController; - @Mock - private QS mQs; - @Mock - private View mQsHeader; - @Mock - private ViewParent mViewParent; - @Mock - private ViewTreeObserver mViewTreeObserver; - @Mock private KeyguardBottomAreaViewModel mKeyguardBottomAreaViewModel; - @Mock private KeyguardBottomAreaInteractor mKeyguardBottomAreaInteractor; - private NotificationPanelViewController.PanelEventsEmitter mPanelEventsEmitter; - private Optional<SysUIUnfoldComponent> mSysUIUnfoldComponent = Optional.empty(); private SysuiStatusBarStateController mStatusBarStateController; private NotificationPanelViewController mNotificationPanelViewController; private View.AccessibilityDelegate mAccessibiltyDelegate; private NotificationsQuickSettingsContainer mNotificationContainerParent; private List<View.OnAttachStateChangeListener> mOnAttachStateChangeListeners; - private FalsingManagerFake mFalsingManager = new FalsingManagerFake(); - private FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock()); private Handler mMainHandler; + private View.OnLayoutChangeListener mLayoutChangeListener; + + private final FalsingManagerFake mFalsingManager = new FalsingManagerFake(); + private final Optional<SysUIUnfoldComponent> mSysUIUnfoldComponent = Optional.empty(); + private final DisplayMetrics mDisplayMetrics = new DisplayMetrics(); private final PanelExpansionStateManager mPanelExpansionStateManager = new PanelExpansionStateManager(); - private SystemClock mSystemClock; + private FragmentHostManager.FragmentListener mFragmentListener; @Before public void setup() { MockitoAnnotations.initMocks(this); - mSystemClock = new FakeSystemClock(); + SystemClock systemClock = new FakeSystemClock(); mStatusBarStateController = new StatusBarStateControllerImpl(mUiEventLogger, mDumpManager, mInteractionJankMonitor); - mKeyguardStatusView = new KeyguardStatusView(mContext); - mKeyguardStatusView.setId(R.id.keyguard_status_view); + KeyguardStatusView keyguardStatusView = new KeyguardStatusView(mContext); + keyguardStatusView.setId(R.id.keyguard_status_view); DejankUtils.setImmediate(true); when(mAuthController.isUdfpsEnrolled(anyInt())).thenReturn(false); when(mHeadsUpCallback.getContext()).thenReturn(mContext); when(mView.getResources()).thenReturn(mResources); + when(mView.getWidth()).thenReturn(PANEL_WIDTH); when(mResources.getConfiguration()).thenReturn(mConfiguration); mConfiguration.orientation = ORIENTATION_PORTRAIT; when(mResources.getDisplayMetrics()).thenReturn(mDisplayMetrics); @@ -413,6 +322,8 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { .thenReturn(NOTIFICATION_SCRIM_TOP_PADDING_IN_SPLIT_SHADE); when(mResources.getDimensionPixelSize(R.dimen.notification_panel_margin_horizontal)) .thenReturn(10); + when(mResources.getDimensionPixelSize(R.dimen.split_shade_full_transition_distance)) + .thenReturn(SPLIT_SHADE_FULL_TRANSITION_DISTANCE); when(mView.getContext()).thenReturn(getContext()); when(mView.findViewById(R.id.keyguard_header)).thenReturn(mKeyguardStatusBar); when(mView.findViewById(R.id.keyguard_user_switcher_view)).thenReturn(mUserSwitcherView); @@ -431,7 +342,7 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { when(mView.findViewById(R.id.keyguard_status_view)) .thenReturn(mock(KeyguardStatusView.class)); mNotificationContainerParent = new NotificationsQuickSettingsContainer(getContext(), null); - mNotificationContainerParent.addView(mKeyguardStatusView); + mNotificationContainerParent.addView(keyguardStatusView); mNotificationContainerParent.onFinishInflate(); when(mView.findViewById(R.id.notification_container_parent)) .thenReturn(mNotificationContainerParent); @@ -447,7 +358,12 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { when(mKeyguardUserSwitcherComponent.getKeyguardUserSwitcherController()) .thenReturn(mKeyguardUserSwitcherController); when(mScreenOffAnimationController.shouldAnimateClockChange()).thenReturn(true); - + when(mQs.getView()).thenReturn(mView); + when(mQSFragment.getView()).thenReturn(mView); + doAnswer(invocation -> { + mFragmentListener = invocation.getArgument(1); + return null; + }).when(mFragmentHostManager).addTagListener(eq(QS.TAG), any()); doAnswer((Answer<Void>) invocation -> { mTouchHandler = invocation.getArgument(0); return null; @@ -484,7 +400,7 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { when(mKeyguardStatusBarViewComponent.getKeyguardStatusBarViewController()) .thenReturn(mKeyguardStatusBarViewController); when(mLayoutInflater.inflate(eq(R.layout.keyguard_status_view), any(), anyBoolean())) - .thenReturn(mKeyguardStatusView); + .thenReturn(keyguardStatusView); when(mLayoutInflater.inflate(eq(R.layout.keyguard_user_switcher), any(), anyBoolean())) .thenReturn(mUserSwitcherView); when(mLayoutInflater.inflate(eq(R.layout.keyguard_bottom_area), any(), anyBoolean())) @@ -499,13 +415,18 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { ((Runnable) invocation.getArgument(0)).run(); return null; }).when(mNotificationShadeWindowController).batchApplyWindowLayoutParams(any()); + doAnswer(invocation -> { + mLayoutChangeListener = invocation.getArgument(0); + return null; + }).when(mView).addOnLayoutChangeListener(any()); when(mView.getViewTreeObserver()).thenReturn(mViewTreeObserver); when(mView.getParent()).thenReturn(mViewParent); when(mQs.getHeader()).thenReturn(mQsHeader); mMainHandler = new Handler(Looper.getMainLooper()); - mPanelEventsEmitter = new NotificationPanelViewController.PanelEventsEmitter(); + NotificationPanelViewController.PanelEventsEmitter panelEventsEmitter = + new NotificationPanelViewController.PanelEventsEmitter(); mNotificationPanelViewController = new NotificationPanelViewController( mView, @@ -547,8 +468,6 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { mNavigationModeController, mFragmentService, mContentResolver, - mQuickAccessWalletController, - mQrCodeScannerController, mRecordingController, mLargeScreenShadeHeaderController, mScreenOffAnimationController, @@ -556,21 +475,20 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { mPanelExpansionStateManager, mNotificationRemoteInputManager, mSysUIUnfoldComponent, - mControlsComponent, mInteractionJankMonitor, mQsFrameTranslateController, mSysUiState, () -> mKeyguardBottomAreaViewController, mKeyguardUnlockAnimationController, mNotificationListContainer, - mPanelEventsEmitter, + panelEventsEmitter, mNotificationStackSizeCalculator, mUnlockedScreenOffAnimationController, mShadeTransitionController, - mSystemClock, + systemClock, mock(CameraGestureHelper.class), - () -> mKeyguardBottomAreaViewModel, - () -> mKeyguardBottomAreaInteractor); + mKeyguardBottomAreaViewModel, + mKeyguardBottomAreaInteractor); mNotificationPanelViewController.initDependencies( mCentralSurfaces, () -> {}, @@ -751,8 +669,9 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { } @Test - public void testSetPanelScrimMinFraction() { - mNotificationPanelViewController.setPanelScrimMinFraction(0.5f); + public void testSetPanelScrimMinFractionWhenHeadsUpIsDragged() { + mNotificationPanelViewController.setHeadsUpDraggingStartingHeight( + mNotificationPanelViewController.getMaxPanelHeight() / 2); verify(mNotificationShadeDepthController).setPanelPullDownMinFraction(eq(0.5f)); } @@ -1103,7 +1022,7 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { FalsingManager.FalsingTapListener listener = getFalsingTapListener(); mStatusBarStateController.setState(KEYGUARD); - listener.onDoubleTapRequired(); + listener.onAdditionalTapRequired(); verify(mKeyguardIndicationController).showTransientIndication(anyInt()); } @@ -1113,7 +1032,7 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { FalsingManager.FalsingTapListener listener = getFalsingTapListener(); mStatusBarStateController.setState(SHADE_LOCKED); - listener.onDoubleTapRequired(); + listener.onAdditionalTapRequired(); verify(mTapAgainViewController).show(); } @@ -1448,40 +1367,137 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { } @Test - public void getMaxPanelHeight_expanding_inSplitShade_returnsSplitShadeFullTransitionDistance() { - int splitShadeFullTransitionDistance = 123456; + public void getMaxPanelTransitionDistance_expanding_inSplitShade_returnsSplitShadeFullTransitionDistance() { + enableSplitShade(true); + mNotificationPanelViewController.expandWithQs(); + + int maxDistance = mNotificationPanelViewController.getMaxPanelTransitionDistance(); + + assertThat(maxDistance).isEqualTo(SPLIT_SHADE_FULL_TRANSITION_DISTANCE); + } + + @Test + public void getMaxPanelTransitionDistance_inSplitShade_withHeadsUp_returnsBiggerValue() { enableSplitShade(true); - setSplitShadeFullTransitionDistance(splitShadeFullTransitionDistance); mNotificationPanelViewController.expandWithQs(); + when(mHeadsUpManager.isTrackingHeadsUp()).thenReturn(true); + mNotificationPanelViewController.setHeadsUpDraggingStartingHeight( + SPLIT_SHADE_FULL_TRANSITION_DISTANCE); - int maxPanelHeight = mNotificationPanelViewController.getMaxPanelHeight(); + int maxDistance = mNotificationPanelViewController.getMaxPanelTransitionDistance(); - assertThat(maxPanelHeight).isEqualTo(splitShadeFullTransitionDistance); + assertThat(maxDistance).isGreaterThan(SPLIT_SHADE_FULL_TRANSITION_DISTANCE); } @Test - public void getMaxPanelHeight_expandingSplitShade_keyguard_returnsNonSplitShadeValue() { + public void getMaxPanelTransitionDistance_expandingSplitShade_keyguard_returnsNonSplitShadeValue() { mStatusBarStateController.setState(KEYGUARD); - int splitShadeFullTransitionDistance = 123456; enableSplitShade(true); - setSplitShadeFullTransitionDistance(splitShadeFullTransitionDistance); mNotificationPanelViewController.expandWithQs(); - int maxPanelHeight = mNotificationPanelViewController.getMaxPanelHeight(); + int maxDistance = mNotificationPanelViewController.getMaxPanelTransitionDistance(); - assertThat(maxPanelHeight).isNotEqualTo(splitShadeFullTransitionDistance); + assertThat(maxDistance).isNotEqualTo(SPLIT_SHADE_FULL_TRANSITION_DISTANCE); } @Test - public void getMaxPanelHeight_expanding_notSplitShade_returnsNonSplitShadeValue() { - int splitShadeFullTransitionDistance = 123456; + public void getMaxPanelTransitionDistance_expanding_notSplitShade_returnsNonSplitShadeValue() { enableSplitShade(false); - setSplitShadeFullTransitionDistance(splitShadeFullTransitionDistance); mNotificationPanelViewController.expandWithQs(); - int maxPanelHeight = mNotificationPanelViewController.getMaxPanelHeight(); + int maxDistance = mNotificationPanelViewController.getMaxPanelTransitionDistance(); - assertThat(maxPanelHeight).isNotEqualTo(splitShadeFullTransitionDistance); + assertThat(maxDistance).isNotEqualTo(SPLIT_SHADE_FULL_TRANSITION_DISTANCE); + } + + @Test + public void onLayoutChange_fullWidth_updatesQSWithFullWithTrue() { + mNotificationPanelViewController.mQs = mQs; + + setIsFullWidth(true); + + verify(mQs).setIsNotificationPanelFullWidth(true); + } + + @Test + public void onLayoutChange_notFullWidth_updatesQSWithFullWithFalse() { + mNotificationPanelViewController.mQs = mQs; + + setIsFullWidth(false); + + verify(mQs).setIsNotificationPanelFullWidth(false); + } + + @Test + public void onLayoutChange_qsNotSet_doesNotCrash() { + mNotificationPanelViewController.mQs = null; + + triggerLayoutChange(); + } + + @Test + public void onQsFragmentAttached_fullWidth_setsFullWidthTrueOnQS() { + setIsFullWidth(true); + givenViewAttached(); + mFragmentListener.onFragmentViewCreated(QS.TAG, mQSFragment); + + verify(mQSFragment).setIsNotificationPanelFullWidth(true); + } + + @Test + public void onQsFragmentAttached_notFullWidth_setsFullWidthFalseOnQS() { + setIsFullWidth(false); + givenViewAttached(); + mFragmentListener.onFragmentViewCreated(QS.TAG, mQSFragment); + + verify(mQSFragment).setIsNotificationPanelFullWidth(false); + } + + @Test + public void setQsExpansion_lockscreenShadeTransitionInProgress_usesLockscreenSquishiness() { + float squishinessFraction = 0.456f; + mNotificationPanelViewController.mQs = mQs; + when(mLockscreenShadeTransitionController.getQsSquishTransitionFraction()) + .thenReturn(squishinessFraction); + when(mNotificationStackScrollLayoutController.getNotificationSquishinessFraction()) + .thenReturn(0.987f); + // Call setTransitionToFullShadeAmount to get into the full shade transition in progress + // state. + mNotificationPanelViewController.setTransitionToFullShadeAmount( + /* pxAmount= */ 234, + /* animate= */ false, + /* delay= */ 0 + ); + + mNotificationPanelViewController.setQsExpansion(/* height= */ 123); + + // First for setTransitionToFullShadeAmount and then setQsExpansion + verify(mQs, times(2)).setQsExpansion( + /* expansion= */ anyFloat(), + /* panelExpansionFraction= */ anyFloat(), + /* proposedTranslation= */ anyFloat(), + eq(squishinessFraction) + ); + } + + @Test + public void setQsExpansion_lockscreenShadeTransitionNotInProgress_usesStandardSquishiness() { + float lsSquishinessFraction = 0.456f; + float nsslSquishinessFraction = 0.987f; + mNotificationPanelViewController.mQs = mQs; + when(mLockscreenShadeTransitionController.getQsSquishTransitionFraction()) + .thenReturn(lsSquishinessFraction); + when(mNotificationStackScrollLayoutController.getNotificationSquishinessFraction()) + .thenReturn(nsslSquishinessFraction); + + mNotificationPanelViewController.setQsExpansion(/* height= */ 123); + + verify(mQs).setQsExpansion( + /* expansion= */ anyFloat(), + /* panelExpansionFraction= */ anyFloat(), + /* proposedTranslation= */ anyFloat(), + eq(nsslSquishinessFraction) + ); } private static MotionEvent createMotionEvent(int x, int y, int action) { @@ -1507,12 +1523,6 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { } } - private void givenViewDetached() { - for (View.OnAttachStateChangeListener listener : mOnAttachStateChangeListeners) { - listener.onViewDetachedFromWindow(mView); - } - } - private ConstraintSet.Layout getConstraintSetLayout(@IdRes int id) { ConstraintSet constraintSet = new ConstraintSet(); constraintSet.clone(mNotificationContainerParent); @@ -1544,12 +1554,6 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { mTouchHandler.onTouch(mView, ev); } - private void setSplitShadeFullTransitionDistance(int splitShadeFullTransitionDistance) { - when(mResources.getDimensionPixelSize(R.dimen.split_shade_full_transition_distance)) - .thenReturn(splitShadeFullTransitionDistance); - mNotificationPanelViewController.updateResources(); - } - private void setDozing(boolean dozing, boolean dozingAlwaysOn) { when(mDozeParameters.getAlwaysOn()).thenReturn(dozingAlwaysOn); mNotificationPanelViewController.setDozing( @@ -1569,4 +1573,24 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase { assertThat(getConstraintSetLayout(R.id.keyguard_status_view).endToEnd).isEqualTo( R.id.qs_edge_guideline); } + + private void setIsFullWidth(boolean fullWidth) { + float nsslWidth = fullWidth ? PANEL_WIDTH : PANEL_WIDTH / 2f; + when(mNotificationStackScrollLayoutController.getWidth()).thenReturn(nsslWidth); + triggerLayoutChange(); + } + + private void triggerLayoutChange() { + mLayoutChangeListener.onLayoutChange( + mView, + /* left= */ 0, + /* top= */ 0, + /* right= */ 0, + /* bottom= */ 0, + /* oldLeft= */ 0, + /* oldTop= */ 0, + /* oldRight= */ 0, + /* oldBottom= */ 0 + ); + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationQSContainerControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationQSContainerControllerTest.kt index 0c6a6a98052f..12ef036d89d0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationQSContainerControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationQSContainerControllerTest.kt @@ -20,6 +20,7 @@ import com.android.systemui.recents.OverviewProxyService.OverviewProxyListener import com.android.systemui.util.concurrency.FakeExecutor import com.android.systemui.util.time.FakeSystemClock import com.google.common.truth.Truth.assertThat +import java.util.function.Consumer import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -33,10 +34,10 @@ import org.mockito.Mockito.doNothing import org.mockito.Mockito.eq import org.mockito.Mockito.mock import org.mockito.Mockito.never +import org.mockito.Mockito.reset import org.mockito.Mockito.verify -import org.mockito.MockitoAnnotations -import java.util.function.Consumer import org.mockito.Mockito.`when` as whenever +import org.mockito.MockitoAnnotations @SmallTest @RunWith(AndroidTestingRunner::class) @@ -63,6 +64,8 @@ class NotificationQSContainerControllerTest : SysuiTestCase() { @Mock private lateinit var notificationsQSContainer: NotificationsQuickSettingsContainer @Mock + private lateinit var largeScreenShadeHeaderController: LargeScreenShadeHeaderController + @Mock private lateinit var featureFlags: FeatureFlags @Captor lateinit var navigationModeCaptor: ArgumentCaptor<ModeChangedListener> @@ -92,6 +95,7 @@ class NotificationQSContainerControllerTest : SysuiTestCase() { notificationsQSContainer, navigationModeController, overviewProxyService, + largeScreenShadeHeaderController, featureFlags, delayableExecutor ) @@ -371,8 +375,14 @@ class NotificationQSContainerControllerTest : SysuiTestCase() { container.removeAllViews() container.addView(newViewWithId(1)) container.addView(newViewWithId(View.NO_ID)) - val controller = NotificationsQSContainerController(container, navigationModeController, - overviewProxyService, featureFlags, delayableExecutor) + val controller = NotificationsQSContainerController( + container, + navigationModeController, + overviewProxyService, + largeScreenShadeHeaderController, + featureFlags, + delayableExecutor + ) controller.updateConstraints() assertThat(container.getChildAt(0).id).isEqualTo(1) @@ -397,6 +407,21 @@ class NotificationQSContainerControllerTest : SysuiTestCase() { verify(notificationsQSContainer).setQSContainerPaddingBottom(STABLE_INSET_BOTTOM) } + @Test + fun testStartCustomizingWithDuration() { + controller.setCustomizerShowing(true, 100L) + verify(largeScreenShadeHeaderController).startCustomizingAnimation(true, 100L) + } + + @Test + fun testEndCustomizingWithDuration() { + controller.setCustomizerShowing(true, 0L) // Only tracks changes + reset(largeScreenShadeHeaderController) + + controller.setCustomizerShowing(false, 100L) + verify(largeScreenShadeHeaderController).startCustomizingAnimation(false, 100L) + } + private fun disableSplitShade() { setSplitShadeEnabled(false) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt index 43fc8983011d..2adc389a964e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationShadeWindowViewControllerTest.kt @@ -19,8 +19,10 @@ package com.android.systemui.shade import android.testing.AndroidTestingRunner import android.testing.TestableLooper.RunWithLooper import android.view.MotionEvent +import android.view.ViewGroup import androidx.test.filters.SmallTest import com.android.keyguard.LockIconViewController +import com.android.systemui.R import com.android.systemui.SysuiTestCase import com.android.systemui.classifier.FalsingCollectorFake import com.android.systemui.dock.DockManager @@ -246,6 +248,18 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() { verify(phoneStatusBarViewController).sendTouchToView(nextEvent) assertThat(returnVal).isTrue() } + + @Test + fun testGetBouncerContainer() { + underTest.bouncerContainer + verify(view).findViewById<ViewGroup>(R.id.keyguard_bouncer_container) + } + + @Test + fun testGetKeyguardMessageArea() { + underTest.keyguardMessageArea + verify(view).findViewById<ViewGroup>(R.id.keyguard_message_area) + } } private val downEv = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0) diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/PulsingGestureListenerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/PulsingGestureListenerTest.kt index d2970a63a860..09add652483e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/PulsingGestureListenerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/PulsingGestureListenerTest.kt @@ -27,6 +27,7 @@ import com.android.systemui.SysuiTestCase import com.android.systemui.dock.DockManager import com.android.systemui.dump.DumpManager import com.android.systemui.plugins.FalsingManager +import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.statusbar.phone.CentralSurfaces import com.android.systemui.tuner.TunerService import com.android.systemui.tuner.TunerService.Tunable @@ -63,6 +64,8 @@ class PulsingGestureListenerTest : SysuiTestCase() { private lateinit var tunerService: TunerService @Mock private lateinit var dumpManager: DumpManager + @Mock + private lateinit var statusBarStateController: StatusBarStateController private lateinit var tunableCaptor: ArgumentCaptor<Tunable> private lateinit var underTest: PulsingGestureListener @@ -77,6 +80,7 @@ class PulsingGestureListenerTest : SysuiTestCase() { dockManager, centralSurfaces, ambientDisplayConfiguration, + statusBarStateController, tunerService, dumpManager ) @@ -85,6 +89,8 @@ class PulsingGestureListenerTest : SysuiTestCase() { @Test fun testGestureDetector_singleTapEnabled() { + whenever(statusBarStateController.isDozing).thenReturn(true) + // GIVEN tap is enabled, prox not covered whenever(ambientDisplayConfiguration.tapGestureEnabled(anyInt())).thenReturn(true) updateSettings() @@ -94,7 +100,7 @@ class PulsingGestureListenerTest : SysuiTestCase() { whenever(falsingManager.isFalseTap(anyInt())).thenReturn(false) // WHEN there's a tap - underTest.onSingleTapConfirmed(downEv) + underTest.onSingleTapUp(upEv) // THEN wake up device if dozing verify(centralSurfaces).wakeUpIfDozing(anyLong(), anyObject(), anyString()) @@ -102,6 +108,8 @@ class PulsingGestureListenerTest : SysuiTestCase() { @Test fun testGestureDetector_doubleTapEnabled() { + whenever(statusBarStateController.isDozing).thenReturn(true) + // GIVEN double tap is enabled, prox not covered whenever(ambientDisplayConfiguration.doubleTapGestureEnabled(anyInt())).thenReturn(true) updateSettings() @@ -111,14 +119,28 @@ class PulsingGestureListenerTest : SysuiTestCase() { whenever(falsingManager.isFalseDoubleTap).thenReturn(false) // WHEN there's a double tap - underTest.onDoubleTap(downEv) + underTest.onDoubleTapEvent(upEv) // THEN wake up device if dozing verify(centralSurfaces).wakeUpIfDozing(anyLong(), anyObject(), anyString()) } @Test + fun testGestureDetector_doubleTapEnabled_onDownEvent_noFalsingCheck() { + // GIVEN tap is enabled + whenever(ambientDisplayConfiguration.tapGestureEnabled(anyInt())).thenReturn(true) + + // WHEN there's a double tap on DOWN event + underTest.onDoubleTapEvent(downEv) + + // THEN don't check the falsing manager, should only be checked on the UP event + verify(falsingManager, never()).isFalseDoubleTap() + } + + @Test fun testGestureDetector_singleTapEnabled_falsing() { + whenever(statusBarStateController.isDozing).thenReturn(true) + // GIVEN tap is enabled, prox not covered whenever(ambientDisplayConfiguration.tapGestureEnabled(anyInt())).thenReturn(true) updateSettings() @@ -128,14 +150,44 @@ class PulsingGestureListenerTest : SysuiTestCase() { whenever(falsingManager.isFalseTap(anyInt())).thenReturn(true) // WHEN there's a tap - underTest.onSingleTapConfirmed(downEv) + underTest.onSingleTapUp(upEv) // THEN the device doesn't wake up verify(centralSurfaces, never()).wakeUpIfDozing(anyLong(), anyObject(), anyString()) } @Test + fun testSingleTap_notDozing_noFalsingCheck() { + whenever(statusBarStateController.isDozing).thenReturn(false) + + // GIVEN tap is enabled + whenever(ambientDisplayConfiguration.tapGestureEnabled(anyInt())).thenReturn(true) + // WHEN there's a tap + underTest.onSingleTapUp(upEv) + + // THEN the falsing manager never gets a call (because the device wasn't dozing + // during the tap) + verify(falsingManager, never()).isFalseTap(anyInt()) + } + + @Test + fun testDoubleTap_notDozing_noFalsingCheck() { + whenever(statusBarStateController.isDozing).thenReturn(false) + + // GIVEN tap is enabled + whenever(ambientDisplayConfiguration.tapGestureEnabled(anyInt())).thenReturn(true) + // WHEN there's a tap + underTest.onDoubleTapEvent(upEv) + + // THEN the falsing manager never gets a call (because the device wasn't dozing + // during the tap) + verify(falsingManager, never()).isFalseTap(anyInt()) + } + + @Test fun testGestureDetector_doubleTapEnabled_falsing() { + whenever(statusBarStateController.isDozing).thenReturn(true) + // GIVEN double tap is enabled, prox not covered whenever(ambientDisplayConfiguration.doubleTapGestureEnabled(anyInt())).thenReturn(true) updateSettings() @@ -144,8 +196,8 @@ class PulsingGestureListenerTest : SysuiTestCase() { // GIVEN the falsing manager thinks the tap is a false tap whenever(falsingManager.isFalseDoubleTap).thenReturn(true) - // WHEN there's a tap - underTest.onDoubleTap(downEv) + // WHEN there's a double tap ACTION_UP event + underTest.onDoubleTapEvent(upEv) // THEN the device doesn't wake up verify(centralSurfaces, never()).wakeUpIfDozing(anyLong(), anyObject(), anyString()) @@ -153,6 +205,8 @@ class PulsingGestureListenerTest : SysuiTestCase() { @Test fun testGestureDetector_singleTapEnabled_proxCovered() { + whenever(statusBarStateController.isDozing).thenReturn(true) + // GIVEN tap is enabled, not a false tap based on classifiers whenever(ambientDisplayConfiguration.tapGestureEnabled(anyInt())).thenReturn(true) updateSettings() @@ -162,7 +216,7 @@ class PulsingGestureListenerTest : SysuiTestCase() { whenever(falsingManager.isProximityNear()).thenReturn(true) // WHEN there's a tap - underTest.onSingleTapConfirmed(downEv) + underTest.onSingleTapUp(upEv) // THEN the device doesn't wake up verify(centralSurfaces, never()).wakeUpIfDozing(anyLong(), anyObject(), anyString()) @@ -170,6 +224,8 @@ class PulsingGestureListenerTest : SysuiTestCase() { @Test fun testGestureDetector_doubleTapEnabled_proxCovered() { + whenever(statusBarStateController.isDozing).thenReturn(true) + // GIVEN double tap is enabled, not a false tap based on classifiers whenever(ambientDisplayConfiguration.doubleTapGestureEnabled(anyInt())).thenReturn(true) updateSettings() @@ -179,7 +235,7 @@ class PulsingGestureListenerTest : SysuiTestCase() { whenever(falsingManager.isProximityNear()).thenReturn(true) // WHEN there's a tap - underTest.onDoubleTap(downEv) + underTest.onDoubleTapEvent(upEv) // THEN the device doesn't wake up verify(centralSurfaces, never()).wakeUpIfDozing(anyLong(), anyObject(), anyString()) @@ -197,3 +253,4 @@ class PulsingGestureListenerTest : SysuiTestCase() { } private val downEv = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, 0f, 0) +private val upEv = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_UP, 0f, 0f, 0) diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/transition/ScrimShadeTransitionControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/transition/ScrimShadeTransitionControllerTest.kt index baaa447d53a3..6be76a6ac969 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/shade/transition/ScrimShadeTransitionControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/shade/transition/ScrimShadeTransitionControllerTest.kt @@ -13,6 +13,7 @@ import com.android.systemui.statusbar.phone.panelstate.STATE_CLOSED import com.android.systemui.statusbar.phone.panelstate.STATE_OPEN import com.android.systemui.statusbar.phone.panelstate.STATE_OPENING import com.android.systemui.statusbar.policy.FakeConfigurationController +import com.android.systemui.statusbar.policy.HeadsUpManager import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -28,6 +29,7 @@ class ScrimShadeTransitionControllerTest : SysuiTestCase() { @Mock private lateinit var scrimController: ScrimController @Mock private lateinit var dumpManager: DumpManager @Mock private lateinit var statusBarStateController: SysuiStatusBarStateController + @Mock private lateinit var headsUpManager: HeadsUpManager private val configurationController = FakeConfigurationController() private lateinit var controller: ScrimShadeTransitionController @@ -42,7 +44,8 @@ class ScrimShadeTransitionControllerTest : SysuiTestCase() { dumpManager, scrimController, context.resources, - statusBarStateController) + statusBarStateController, + headsUpManager) controller.onPanelStateChanged(STATE_OPENING) } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java index 798f47d2d6cb..945cf7f8774f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java @@ -19,7 +19,10 @@ package com.android.systemui.statusbar; import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_DEFAULT; import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_FINANCED; import static android.content.pm.UserInfo.FLAG_MANAGED_PROFILE; +import static android.hardware.biometrics.BiometricFaceConstants.FACE_ACQUIRED_TOO_DARK; +import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_TIMEOUT; +import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_HELP_FACE_NOT_RECOGNIZED; import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED; import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_ALIGNMENT; import static com.android.systemui.keyguard.KeyguardIndicationRotateTextViewController.INDICATION_TYPE_BATTERY; @@ -65,7 +68,6 @@ import android.content.pm.UserInfo; import android.graphics.Color; import android.hardware.biometrics.BiometricFaceConstants; import android.hardware.biometrics.BiometricSourceType; -import android.hardware.face.FaceManager; import android.hardware.fingerprint.FingerprintManager; import android.os.BatteryManager; import android.os.Looper; @@ -86,6 +88,7 @@ import com.android.keyguard.KeyguardUpdateMonitorCallback; import com.android.settingslib.fuelgauge.BatteryStatus; import com.android.systemui.R; import com.android.systemui.SysuiTestCase; +import com.android.systemui.biometrics.FaceHelpMessageDeferral; import com.android.systemui.broadcast.BroadcastDispatcher; import com.android.systemui.dock.DockManager; import com.android.systemui.keyguard.KeyguardIndication; @@ -167,6 +170,8 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase { @Mock private AccessibilityManager mAccessibilityManager; @Mock + private FaceHelpMessageDeferral mFaceHelpMessageDeferral; + @Mock private ScreenLifecycle mScreenLifecycle; @Captor private ArgumentCaptor<DockManager.AlignmentStateListener> mAlignmentListener; @@ -259,7 +264,8 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase { mKeyguardStateController, mStatusBarStateController, mKeyguardUpdateMonitor, mDockManager, mBroadcastDispatcher, mDevicePolicyManager, mIBatteryStats, mUserManager, mExecutor, mExecutor, mFalsingManager, mLockPatternUtils, - mScreenLifecycle, mKeyguardBypassController, mAccessibilityManager); + mScreenLifecycle, mKeyguardBypassController, mAccessibilityManager, + mFaceHelpMessageDeferral); mController.init(); mController.setIndicationArea(mIndicationArea); verify(mStatusBarStateController).addCallback(mStatusBarStateListenerCaptor.capture()); @@ -535,7 +541,7 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase { mController.setVisible(true); mController.getKeyguardCallback().onBiometricHelp( - KeyguardUpdateMonitor.BIOMETRIC_HELP_FACE_NOT_RECOGNIZED, message, + BIOMETRIC_HELP_FACE_NOT_RECOGNIZED, message, BiometricSourceType.FACE); verifyIndicationMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE, message); reset(mRotateTextViewController); @@ -582,7 +588,7 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase { // WHEN there's a face not recognized message mController.getKeyguardCallback().onBiometricHelp( - KeyguardUpdateMonitor.BIOMETRIC_HELP_FACE_NOT_RECOGNIZED, + BIOMETRIC_HELP_FACE_NOT_RECOGNIZED, message, BiometricSourceType.FACE); @@ -602,7 +608,7 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase { String message = mContext.getString(R.string.keyguard_unlock); mController.setVisible(true); - mController.getKeyguardCallback().onBiometricError(FaceManager.FACE_ERROR_TIMEOUT, + mController.getKeyguardCallback().onBiometricError(FACE_ERROR_TIMEOUT, "A message", BiometricSourceType.FACE); verifyIndicationMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE, message); @@ -636,10 +642,10 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase { when(mKeyguardUpdateMonitor.isFaceEnrolled()).thenReturn(true); mController.setVisible(true); - mController.getKeyguardCallback().onBiometricError(FaceManager.FACE_ERROR_TIMEOUT, + mController.getKeyguardCallback().onBiometricError(FACE_ERROR_TIMEOUT, "A message", BiometricSourceType.FACE); - verify(mStatusBarKeyguardViewManager).showBouncerMessage(eq(message), any()); + verify(mStatusBarKeyguardViewManager).setKeyguardMessage(eq(message), any()); } @Test @@ -651,7 +657,7 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase { mController.setVisible(true); mController.getKeyguardCallback().onBiometricError( - FaceManager.FACE_ERROR_TIMEOUT, message, BiometricSourceType.FACE); + FACE_ERROR_TIMEOUT, message, BiometricSourceType.FACE); verifyNoMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE); } @@ -698,8 +704,7 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase { BiometricFaceConstants.FACE_ACQUIRED_TOO_LEFT, BiometricFaceConstants.FACE_ACQUIRED_TOO_HIGH, BiometricFaceConstants.FACE_ACQUIRED_TOO_LOW, - BiometricFaceConstants.FACE_ACQUIRED_TOO_BRIGHT, - BiometricFaceConstants.FACE_ACQUIRED_TOO_DARK + BiometricFaceConstants.FACE_ACQUIRED_TOO_BRIGHT }; for (int msgId : msgIds) { mKeyguardUpdateMonitorCallback.onBiometricHelp( @@ -728,8 +733,7 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase { BiometricFaceConstants.FACE_ACQUIRED_TOO_LEFT, BiometricFaceConstants.FACE_ACQUIRED_TOO_HIGH, BiometricFaceConstants.FACE_ACQUIRED_TOO_LOW, - BiometricFaceConstants.FACE_ACQUIRED_TOO_BRIGHT, - BiometricFaceConstants.FACE_ACQUIRED_TOO_DARK + BiometricFaceConstants.FACE_ACQUIRED_TOO_BRIGHT }; for (int msgId : msgIds) { final String numberedHelpString = helpString + msgId; @@ -743,6 +747,68 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase { } @Test + public void sendTooDarkFaceHelpMessages_onTimeout_noFpEnrolled() { + createController(); + + // GIVEN fingerprint NOT enrolled + when(mKeyguardUpdateMonitor.getCachedIsUnlockWithFingerprintPossible( + 0)).thenReturn(false); + + // WHEN help message received and deferred message is valid + final String helpString = "helpMsg"; + when(mFaceHelpMessageDeferral.getDeferredMessage()).thenReturn(helpString); + when(mFaceHelpMessageDeferral.shouldDefer(FACE_ACQUIRED_TOO_DARK)).thenReturn(true); + mKeyguardUpdateMonitorCallback.onBiometricHelp( + BiometricFaceConstants.FACE_ACQUIRED_TOO_DARK, + helpString, + BiometricSourceType.FACE + ); + + // THEN help message not shown yet + verifyNoMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE); + + // WHEN face timeout error received + mKeyguardUpdateMonitorCallback.onBiometricError(FACE_ERROR_TIMEOUT, "face timeout", + BiometricSourceType.FACE); + + // THEN the low light message shows with suggestion to swipe up to unlock + verifyIndicationMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE, helpString); + verifyIndicationMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP, + mContext.getString(R.string.keyguard_unlock)); + } + + @Test + public void sendTooDarkFaceHelpMessages_onTimeout_fingerprintEnrolled() { + createController(); + + // GIVEN fingerprint enrolled + when(mKeyguardUpdateMonitor.getCachedIsUnlockWithFingerprintPossible( + 0)).thenReturn(true); + + // WHEN help message received and deferredMessage is valid + final String helpString = "helpMsg"; + when(mFaceHelpMessageDeferral.getDeferredMessage()).thenReturn(helpString); + when(mFaceHelpMessageDeferral.shouldDefer(FACE_ACQUIRED_TOO_DARK)).thenReturn(true); + mKeyguardUpdateMonitorCallback.onBiometricHelp( + BiometricFaceConstants.FACE_ACQUIRED_TOO_DARK, + helpString, + BiometricSourceType.FACE + ); + + // THEN help message not shown yet + verifyNoMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE); + + // WHEN face timeout error received + mKeyguardUpdateMonitorCallback.onBiometricError(FACE_ERROR_TIMEOUT, "face timeout", + BiometricSourceType.FACE); + + // THEN the low light message shows and suggests trying fingerprint + verifyIndicationMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE, helpString); + verifyIndicationMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP, + mContext.getString(R.string.keyguard_suggest_fingerprint)); + } + + @Test public void updateMonitor_listenerUpdatesIndication() { createController(); String restingIndication = "Resting indication"; @@ -994,14 +1060,14 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase { } @Test - public void onTrustGrantedMessageDoesShowsOnTrustGranted() { + public void onTrustGrantedMessageShowsOnTrustGranted() { createController(); mController.setVisible(true); // GIVEN trust is granted when(mKeyguardUpdateMonitor.getUserHasTrust(anyInt())).thenReturn(true); - // WHEN the showTrustGranted message is called + // WHEN the showTrustGranted method is called final String trustGrantedMsg = "testing trust granted message"; mController.getKeyguardCallback().showTrustGrantedMessage(trustGrantedMsg); @@ -1012,6 +1078,38 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase { } @Test + public void onTrustGrantedMessage_nullMessage_showsDefaultMessage() { + createController(); + mController.setVisible(true); + + // GIVEN trust is granted + when(mKeyguardUpdateMonitor.getUserHasTrust(anyInt())).thenReturn(true); + + // WHEN the showTrustGranted method is called with a null message + mController.getKeyguardCallback().showTrustGrantedMessage(null); + + // THEN verify the default trust granted message shows + verifyIndicationMessage( + INDICATION_TYPE_TRUST, + getContext().getString(R.string.keyguard_indication_trust_unlocked)); + } + + @Test + public void onTrustGrantedMessage_emptyString_showsNoMessage() { + createController(); + mController.setVisible(true); + + // GIVEN trust is granted + when(mKeyguardUpdateMonitor.getUserHasTrust(anyInt())).thenReturn(true); + + // WHEN the showTrustGranted method is called with an EMPTY string + mController.getKeyguardCallback().showTrustGrantedMessage(""); + + // THEN verify NO trust message is shown + verifyNoMessage(INDICATION_TYPE_TRUST); + } + + @Test public void coEx_faceSuccess_showsPressToOpen() { // GIVEN bouncer isn't showing, can skip bouncer, udfps is supported, no a11y enabled when(mStatusBarKeyguardViewManager.isBouncerShowing()).thenReturn(false); @@ -1035,7 +1133,6 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase { verifyIndicationMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE_FOLLOW_UP, pressToOpen); } - @Test public void coEx_faceSuccess_touchExplorationEnabled_showsFaceUnlockedSwipeToOpen() { // GIVEN bouncer isn't showing, can skip bouncer, udfps is supported, a11y enabled @@ -1181,6 +1278,87 @@ public class KeyguardIndicationControllerTest extends SysuiTestCase { verifyIndicationMessage(INDICATION_TYPE_BIOMETRIC_MESSAGE, swipeToOpen); } + @Test + public void faceOnAcquired_processFrame() { + createController(); + + // WHEN face sends an acquired message + final int acquireInfo = 1; + mKeyguardUpdateMonitorCallback.onBiometricAcquired(BiometricSourceType.FACE, acquireInfo); + + // THEN face help message deferral should process the acquired frame + verify(mFaceHelpMessageDeferral).processFrame(acquireInfo); + } + + @Test + public void fingerprintOnAcquired_noProcessFrame() { + createController(); + + // WHEN fingerprint sends an acquired message + mKeyguardUpdateMonitorCallback.onBiometricAcquired(BiometricSourceType.FINGERPRINT, 1); + + // THEN face help message deferral should NOT process any acquired frames + verify(mFaceHelpMessageDeferral, never()).processFrame(anyInt()); + } + + @Test + public void onBiometricHelp_fingerprint_faceHelpMessageDeferralDoesNothing() { + createController(); + + // WHEN fingerprint sends an onBiometricHelp + mKeyguardUpdateMonitorCallback.onBiometricHelp( + 1, + "placeholder", + BiometricSourceType.FINGERPRINT); + + // THEN face help message deferral is NOT: reset, updated, or checked for shouldDefer + verify(mFaceHelpMessageDeferral, never()).reset(); + verify(mFaceHelpMessageDeferral, never()).updateMessage(anyInt(), anyString()); + verify(mFaceHelpMessageDeferral, never()).shouldDefer(anyInt()); + } + + @Test + public void onBiometricFailed_resetFaceHelpMessageDeferral() { + createController(); + + // WHEN face sends an onBiometricHelp BIOMETRIC_HELP_FACE_NOT_RECOGNIZED + mKeyguardUpdateMonitorCallback.onBiometricAuthFailed(BiometricSourceType.FACE); + + // THEN face help message deferral is reset + verify(mFaceHelpMessageDeferral).reset(); + } + + @Test + public void onBiometricError_resetFaceHelpMessageDeferral() { + createController(); + + // WHEN face has an error + mKeyguardUpdateMonitorCallback.onBiometricError(4, "string", + BiometricSourceType.FACE); + + // THEN face help message deferral is reset + verify(mFaceHelpMessageDeferral).reset(); + } + + @Test + public void onBiometricHelp_faceAcquiredInfo_faceHelpMessageDeferral() { + createController(); + + // WHEN face sends an onBiometricHelp BIOMETRIC_HELP_FACE_NOT_RECOGNIZED + final int msgId = 1; + final String helpString = "test"; + mKeyguardUpdateMonitorCallback.onBiometricHelp( + msgId, + "test", + BiometricSourceType.FACE); + + // THEN face help message deferral is NOT reset and message IS updated + verify(mFaceHelpMessageDeferral, never()).reset(); + verify(mFaceHelpMessageDeferral).updateMessage(msgId, helpString); + } + + + private void sendUpdateDisclosureBroadcast() { mBroadcastReceiver.onReceive(mContext, new Intent()); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeQsTransitionControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeQsTransitionControllerTest.kt new file mode 100644 index 000000000000..70412626420d --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeQsTransitionControllerTest.kt @@ -0,0 +1,255 @@ +/* + * 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 + +import android.testing.AndroidTestingRunner +import androidx.test.filters.SmallTest +import com.android.systemui.R +import com.android.systemui.SysuiTestCase +import com.android.systemui.dump.DumpManager +import com.android.systemui.plugins.qs.QS +import com.android.systemui.statusbar.policy.FakeConfigurationController +import com.google.common.truth.Expect +import com.google.common.truth.Truth.assertThat +import org.junit.Before +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.mockito.Mock +import org.mockito.Mockito.verify +import org.mockito.MockitoAnnotations + +@SmallTest +@RunWith(AndroidTestingRunner::class) +class LockscreenShadeQsTransitionControllerTest : SysuiTestCase() { + + private val configurationController = FakeConfigurationController() + + @get:Rule val expect: Expect = Expect.create() + + @Mock private lateinit var dumpManager: DumpManager + @Mock private lateinit var qS: QS + + private lateinit var controller: LockscreenShadeQsTransitionController + + @Before + fun setUp() { + MockitoAnnotations.initMocks(this) + setTransitionDistance(TRANSITION_DISTANCE) + setTransitionDelay(TRANSITION_DELAY) + setSquishTransitionDistance(SQUISH_TRANSITION_DISTANCE) + setSquishStartFraction(SQUISH_START_FRACTION) + + controller = + LockscreenShadeQsTransitionController( + context, + configurationController, + dumpManager, + qsProvider = { qS } + ) + } + + @Test + fun qsTransitionFraction_byDefault_returns0() { + assertThat(controller.qsTransitionFraction).isZero() + } + + @Test + fun qsTransitionFraction_noStartDelay_returnsBasedOnTransitionDistance() { + setTransitionDelay(0) + setTransitionDistance(100) + + controller.dragDownAmount = 25f + expect.that(controller.qsTransitionFraction).isEqualTo(0.25f) + + controller.dragDownAmount = 50f + expect.that(controller.qsTransitionFraction).isEqualTo(0.5f) + + controller.dragDownAmount = 75f + expect.that(controller.qsTransitionFraction).isEqualTo(0.75f) + + controller.dragDownAmount = 100f + expect.that(controller.qsTransitionFraction).isEqualTo(1f) + } + + @Test + fun qsTransitionFraction_noStartDelay_returnsValuesBetween0and1() { + setTransitionDelay(0) + setTransitionDistance(100) + + controller.dragDownAmount = -500f + expect.that(controller.qsTransitionFraction).isEqualTo(0f) + + controller.dragDownAmount = 500f + expect.that(controller.qsTransitionFraction).isEqualTo(1f) + } + + @Test + fun qsTransitionFraction_withStartDelay_returnsBasedOnTransitionDistanceAndDelay() { + setTransitionDelay(10) + setTransitionDistance(100) + + controller.dragDownAmount = 0f + expect.that(controller.qsTransitionFraction).isEqualTo(0f) + + controller.dragDownAmount = 10f + expect.that(controller.qsTransitionFraction).isEqualTo(0f) + + controller.dragDownAmount = 25f + expect.that(controller.qsTransitionFraction).isEqualTo(0.15f) + + controller.dragDownAmount = 100f + expect.that(controller.qsTransitionFraction).isEqualTo(0.9f) + + controller.dragDownAmount = 110f + expect.that(controller.qsTransitionFraction).isEqualTo(1f) + } + + @Test + fun qsTransitionFraction_withStartDelay_returnsValuesBetween0and1() { + setTransitionDelay(10) + setTransitionDistance(100) + + controller.dragDownAmount = -500f + expect.that(controller.qsTransitionFraction).isEqualTo(0f) + + controller.dragDownAmount = 500f + expect.that(controller.qsTransitionFraction).isEqualTo(1f) + } + + @Test + fun qsSquishTransitionFraction_byDefault_returnsValueSetFromResource() { + assertThat(controller.qsSquishTransitionFraction).isEqualTo(SQUISH_START_FRACTION) + } + + @Test + fun qsSquishTransitionFraction_noStartDelay_startFraction0_returnsBasedOnTransitionDistance() { + setTransitionDelay(0) + setSquishStartFraction(0f) + setSquishTransitionDistance(1000) + + controller.dragDownAmount = 250f + expect.that(controller.qsSquishTransitionFraction).isEqualTo(0.25f) + + controller.dragDownAmount = 500f + expect.that(controller.qsSquishTransitionFraction).isEqualTo(0.5f) + + controller.dragDownAmount = 750f + expect.that(controller.qsSquishTransitionFraction).isEqualTo(0.75f) + + controller.dragDownAmount = 1000f + expect.that(controller.qsSquishTransitionFraction).isEqualTo(1f) + } + + @Test + fun qsSquishTransitionFraction_startDelay_startFraction0_basedOnTransitionDistanceAndDelay() { + setTransitionDelay(100) + setSquishStartFraction(0f) + setSquishTransitionDistance(1000) + + controller.dragDownAmount = 250f + expect.that(controller.qsSquishTransitionFraction).isEqualTo(0.15f) + + controller.dragDownAmount = 500f + expect.that(controller.qsSquishTransitionFraction).isEqualTo(0.4f) + + controller.dragDownAmount = 750f + expect.that(controller.qsSquishTransitionFraction).isEqualTo(0.65f) + + controller.dragDownAmount = 1000f + expect.that(controller.qsSquishTransitionFraction).isEqualTo(0.9f) + + controller.dragDownAmount = 1100f + expect.that(controller.qsSquishTransitionFraction).isEqualTo(1f) + } + + @Test + fun qsSquishTransitionFraction_noStartDelay_startFractionSet_returnsBasedOnStartAndDistance() { + setTransitionDelay(0) + setSquishStartFraction(0.5f) + setSquishTransitionDistance(1000) + + controller.dragDownAmount = 0f + expect.that(controller.qsSquishTransitionFraction).isEqualTo(0.5f) + + controller.dragDownAmount = 500f + expect.that(controller.qsSquishTransitionFraction).isEqualTo(0.75f) + + controller.dragDownAmount = 1000f + expect.that(controller.qsSquishTransitionFraction).isEqualTo(1f) + } + + @Test + fun qsSquishTransitionFraction_startDelay_startFractionSet_basedOnStartAndDistanceAndDelay() { + setTransitionDelay(10) + setSquishStartFraction(0.5f) + setSquishTransitionDistance(100) + + controller.dragDownAmount = 0f + expect.that(controller.qsSquishTransitionFraction).isEqualTo(0.5f) + + controller.dragDownAmount = 50f + expect.that(controller.qsSquishTransitionFraction).isEqualTo(0.7f) + + controller.dragDownAmount = 100f + expect.that(controller.qsSquishTransitionFraction).isEqualTo(0.95f) + + controller.dragDownAmount = 110f + expect.that(controller.qsSquishTransitionFraction).isEqualTo(1f) + } + + @Test + fun onDragDownAmountChanged_setsValuesOnQS() { + val rawDragAmount = 200f + + controller.dragDownAmount = rawDragAmount + + verify(qS) + .setTransitionToFullShadeProgress( + /* isTransitioningToFullShade= */ true, + /* transitionFraction= */ controller.qsTransitionFraction, + /* squishinessFraction= */ controller.qsSquishTransitionFraction + ) + } + + private fun setTransitionDistance(value: Int) { + overrideResource(R.dimen.lockscreen_shade_qs_transition_distance, value) + configurationController.notifyConfigurationChanged() + } + + private fun setTransitionDelay(value: Int) { + overrideResource(R.dimen.lockscreen_shade_qs_transition_delay, value) + configurationController.notifyConfigurationChanged() + } + + private fun setSquishTransitionDistance(value: Int) { + overrideResource(R.dimen.lockscreen_shade_qs_squish_transition_distance, value) + configurationController.notifyConfigurationChanged() + } + + private fun setSquishStartFraction(value: Float) { + overrideResource(R.dimen.lockscreen_shade_qs_squish_start_fraction, value) + configurationController.notifyConfigurationChanged() + } + + companion object { + private const val TRANSITION_DELAY = 123 + private const val TRANSITION_DISTANCE = 321 + private const val SQUISH_START_FRACTION = 0.123f + private const val SQUISH_TRANSITION_DISTANCE = 456 + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt index fe1cd978ef91..8643e86acef2 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt @@ -1,9 +1,9 @@ package com.android.systemui.statusbar -import android.test.suitebuilder.annotation.SmallTest import android.testing.AndroidTestingRunner import android.testing.TestableLooper import android.testing.TestableLooper.RunWithLooper +import androidx.test.filters.SmallTest import com.android.systemui.ExpandHelper import com.android.systemui.R import com.android.systemui.SysuiTestCase @@ -78,6 +78,7 @@ class LockscreenShadeTransitionControllerTest : SysuiTestCase() { @Mock lateinit var qS: QS @Mock lateinit var singleShadeOverScroller: SingleShadeLockScreenOverScroller @Mock lateinit var splitShadeOverScroller: SplitShadeLockScreenOverScroller + @Mock lateinit var qsTransitionController: LockscreenShadeQsTransitionController @JvmField @Rule val mockito = MockitoJUnit.rule() private val configurationController = FakeConfigurationController() @@ -120,7 +121,9 @@ class LockscreenShadeTransitionControllerTest : SysuiTestCase() { context, configurationController, dumpManager) - }) + }, + qsTransitionControllerFactory = { qsTransitionController }, + ) whenever(nsslController.view).thenReturn(stackscroller) whenever(nsslController.expandHelperCallback).thenReturn(expandHelperCallback) transitionController.notificationPanelController = notificationPanelController @@ -249,7 +252,7 @@ class LockscreenShadeTransitionControllerTest : SysuiTestCase() { verify(scrimController, never()).setTransitionToFullShadeProgress(anyFloat(), anyFloat()) verify(notificationPanelController, never()).setTransitionToFullShadeAmount(anyFloat(), anyBoolean(), anyLong()) - verify(qS, never()).setTransitionToFullShadeAmount(anyFloat(), anyFloat()) + verify(qsTransitionController, never()).dragDownAmount = anyFloat() } @Test @@ -260,7 +263,7 @@ class LockscreenShadeTransitionControllerTest : SysuiTestCase() { verify(scrimController).setTransitionToFullShadeProgress(anyFloat(), anyFloat()) verify(notificationPanelController).setTransitionToFullShadeAmount(anyFloat(), anyBoolean(), anyLong()) - verify(qS).setTransitionToFullShadeAmount(anyFloat(), anyFloat()) + verify(qsTransitionController).dragDownAmount = 10f verify(depthController).transitionToFullShadeProgress = anyFloat() } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt index b166b7367b53..6446fb5d8c81 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt @@ -48,7 +48,6 @@ import org.mockito.ArgumentMatchers.floatThat import org.mockito.Captor import org.mockito.Mock import org.mockito.Mockito -import org.mockito.Mockito.`when` import org.mockito.Mockito.any import org.mockito.Mockito.anyFloat import org.mockito.Mockito.anyString @@ -56,6 +55,7 @@ import org.mockito.Mockito.clearInvocations import org.mockito.Mockito.never import org.mockito.Mockito.reset import org.mockito.Mockito.verify +import org.mockito.Mockito.`when` import org.mockito.junit.MockitoJUnit @RunWith(AndroidTestingRunner::class) @@ -139,7 +139,7 @@ class NotificationShadeDepthControllerTest : SysuiTestCase() { notificationShadeDepthController.onPanelExpansionChanged( PanelExpansionChangeEvent( fraction = 1f, expanded = true, tracking = false, dragDownPxAmount = 0f)) - verify(shadeAnimation).animateTo(eq(maxBlur), any()) + verify(shadeAnimation).animateTo(eq(maxBlur)) } @Test @@ -147,7 +147,7 @@ class NotificationShadeDepthControllerTest : SysuiTestCase() { notificationShadeDepthController.onPanelExpansionChanged( PanelExpansionChangeEvent( fraction = 0.01f, expanded = false, tracking = false, dragDownPxAmount = 0f)) - verify(shadeAnimation).animateTo(eq(maxBlur), any()) + verify(shadeAnimation).animateTo(eq(maxBlur)) } @Test @@ -157,7 +157,7 @@ class NotificationShadeDepthControllerTest : SysuiTestCase() { notificationShadeDepthController.onPanelExpansionChanged( PanelExpansionChangeEvent( fraction = 0f, expanded = false, tracking = false, dragDownPxAmount = 0f)) - verify(shadeAnimation).animateTo(eq(0), any()) + verify(shadeAnimation).animateTo(eq(0)) } @Test @@ -168,15 +168,15 @@ class NotificationShadeDepthControllerTest : SysuiTestCase() { onPanelExpansionChanged_apliesBlur_ifShade() clearInvocations(shadeAnimation) notificationShadeDepthController.onPanelExpansionChanged(event) - verify(shadeAnimation, never()).animateTo(anyInt(), any()) + verify(shadeAnimation, never()).animateTo(anyInt()) notificationShadeDepthController.onPanelExpansionChanged( event.copy(fraction = 0.9f, tracking = true)) - verify(shadeAnimation, never()).animateTo(anyInt(), any()) + verify(shadeAnimation, never()).animateTo(anyInt()) notificationShadeDepthController.onPanelExpansionChanged( event.copy(fraction = 0.8f, tracking = false)) - verify(shadeAnimation).animateTo(eq(0), any()) + verify(shadeAnimation).animateTo(eq(0)) } @Test @@ -186,7 +186,7 @@ class NotificationShadeDepthControllerTest : SysuiTestCase() { notificationShadeDepthController.onPanelExpansionChanged( PanelExpansionChangeEvent( fraction = 0.6f, expanded = true, tracking = true, dragDownPxAmount = 0f)) - verify(shadeAnimation).animateTo(eq(maxBlur), any()) + verify(shadeAnimation).animateTo(eq(maxBlur)) } @Test @@ -212,7 +212,7 @@ class NotificationShadeDepthControllerTest : SysuiTestCase() { statusBarState = StatusBarState.KEYGUARD statusBarStateListener.onStateChanged(statusBarState) - verify(shadeAnimation).animateTo(eq(0), any()) + verify(shadeAnimation).animateTo(eq(0)) } @Test @@ -395,13 +395,13 @@ class NotificationShadeDepthControllerTest : SysuiTestCase() { @Test fun brightnessMirrorVisible_whenVisible() { notificationShadeDepthController.brightnessMirrorVisible = true - verify(brightnessSpring).animateTo(eq(maxBlur), any()) + verify(brightnessSpring).animateTo(eq(maxBlur)) } @Test fun brightnessMirrorVisible_whenHidden() { notificationShadeDepthController.brightnessMirrorVisible = false - verify(brightnessSpring).animateTo(eq(0), any()) + verify(brightnessSpring).animateTo(eq(0)) } @Test @@ -424,7 +424,7 @@ class NotificationShadeDepthControllerTest : SysuiTestCase() { fun ignoreShadeBlurUntilHidden_whennNull_ignoresIfShadeHasNoBlur() { `when`(shadeAnimation.radius).thenReturn(0f) notificationShadeDepthController.blursDisabledForAppLaunch = true - verify(shadeAnimation, never()).animateTo(anyInt(), any()) + verify(shadeAnimation, never()).animateTo(anyInt()) } private fun enableSplitShade() { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/AmbientStateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/AmbientStateTest.kt new file mode 100644 index 000000000000..11798a7a4f96 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/AmbientStateTest.kt @@ -0,0 +1,390 @@ +/* + * 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.stack + +import android.testing.AndroidTestingRunner +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.dump.DumpManager +import com.android.systemui.statusbar.StatusBarState +import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager +import com.android.systemui.util.mockito.mock +import com.android.systemui.util.mockito.whenever +import com.google.common.truth.Truth.assertThat +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith + +private const val MAX_PULSE_HEIGHT = 100000f + +@RunWith(AndroidTestingRunner::class) +@SmallTest +class AmbientStateTest : SysuiTestCase() { + + private val dumpManager = mock<DumpManager>() + private val sectionProvider = StackScrollAlgorithm.SectionProvider { _, _ -> false } + private val bypassController = StackScrollAlgorithm.BypassController { false } + private val statusBarKeyguardViewManager = mock<StatusBarKeyguardViewManager>() + + private lateinit var sut: AmbientState + + @Before + fun setUp() { + sut = + AmbientState( + context, + dumpManager, + sectionProvider, + bypassController, + statusBarKeyguardViewManager, + ) + } + + // region isDimmed + @Test + fun isDimmed_whenTrue_shouldReturnTrue() { + sut.arrangeDimmed(true) + + assertThat(sut.isDimmed).isTrue() + } + + @Test + fun isDimmed_whenFalse_shouldReturnFalse() { + sut.arrangeDimmed(false) + + assertThat(sut.isDimmed).isFalse() + } + + @Test + fun isDimmed_whenDozeAmountIsEmpty_shouldReturnTrue() { + sut.arrangeDimmed(true) + sut.dozeAmount = 0f + + assertThat(sut.isDimmed).isTrue() + } + + @Test + fun isDimmed_whenPulseExpandingIsFalse_shouldReturnTrue() { + sut.arrangeDimmed(true) + sut.arrangePulseExpanding(false) + sut.dozeAmount = 1f // arrangePulseExpanding changes dozeAmount + + assertThat(sut.isDimmed).isTrue() + } + // endregion + + // region pulseHeight + @Test + fun pulseHeight_whenValueChanged_shouldCallListener() { + var listenerCalledCount = 0 + sut.pulseHeight = MAX_PULSE_HEIGHT + sut.setOnPulseHeightChangedListener { listenerCalledCount++ } + + sut.pulseHeight = 0f + + assertThat(listenerCalledCount).isEqualTo(1) + } + + @Test + fun pulseHeight_whenSetSameValue_shouldDoNothing() { + var listenerCalledCount = 0 + sut.pulseHeight = MAX_PULSE_HEIGHT + sut.setOnPulseHeightChangedListener { listenerCalledCount++ } + + sut.pulseHeight = MAX_PULSE_HEIGHT + + assertThat(listenerCalledCount).isEqualTo(0) + } + + @Test + fun pulseHeight_whenValueIsFull_shouldReturn0() { + sut.pulseHeight = MAX_PULSE_HEIGHT + + assertThat(sut.pulseHeight).isEqualTo(0f) + } + + @Test + fun pulseHeight_whenValueIsNotFull_shouldReturnValue() { + val expected = MAX_PULSE_HEIGHT - 0.1f + sut.pulseHeight = expected + + assertThat(sut.pulseHeight).isEqualTo(expected) + } + // endregion + + // region statusBarState + @Test + fun statusBarState_whenPreviousStateIsNotKeyguardAndChange_shouldSetIsFlingRequiredToFalse() { + sut.setStatusBarState(StatusBarState.SHADE) + sut.isFlingRequiredAfterLockScreenSwipeUp = true + + sut.setStatusBarState(StatusBarState.KEYGUARD) + + assertThat(sut.isFlingRequiredAfterLockScreenSwipeUp).isFalse() + } + + @Test + fun statusBarState_whenPreviousStateIsKeyguardAndChange_shouldDoNothing() { + sut.setStatusBarState(StatusBarState.KEYGUARD) + sut.isFlingRequiredAfterLockScreenSwipeUp = true + + sut.setStatusBarState(StatusBarState.SHADE) + + assertThat(sut.isFlingRequiredAfterLockScreenSwipeUp).isTrue() + } + // endregion + + // region hideAmount + @Test + fun hideAmount_whenSetToFullValue_shouldReturnZeroFromPulseHeight() { + sut.hideAmount = 0f + sut.pulseHeight = 1f + + sut.hideAmount = 1f + + assertThat(sut.pulseHeight).isEqualTo(0f) + } + + @Test + fun hideAmount_whenSetToAnyNotFullValue_shouldDoNothing() { + sut.hideAmount = 1f + sut.pulseHeight = 1f + + sut.hideAmount = 0f + + assertThat(sut.pulseHeight).isEqualTo(1f) + } + // endregion + + // region dozeAmount + @Test + fun dozeAmount_whenDozeAmountIsSetToFullDozing_shouldReturnZeroFromPulseHeight() { + sut.dozeAmount = 0f + sut.pulseHeight = 1f + + sut.dozeAmount = 1f + + assertThat(sut.pulseHeight).isEqualTo(0f) + } + + @Test + fun dozeAmount_whenDozeAmountIsSetToFullAwake_shouldReturnZeroFromPulseHeight() { + sut.dozeAmount = 1f + sut.pulseHeight = 1f + + sut.dozeAmount = 0f + + assertThat(sut.pulseHeight).isEqualTo(0f) + } + + @Test + fun dozeAmount_whenDozeAmountIsSetAnyValueNotFullAwakeOrDozing_shouldDoNothing() { + sut.dozeAmount = 1f + sut.pulseHeight = 1f + + sut.dozeAmount = 0.5f + + assertThat(sut.pulseHeight).isEqualTo(1f) + } + // endregion + + // region trackedHeadsUpRow + @Test + fun trackedHeadsUpRow_whenIsAboveTheShelf_shouldReturnInstance() { + sut.trackedHeadsUpRow = mock { whenever(isAboveShelf).thenReturn(true) } + + assertThat(sut.trackedHeadsUpRow).isNotNull() + } + + @Test + fun trackedHeadsUpRow_whenIsNotAboveTheShelf_shouldReturnNull() { + sut.trackedHeadsUpRow = mock { whenever(isAboveShelf).thenReturn(false) } + + assertThat(sut.trackedHeadsUpRow).isNull() + } + // endregion + + // region isSwipingUp + @Test + fun isSwipingUp_whenValueChangedToTrue_shouldRequireFling() { + sut.isSwipingUp = false + sut.isFlingRequiredAfterLockScreenSwipeUp = false + + sut.isSwipingUp = true + + assertThat(sut.isFlingRequiredAfterLockScreenSwipeUp).isFalse() + } + + @Test + fun isSwipingUp_whenValueChangedToFalse_shouldRequireFling() { + sut.isSwipingUp = true + sut.isFlingRequiredAfterLockScreenSwipeUp = false + + sut.isSwipingUp = false + + assertThat(sut.isFlingRequiredAfterLockScreenSwipeUp).isTrue() + } + // endregion + + // region isFlinging + @Test + fun isFlinging_shouldNotNeedFling() { + sut.arrangeFlinging(true) + + sut.setFlinging(false) + + assertThat(sut.isFlingRequiredAfterLockScreenSwipeUp).isFalse() + } + + @Test + fun isFlinging_whenNotOnLockScreen_shouldDoNothing() { + sut.arrangeFlinging(true) + sut.setStatusBarState(StatusBarState.SHADE) + sut.isFlingRequiredAfterLockScreenSwipeUp = true + + sut.setFlinging(false) + + assertThat(sut.isFlingRequiredAfterLockScreenSwipeUp).isTrue() + } + + @Test + fun isFlinging_whenValueChangedToTrue_shouldDoNothing() { + sut.arrangeFlinging(false) + + sut.setFlinging(true) + + assertThat(sut.isFlingRequiredAfterLockScreenSwipeUp).isTrue() + } + // endregion + + // region scrollY + @Test + fun scrollY_shouldSetValueGreaterThanZero() { + sut.scrollY = 0 + + sut.scrollY = 1 + + assertThat(sut.scrollY).isEqualTo(1) + } + + @Test + fun scrollY_shouldNotSetValueLessThanZero() { + sut.scrollY = 0 + + sut.scrollY = -1 + + assertThat(sut.scrollY).isEqualTo(0) + } + // endregion + + // region setOverScrollAmount + fun setOverScrollAmount_shouldSetValueOnTop() { + sut.setOverScrollAmount(/* amount = */ 10f, /* onTop = */ true) + + val resultOnTop = sut.getOverScrollAmount(/* top = */ true) + val resultOnBottom = sut.getOverScrollAmount(/* top = */ false) + + assertThat(resultOnTop).isEqualTo(10f) + assertThat(resultOnBottom).isEqualTo(0f) + } + + fun setOverScrollAmount_shouldSetValueOnBottom() { + sut.setOverScrollAmount(/* amount = */ 10f, /* onTop = */ false) + + val resultOnTop = sut.getOverScrollAmount(/* top */ true) + val resultOnBottom = sut.getOverScrollAmount(/* top */ false) + + assertThat(resultOnTop).isEqualTo(0f) + assertThat(resultOnBottom).isEqualTo(10f) + } + // endregion + + // region IsPulseExpanding + @Test + fun isPulseExpanding_shouldReturnTrue() { + sut.arrangePulseExpanding(true) + + assertThat(sut.isPulseExpanding).isTrue() + } + + @Test + fun isPulseExpanding_whenPulseHeightIsMax_shouldReturnFalse() { + sut.arrangePulseExpanding(true) + sut.pulseHeight = MAX_PULSE_HEIGHT + + assertThat(sut.isPulseExpanding).isFalse() + } + + @Test + fun isPulseExpanding_whenDozeAmountIsZero_shouldReturnFalse() { + sut.arrangePulseExpanding(true) + sut.dozeAmount = 0f + + assertThat(sut.isPulseExpanding).isFalse() + } + + @Test + fun isPulseExpanding_whenHideAmountIsFull_shouldReturnFalse() { + sut.arrangePulseExpanding(true) + sut.hideAmount = 1f + + assertThat(sut.isPulseExpanding).isFalse() + } + // endregion + + // region isOnKeyguard + @Test + fun isOnKeyguard_whenStatusBarStateIsKeyguard_shouldReturnTrue() { + sut.setStatusBarState(StatusBarState.KEYGUARD) + + assertThat(sut.isOnKeyguard).isTrue() + } + + @Test + fun isOnKeyguard_whenStatusBarStateIsNotKeyguard_shouldReturnFalse() { + sut.setStatusBarState(StatusBarState.SHADE) + + assertThat(sut.isOnKeyguard).isFalse() + } + // endregion +} + +// region Arrange helper methods. +private fun AmbientState.arrangeDimmed(value: Boolean) { + isDimmed = value + dozeAmount = if (value) 0f else 1f + arrangePulseExpanding(!value) +} + +private fun AmbientState.arrangePulseExpanding(value: Boolean) { + if (value) { + dozeAmount = 1f + hideAmount = 0f + pulseHeight = 0f + } else { + dozeAmount = 0f + hideAmount = 1f + pulseHeight = MAX_PULSE_HEIGHT + } +} + +private fun AmbientState.arrangeFlinging(value: Boolean) { + setStatusBarState(StatusBarState.KEYGUARD) + setFlinging(value) + isFlingRequiredAfterLockScreenSwipeUp = true +} +// endregion diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationShelfTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationShelfTest.kt index 3f190367f284..77418138158b 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationShelfTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationShelfTest.kt @@ -3,15 +3,22 @@ package com.android.systemui.statusbar.notification.stack import android.testing.AndroidTestingRunner import android.testing.TestableLooper.RunWithLooper import androidx.test.filters.SmallTest +import com.android.keyguard.BouncerPanelExpansionCalculator.aboutToShowBouncerProgress import com.android.systemui.SysuiTestCase +import com.android.systemui.animation.ShadeInterpolation import com.android.systemui.statusbar.NotificationShelf import com.android.systemui.statusbar.StatusBarIconView +import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow import com.android.systemui.statusbar.notification.row.ExpandableView -import junit.framework.Assert.* +import com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm.StackScrollAlgorithmState +import com.android.systemui.util.mockito.mock +import junit.framework.Assert.assertEquals +import junit.framework.Assert.assertFalse +import junit.framework.Assert.assertTrue import org.junit.Before import org.junit.Test import org.junit.runner.RunWith -import org.mockito.Mockito.* +import org.mockito.Mockito.mock import org.mockito.Mockito.`when` as whenever /** @@ -22,13 +29,18 @@ import org.mockito.Mockito.`when` as whenever @RunWithLooper class NotificationShelfTest : SysuiTestCase() { - private val shelf = NotificationShelf(context, /* attrs */ null) + private val shelf = NotificationShelf( + context, + /* attrs */ null, + /* showNotificationShelf */true + ) private val shelfState = shelf.viewState as NotificationShelf.ShelfState private val ambientState = mock(AmbientState::class.java) + private val hostLayoutController: NotificationStackScrollLayoutController = mock() @Before fun setUp() { - shelf.bind(ambientState, /* hostLayoutController */ null) + shelf.bind(ambientState, /* hostLayoutController */ hostLayoutController) shelf.layout(/* left */ 0, /* top */ 0, /* right */ 30, /* bottom */5) } @@ -37,7 +49,7 @@ class NotificationShelfTest : SysuiTestCase() { setFractionToShade(0f) setOnLockscreen(true) - shelf.updateActualWidth(/* fractionToShade */ 0f, /* shortestWidth */ 10f); + shelf.updateActualWidth(/* fractionToShade */ 0f, /* shortestWidth */ 10f) assertTrue(shelf.actualWidth == 10) shelf.updateActualWidth(/* fractionToShade */ 0.5f, /* shortestWidth */ 10f) @@ -155,7 +167,7 @@ class NotificationShelfTest : SysuiTestCase() { whenever(expandableView.actualHeight).thenReturn(20) whenever(expandableView.minHeight).thenReturn(20) - whenever(expandableView.shelfTransformationTarget).thenReturn(null) // use translationY + whenever(expandableView.shelfTransformationTarget).thenReturn(null) // use translationY whenever(expandableView.isInShelf).thenReturn(true) whenever(ambientState.isOnKeyguard).thenReturn(true) @@ -182,7 +194,7 @@ class NotificationShelfTest : SysuiTestCase() { whenever(expandableView.actualHeight).thenReturn(20) whenever(expandableView.minHeight).thenReturn(20) - whenever(expandableView.shelfTransformationTarget).thenReturn(null) // use translationY + whenever(expandableView.shelfTransformationTarget).thenReturn(null) // use translationY whenever(expandableView.isInShelf).thenReturn(true) whenever(ambientState.isOnKeyguard).thenReturn(true) @@ -209,7 +221,7 @@ class NotificationShelfTest : SysuiTestCase() { whenever(expandableView.actualHeight).thenReturn(25) whenever(expandableView.minHeight).thenReturn(25) - whenever(expandableView.shelfTransformationTarget).thenReturn(null) // use translationY + whenever(expandableView.shelfTransformationTarget).thenReturn(null) // use translationY whenever(expandableView.isInShelf).thenReturn(true) whenever(ambientState.isOnKeyguard).thenReturn(true) @@ -236,7 +248,7 @@ class NotificationShelfTest : SysuiTestCase() { whenever(expandableView.actualHeight).thenReturn(10) whenever(expandableView.minHeight).thenReturn(10) - whenever(expandableView.shelfTransformationTarget).thenReturn(null) // use translationY + whenever(expandableView.shelfTransformationTarget).thenReturn(null) // use translationY whenever(expandableView.isInShelf).thenReturn(false) whenever(ambientState.isExpansionChanging).thenReturn(false) @@ -251,6 +263,42 @@ class NotificationShelfTest : SysuiTestCase() { assertEquals(0f, amountInShelf) } + @Test + fun updateState_expansionChanging_shelfTransparent() { + updateState_expansionChanging_shelfAlphaUpdated( + expansionFraction = 0.25f, + expectedAlpha = 0.0f + ) + } + + @Test + fun updateState_expansionChangingWhileBouncerInTransit_shelfTransparent() { + whenever(ambientState.isBouncerInTransit).thenReturn(true) + + updateState_expansionChanging_shelfAlphaUpdated( + expansionFraction = 0.85f, + expectedAlpha = 0.0f + ) + } + + @Test + fun updateState_expansionChanging_shelfAlphaUpdated() { + updateState_expansionChanging_shelfAlphaUpdated( + expansionFraction = 0.6f, + expectedAlpha = ShadeInterpolation.getContentAlpha(0.6f) + ) + } + + @Test + fun updateState_expansionChangingWhileBouncerInTransit_shelfAlphaUpdated() { + whenever(ambientState.isBouncerInTransit).thenReturn(true) + + updateState_expansionChanging_shelfAlphaUpdated( + expansionFraction = 0.95f, + expectedAlpha = aboutToShowBouncerProgress(0.95f) + ) + } + private fun setFractionToShade(fraction: Float) { whenever(ambientState.fractionToShade).thenReturn(fraction) } @@ -258,4 +306,19 @@ class NotificationShelfTest : SysuiTestCase() { private fun setOnLockscreen(isOnLockscreen: Boolean) { whenever(ambientState.isOnKeyguard).thenReturn(isOnLockscreen) } -}
\ No newline at end of file + + private fun updateState_expansionChanging_shelfAlphaUpdated( + expansionFraction: Float, + expectedAlpha: Float + ) { + whenever(ambientState.lastVisibleBackgroundChild) + .thenReturn(ExpandableNotificationRow(mContext, null)) + whenever(ambientState.isExpansionChanging).thenReturn(true) + whenever(ambientState.expansionFraction).thenReturn(expansionFraction) + whenever(hostLayoutController.speedBumpIndex).thenReturn(0) + + shelf.updateState(StackScrollAlgorithmState(), ambientState) + + assertEquals(expectedAlpha, shelf.viewState.alpha) + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java index 3c22edc0fcf2..6ae021b48f66 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java @@ -250,7 +250,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase { // Validate that when the animation ends the stackEndHeight is recalculated immediately clearInvocations(mAmbientState); mStackScroller.setPanelFlinging(false); - verify(mAmbientState).setIsFlinging(eq(false)); + verify(mAmbientState).setFlinging(eq(false)); verify(mAmbientState).setStackEndHeight(anyFloat()); verify(mAmbientState).setStackHeight(anyFloat()); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt index 24eff5ff1162..40aec82f5a85 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithmTest.kt @@ -20,7 +20,10 @@ import junit.framework.Assert.assertFalse import junit.framework.Assert.assertTrue import org.junit.Before import org.junit.Test +import org.mockito.Mockito.any +import org.mockito.Mockito.eq import org.mockito.Mockito.mock +import org.mockito.Mockito.verify import org.mockito.Mockito.`when` as whenever @SmallTest @@ -35,7 +38,6 @@ class StackScrollAlgorithmTest : SysuiTestCase() { private val emptyShadeView = EmptyShadeView(context, /* attrs= */ null).apply { layout(/* l= */ 0, /* t= */ 0, /* r= */ 100, /* b= */ 100) } - private val ambientState = AmbientState( context, dumpManager, @@ -115,29 +117,54 @@ class StackScrollAlgorithmTest : SysuiTestCase() { } @Test - fun resetViewStates_isExpansionChanging_viewBecomesTransparent() { + fun resetViewStates_expansionChanging_notificationBecomesTransparent() { whenever(mStatusBarKeyguardViewManager.isBouncerInTransit).thenReturn(false) - ambientState.isExpansionChanging = true - ambientState.expansionFraction = 0.25f - stackScrollAlgorithm.initView(context) + resetViewStates_expansionChanging_notificationAlphaUpdated( + expansionFraction = 0.25f, + expectedAlpha = 0.0f + ) + } - stackScrollAlgorithm.resetViewStates(ambientState, /* speedBumpIndex= */ 0) + @Test + fun resetViewStates_expansionChangingWhileBouncerInTransit_viewBecomesTransparent() { + whenever(mStatusBarKeyguardViewManager.isBouncerInTransit).thenReturn(true) + resetViewStates_expansionChanging_notificationAlphaUpdated( + expansionFraction = 0.85f, + expectedAlpha = 0.0f + ) + } - val expected = getContentAlpha(0.25f) - assertThat(notificationRow.viewState.alpha).isEqualTo(expected) + @Test + fun resetViewStates_expansionChanging_notificationAlphaUpdated() { + whenever(mStatusBarKeyguardViewManager.isBouncerInTransit).thenReturn(false) + resetViewStates_expansionChanging_notificationAlphaUpdated( + expansionFraction = 0.6f, + expectedAlpha = getContentAlpha(0.6f) + ) } @Test - fun resetViewStates_isExpansionChangingWhileBouncerInTransit_viewBecomesTransparent() { + fun resetViewStates_expansionChangingWhileBouncerInTransit_notificationAlphaUpdated() { whenever(mStatusBarKeyguardViewManager.isBouncerInTransit).thenReturn(true) + resetViewStates_expansionChanging_notificationAlphaUpdated( + expansionFraction = 0.95f, + expectedAlpha = aboutToShowBouncerProgress(0.95f) + ) + } + + @Test + fun resetViewStates_expansionChanging_shelfUpdated() { + ambientState.shelf = notificationShelf ambientState.isExpansionChanging = true - ambientState.expansionFraction = 0.25f + ambientState.expansionFraction = 0.6f stackScrollAlgorithm.initView(context) stackScrollAlgorithm.resetViewStates(ambientState, /* speedBumpIndex= */ 0) - val expected = aboutToShowBouncerProgress(0.25f) - assertThat(notificationRow.viewState.alpha).isEqualTo(expected) + verify(notificationShelf).updateState( + /* algorithmState= */any(), + /* ambientState= */eq(ambientState) + ) } @Test @@ -479,6 +506,19 @@ class StackScrollAlgorithmTest : SysuiTestCase() { /* originalCornerRoundness= */ 1f) assertEquals(1f, currentRoundness) } + + private fun resetViewStates_expansionChanging_notificationAlphaUpdated( + expansionFraction: Float, + expectedAlpha: Float + ) { + ambientState.isExpansionChanging = true + ambientState.expansionFraction = expansionFraction + stackScrollAlgorithm.initView(context) + + stackScrollAlgorithm.resetViewStates(ambientState, /* speedBumpIndex= */ 0) + + assertThat(notificationRow.viewState.alpha).isEqualTo(expectedAlpha) + } } private fun mockExpandableNotificationRow(): ExpandableNotificationRow { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java index a6808e01a081..cd0cc33df1a9 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java @@ -167,8 +167,6 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase { mBiometricUnlockController.onBiometricAuthenticated(UserHandle.USER_CURRENT, BiometricSourceType.FINGERPRINT, false /* isStrongBiometric */); verify(mStatusBarKeyguardViewManager).showBouncer(anyBoolean()); - verify(mShadeController).animateCollapsePanels(anyInt(), anyBoolean(), anyBoolean(), - anyFloat()); assertThat(mBiometricUnlockController.getMode()) .isEqualTo(BiometricUnlockController.MODE_SHOW_BOUNCER); assertThat(mBiometricUnlockController.getBiometricType()) @@ -298,10 +296,6 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase { mBiometricUnlockController.onBiometricAuthenticated(UserHandle.USER_CURRENT, BiometricSourceType.FACE, true /* isStrongBiometric */); - // Wake up before showing the bouncer - verify(mStatusBarKeyguardViewManager, never()).showBouncer(anyBoolean()); - mBiometricUnlockController.mWakefulnessObserver.onFinishedWakingUp(); - verify(mStatusBarKeyguardViewManager).showBouncer(anyBoolean()); assertThat(mBiometricUnlockController.getMode()) .isEqualTo(BiometricUnlockController.MODE_SHOW_BOUNCER); 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 14b74712ec43..f510e48de5a5 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 @@ -35,6 +35,7 @@ import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; +import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -69,7 +70,11 @@ import android.util.DisplayMetrics; import android.util.SparseArray; import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; +import android.view.ViewRootImpl; import android.view.WindowManager; +import android.window.OnBackInvokedCallback; +import android.window.OnBackInvokedDispatcher; +import android.window.WindowOnBackInvokedDispatcher; import androidx.test.filters.SmallTest; @@ -168,6 +173,7 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; +import org.mockito.Captor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; @@ -279,6 +285,15 @@ public class CentralSurfacesImplTest extends SysuiTestCase { @Mock private InteractionJankMonitor mJankMonitor; @Mock private DeviceStateManager mDeviceStateManager; @Mock private WiredChargingRippleController mWiredChargingRippleController; + /** + * The process of registering/unregistering a predictive back callback requires a + * ViewRootImpl, which is present IRL, but may be missing during a Mockito unit test. + * To prevent an NPE during test execution, we explicitly craft and provide a fake ViewRootImpl. + */ + @Mock private ViewRootImpl mViewRootImpl; + @Mock private WindowOnBackInvokedDispatcher mOnBackInvokedDispatcher; + @Captor private ArgumentCaptor<OnBackInvokedCallback> mOnBackInvokedCallback; + private ShadeController mShadeController; private final FakeSystemClock mFakeSystemClock = new FakeSystemClock(); private FakeExecutor mMainExecutor = new FakeExecutor(mFakeSystemClock); @@ -368,10 +383,10 @@ public class CentralSurfacesImplTest extends SysuiTestCase { return null; }).when(mNotificationShadeWindowController).batchApplyWindowLayoutParams(any()); - mShadeController = new ShadeControllerImpl(mCommandQueue, + mShadeController = spy(new ShadeControllerImpl(mCommandQueue, mStatusBarStateController, mNotificationShadeWindowController, mStatusBarKeyguardViewManager, mContext.getSystemService(WindowManager.class), - () -> Optional.of(mCentralSurfaces), () -> mAssistManager); + () -> Optional.of(mCentralSurfaces), () -> mAssistManager)); when(mOperatorNameViewControllerFactory.create(any())) .thenReturn(mOperatorNameViewController); @@ -460,7 +475,14 @@ public class CentralSurfacesImplTest extends SysuiTestCase { mActivityLaunchAnimator, mJankMonitor, mDeviceStateManager, - mWiredChargingRippleController, mDreamManager); + mWiredChargingRippleController, mDreamManager) { + @Override + protected ViewRootImpl getViewRootImpl() { + return mViewRootImpl; + } + }; + when(mViewRootImpl.getOnBackInvokedDispatcher()) + .thenReturn(mOnBackInvokedDispatcher); when(mKeyguardViewMediator.registerCentralSurfaces( any(CentralSurfacesImpl.class), any(NotificationPanelViewController.class), @@ -738,6 +760,43 @@ public class CentralSurfacesImplTest extends SysuiTestCase { } } + /** + * Do the following: + * 1. verify that a predictive back callback is registered when CSurf becomes visible + * 2. verify that the same callback is unregistered when CSurf becomes invisible + */ + @Test + public void testPredictiveBackCallback_registration() { + mCentralSurfaces.handleVisibleToUserChanged(true); + verify(mOnBackInvokedDispatcher).registerOnBackInvokedCallback( + eq(OnBackInvokedDispatcher.PRIORITY_DEFAULT), + mOnBackInvokedCallback.capture()); + + mCentralSurfaces.handleVisibleToUserChanged(false); + verify(mOnBackInvokedDispatcher).unregisterOnBackInvokedCallback( + eq(mOnBackInvokedCallback.getValue())); + } + + /** + * Do the following: + * 1. capture the predictive back callback during registration + * 2. call the callback directly + * 3. verify that the ShadeController's panel collapse animation is invoked + */ + @Test + public void testPredictiveBackCallback_invocationCollapsesPanel() { + mCentralSurfaces.setNotificationShadeWindowViewController( + mNotificationShadeWindowViewController); + mCentralSurfaces.handleVisibleToUserChanged(true); + verify(mOnBackInvokedDispatcher).registerOnBackInvokedCallback( + eq(OnBackInvokedDispatcher.PRIORITY_DEFAULT), + mOnBackInvokedCallback.capture()); + + when(mNotificationPanelViewController.canPanelBeCollapsed()).thenReturn(true); + mOnBackInvokedCallback.getValue().onBackInvoked(); + verify(mShadeController).animateCollapsePanels(); + } + @Test public void testPanelOpenForHeadsUp() { when(mDeviceProvisionedController.isDeviceProvisioned()).thenReturn(true); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java index 5c9871a01536..9de9db1d39e7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeServiceHostTest.java @@ -29,6 +29,7 @@ import static org.mockito.Mockito.when; import android.os.PowerManager; import android.testing.AndroidTestingRunner; +import android.testing.TestableLooper.RunWithLooper; import android.view.View; import androidx.test.filters.SmallTest; @@ -61,10 +62,10 @@ import org.mockito.MockitoAnnotations; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; -import java.util.Optional; @SmallTest @RunWith(AndroidTestingRunner.class) +@RunWithLooper(setAsMainLooper = true) public class DozeServiceHostTest extends SysuiTestCase { private DozeServiceHost mDozeServiceHost; @@ -92,6 +93,7 @@ public class DozeServiceHostTest extends SysuiTestCase { @Mock private View mAmbientIndicationContainer; @Mock private BiometricUnlockController mBiometricUnlockController; @Mock private AuthController mAuthController; + @Mock private DozeHost.Callback mCallback; @Before public void setup() { @@ -100,7 +102,7 @@ public class DozeServiceHostTest extends SysuiTestCase { mStatusBarStateController, mDeviceProvisionedController, mHeadsUpManager, mBatteryController, mScrimController, () -> mBiometricUnlockController, mKeyguardViewMediator, () -> mAssistManager, mDozeScrimController, - mKeyguardUpdateMonitor, mPulseExpansionHandler, Optional.empty(), + mKeyguardUpdateMonitor, mPulseExpansionHandler, mNotificationShadeWindowController, mNotificationWakeUpCoordinator, mAuthController, mNotificationIconAreaController); @@ -114,16 +116,19 @@ public class DozeServiceHostTest extends SysuiTestCase { @Test public void testStartStopDozing() { + mDozeServiceHost.addCallback(mCallback); when(mStatusBarStateController.getState()).thenReturn(StatusBarState.KEYGUARD); when(mStatusBarStateController.isKeyguardRequested()).thenReturn(true); assertFalse(mDozeServiceHost.getDozingRequested()); mDozeServiceHost.startDozing(); + verify(mCallback).onDozingChanged(eq(true)); verify(mStatusBarStateController).setIsDozing(eq(true)); verify(mCentralSurfaces).updateIsKeyguard(); mDozeServiceHost.stopDozing(); + verify(mCallback).onDozingChanged(eq(false)); verify(mStatusBarStateController).setIsDozing(eq(false)); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaTest.kt deleted file mode 100644 index 3440fa5ac9b1..000000000000 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaTest.kt +++ /dev/null @@ -1,54 +0,0 @@ -package com.android.systemui.statusbar.phone - -import android.testing.AndroidTestingRunner -import android.testing.TestableLooper -import android.view.LayoutInflater -import androidx.test.filters.SmallTest -import com.android.systemui.R -import com.android.systemui.SysuiTestCase -import com.android.systemui.assist.AssistManager -import com.android.systemui.plugins.ActivityStarter -import com.android.systemui.statusbar.policy.AccessibilityController -import com.android.systemui.statusbar.policy.FlashlightController -import com.android.systemui.statusbar.policy.KeyguardStateController -import com.android.systemui.tuner.TunerService -import java.util.concurrent.Executor -import org.junit.Before -import org.junit.Test -import org.junit.runner.RunWith -import org.mockito.Mock -import org.mockito.MockitoAnnotations - -@SmallTest -@RunWith(AndroidTestingRunner::class) -@TestableLooper.RunWithLooper(setAsMainLooper = true) -class KeyguardBottomAreaTest : SysuiTestCase() { - - @Mock - private lateinit var mCentralSurfaces: CentralSurfaces - private lateinit var mKeyguardBottomArea: KeyguardBottomAreaView - - @Before - fun setup() { - MockitoAnnotations.initMocks(this) - // Mocked dependencies - mDependency.injectMockDependency(AccessibilityController::class.java) - mDependency.injectMockDependency(ActivityStarter::class.java) - mDependency.injectMockDependency(AssistManager::class.java) - mDependency.injectTestDependency(Executor::class.java, Executor { it.run() }) - mDependency.injectMockDependency(FlashlightController::class.java) - mDependency.injectMockDependency(KeyguardStateController::class.java) - mDependency.injectMockDependency(TunerService::class.java) - - mKeyguardBottomArea = LayoutInflater.from(mContext).inflate( - R.layout.keyguard_bottom_area, null, false) as KeyguardBottomAreaView - } - - @Test - fun initFrom_doesntCrash() { - val other = LayoutInflater.from(mContext).inflate(R.layout.keyguard_bottom_area, - null, false) as KeyguardBottomAreaView - - other.initFrom(mKeyguardBottomArea) - } -} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java index 60a3d95e24f6..ab209d130b2f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java @@ -408,6 +408,16 @@ public class KeyguardBouncerTest extends SysuiTestCase { mBouncer.hide(false /* destroyView */); verify(mHandler).removeCallbacks(eq(showRunnable.getValue())); } + + @Test + public void testShow_doesNotDelaysIfFaceAuthIsLockedOut() { + when(mKeyguardStateController.isFaceAuthEnabled()).thenReturn(true); + when(mKeyguardUpdateMonitor.isFaceLockedOut()).thenReturn(true); + mBouncer.show(true /* reset */); + + verify(mHandler, never()).postDelayed(any(), anyLong()); + } + @Test public void testShow_delaysIfFaceAuthIsRunning_unlessBypassEnabled() { when(mKeyguardStateController.isFaceAuthEnabled()).thenReturn(true); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java index 7cd275db1ed6..4d1a52c494ab 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java @@ -59,16 +59,19 @@ import com.android.systemui.animation.ShadeInterpolation; import com.android.systemui.dock.DockManager; import com.android.systemui.keyguard.KeyguardUnlockAnimationController; import com.android.systemui.scrim.ScrimView; -import com.android.systemui.statusbar.policy.ConfigurationController; +import com.android.systemui.statusbar.policy.FakeConfigurationController; import com.android.systemui.statusbar.policy.KeyguardStateController; import com.android.systemui.util.concurrency.FakeExecutor; import com.android.systemui.util.time.FakeSystemClock; import com.android.systemui.util.wakelock.DelayedWakeLock; import com.android.systemui.utils.os.FakeHandler; +import com.google.common.truth.Expect; + import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; @@ -86,6 +89,11 @@ import java.util.Map; @SmallTest public class ScrimControllerTest extends SysuiTestCase { + @Rule public Expect mExpect = Expect.create(); + + private final FakeConfigurationController mConfigurationController = + new FakeConfigurationController(); + private ScrimController mScrimController; private ScrimView mScrimBehind; private ScrimView mNotificationsScrim; @@ -96,32 +104,19 @@ public class ScrimControllerTest extends SysuiTestCase { private int mScrimVisibility; private boolean mAlwaysOnEnabled; private TestableLooper mLooper; - @Mock - private AlarmManager mAlarmManager; - @Mock - private DozeParameters mDozeParameters; - @Mock - LightBarController mLightBarController; - @Mock - DelayedWakeLock.Builder mDelayedWakeLockBuilder; - @Mock - private DelayedWakeLock mWakeLock; - @Mock - KeyguardStateController mKeyguardStateController; - @Mock - KeyguardUpdateMonitor mKeyguardUpdateMonitor; - @Mock - private DockManager mDockManager; - @Mock - private ConfigurationController mConfigurationController; - @Mock - private ScreenOffAnimationController mScreenOffAnimationController; - @Mock - private KeyguardUnlockAnimationController mKeyguardUnlockAnimationController; + @Mock private AlarmManager mAlarmManager; + @Mock private DozeParameters mDozeParameters; + @Mock private LightBarController mLightBarController; + @Mock private DelayedWakeLock.Builder mDelayedWakeLockBuilder; + @Mock private DelayedWakeLock mWakeLock; + @Mock private KeyguardStateController mKeyguardStateController; + @Mock private KeyguardUpdateMonitor mKeyguardUpdateMonitor; + @Mock private DockManager mDockManager; + @Mock private ScreenOffAnimationController mScreenOffAnimationController; + @Mock private KeyguardUnlockAnimationController mKeyguardUnlockAnimationController; // TODO(b/204991468): Use a real PanelExpansionStateManager object once this bug is fixed. (The // event-dispatch-on-registration pattern caused some of these unit tests to fail.) - @Mock - private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; + @Mock private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager; private static class AnimatorListener implements Animator.AnimatorListener { private int mNumStarts; @@ -1450,6 +1445,41 @@ public class ScrimControllerTest extends SysuiTestCase { } @Test + public void notificationAlpha_qsNotClipped_alphaMatchesNotificationExpansionProgress() { + mScrimController.setClipsQsScrim(false); + mScrimController.transitionTo(ScrimState.KEYGUARD); + // RawPanelExpansion and QsExpansion are usually used for the notification alpha + // calculation. + // Here we set them to non-zero values explicitly to make sure that in not clipped mode, + // they are not being used even when set. + mScrimController.setRawPanelExpansionFraction(0.5f); + mScrimController.setQsPosition(/* expansionFraction= */ 0.5f, /* qsPanelBottomY= */ 500); + finishAnimationsImmediately(); + + float progress = 0.5f; + + float notificationExpansionProgress = 0f; + mScrimController.setTransitionToFullShadeProgress(progress, notificationExpansionProgress); + mExpect.that(mNotificationsScrim.getViewAlpha()).isEqualTo(notificationExpansionProgress); + + notificationExpansionProgress = 0.25f; + mScrimController.setTransitionToFullShadeProgress(progress, notificationExpansionProgress); + mExpect.that(mNotificationsScrim.getViewAlpha()).isEqualTo(notificationExpansionProgress); + + notificationExpansionProgress = 0.5f; + mScrimController.setTransitionToFullShadeProgress(progress, notificationExpansionProgress); + mExpect.that(mNotificationsScrim.getViewAlpha()).isEqualTo(notificationExpansionProgress); + + notificationExpansionProgress = 0.75f; + mScrimController.setTransitionToFullShadeProgress(progress, notificationExpansionProgress); + mExpect.that(mNotificationsScrim.getViewAlpha()).isEqualTo(notificationExpansionProgress); + + notificationExpansionProgress = 1f; + mScrimController.setTransitionToFullShadeProgress(progress, notificationExpansionProgress); + mExpect.that(mNotificationsScrim.getViewAlpha()).isEqualTo(notificationExpansionProgress); + } + + @Test public void setNotificationsOverScrollAmount_setsTranslationYOnNotificationsScrim() { int overScrollAmount = 10; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java index 2dcdcfce56eb..e790d85763d0 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java @@ -51,6 +51,7 @@ import com.android.systemui.shade.NotificationPanelViewController; import com.android.systemui.shade.ShadeController; import com.android.systemui.statusbar.NotificationMediaManager; import com.android.systemui.statusbar.NotificationShadeWindowController; +import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.SysuiStatusBarStateController; import com.android.systemui.statusbar.phone.panelstate.PanelExpansionChangeEvent; import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager; @@ -277,6 +278,17 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase { } @Test + public void onPanelExpansionChanged_neverTranslatesBouncerWhenShadeLocked() { + when(mStatusBarStateController.getState()).thenReturn(StatusBarState.SHADE_LOCKED); + mStatusBarKeyguardViewManager.onPanelExpansionChanged( + expansionEvent( + /* fraction= */ KeyguardBouncer.EXPANSION_VISIBLE, + /* expanded= */ true, + /* tracking= */ false)); + verify(mBouncer, never()).setExpansion(anyFloat()); + } + + @Test public void setOccluded_animatesPanelExpansion_onlyIfBouncerHidden() { mStatusBarKeyguardViewManager.setOccluded(false /* occluded */, true /* animated */); verify(mCentralSurfaces).animateKeyguardUnoccluding(); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/data/repository/ConnectivityRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/data/repository/ConnectivityRepositoryImplTest.kt new file mode 100644 index 000000000000..6dbee2f26ff9 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/data/repository/ConnectivityRepositoryImplTest.kt @@ -0,0 +1,295 @@ +/* + * 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.pipeline.shared.data.repository + +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.dump.DumpManager +import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger +import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlot +import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlots +import com.android.systemui.statusbar.pipeline.shared.data.repository.ConnectivityRepositoryImpl.Companion.DEFAULT_HIDDEN_ICONS_RESOURCE +import com.android.systemui.statusbar.pipeline.shared.data.repository.ConnectivityRepositoryImpl.Companion.HIDDEN_ICONS_TUNABLE_KEY +import com.android.systemui.tuner.TunerService +import com.android.systemui.util.mockito.any +import com.android.systemui.util.mockito.argumentCaptor +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.cancel +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.yield +import org.junit.After +import org.junit.Before +import org.junit.Test +import org.mockito.Mock +import org.mockito.Mockito +import org.mockito.Mockito.`when` as whenever +import org.mockito.MockitoAnnotations + +@OptIn(ExperimentalCoroutinesApi::class) +@SmallTest +class ConnectivityRepositoryImplTest : SysuiTestCase() { + + private lateinit var underTest: ConnectivityRepositoryImpl + + @Mock private lateinit var connectivitySlots: ConnectivitySlots + @Mock private lateinit var dumpManager: DumpManager + @Mock private lateinit var logger: ConnectivityPipelineLogger + private lateinit var scope: CoroutineScope + @Mock private lateinit var tunerService: TunerService + + @Before + fun setUp() { + MockitoAnnotations.initMocks(this) + scope = CoroutineScope(IMMEDIATE) + + underTest = ConnectivityRepositoryImpl( + connectivitySlots, + context, + dumpManager, + logger, + scope, + tunerService, + ) + } + + @After + fun tearDown() { + scope.cancel() + } + + @Test + fun forceHiddenSlots_initiallyGetsDefault() = runBlocking(IMMEDIATE) { + setUpEthernetWifiMobileSlotNames() + context.getOrCreateTestableResources().addOverride( + DEFAULT_HIDDEN_ICONS_RESOURCE, + arrayOf(SLOT_WIFI, SLOT_ETHERNET) + ) + // Re-create our [ConnectivityRepositoryImpl], since it fetches + // config_statusBarIconsToExclude when it's first constructed + underTest = ConnectivityRepositoryImpl( + connectivitySlots, + context, + dumpManager, + logger, + scope, + tunerService, + ) + + var latest: Set<ConnectivitySlot>? = null + val job = underTest + .forceHiddenSlots + .onEach { latest = it } + .launchIn(this) + + assertThat(latest).containsExactly(ConnectivitySlot.ETHERNET, ConnectivitySlot.WIFI) + + job.cancel() + } + + @Test + fun forceHiddenSlots_slotNamesAdded_flowHasSlots() = runBlocking(IMMEDIATE) { + setUpEthernetWifiMobileSlotNames() + + var latest: Set<ConnectivitySlot>? = null + val job = underTest + .forceHiddenSlots + .onEach { latest = it } + .launchIn(this) + + getTunable().onTuningChanged(HIDDEN_ICONS_TUNABLE_KEY, SLOT_MOBILE) + + assertThat(latest).containsExactly(ConnectivitySlot.MOBILE) + + job.cancel() + } + + @Test + fun forceHiddenSlots_wrongKey_doesNotUpdate() = runBlocking(IMMEDIATE) { + setUpEthernetWifiMobileSlotNames() + + var latest: Set<ConnectivitySlot>? = null + val job = underTest + .forceHiddenSlots + .onEach { latest = it } + .launchIn(this) + + getTunable().onTuningChanged(HIDDEN_ICONS_TUNABLE_KEY, SLOT_MOBILE) + + // WHEN onTuningChanged with the wrong key + getTunable().onTuningChanged("wrongKey", SLOT_WIFI) + yield() + + // THEN we didn't update our value and still have the old one + assertThat(latest).containsExactly(ConnectivitySlot.MOBILE) + + job.cancel() + } + + @Test + fun forceHiddenSlots_slotNamesAddedThenNull_flowHasDefault() = runBlocking(IMMEDIATE) { + setUpEthernetWifiMobileSlotNames() + context.getOrCreateTestableResources().addOverride( + DEFAULT_HIDDEN_ICONS_RESOURCE, + arrayOf(SLOT_WIFI, SLOT_ETHERNET) + ) + // Re-create our [ConnectivityRepositoryImpl], since it fetches + // config_statusBarIconsToExclude when it's first constructed + underTest = ConnectivityRepositoryImpl( + connectivitySlots, + context, + dumpManager, + logger, + scope, + tunerService, + ) + + var latest: Set<ConnectivitySlot>? = null + val job = underTest + .forceHiddenSlots + .onEach { latest = it } + .launchIn(this) + + // First, update the slots + getTunable().onTuningChanged(HIDDEN_ICONS_TUNABLE_KEY, SLOT_MOBILE) + assertThat(latest).containsExactly(ConnectivitySlot.MOBILE) + + // WHEN we update to a null value + getTunable().onTuningChanged(HIDDEN_ICONS_TUNABLE_KEY, null) + yield() + + // THEN we go back to our default value + assertThat(latest).containsExactly(ConnectivitySlot.ETHERNET, ConnectivitySlot.WIFI) + + job.cancel() + } + + @Test + fun forceHiddenSlots_someInvalidSlotNames_flowHasValidSlotsOnly() = runBlocking(IMMEDIATE) { + var latest: Set<ConnectivitySlot>? = null + val job = underTest + .forceHiddenSlots + .onEach { latest = it } + .launchIn(this) + + whenever(connectivitySlots.getSlotFromName(SLOT_WIFI)) + .thenReturn(ConnectivitySlot.WIFI) + whenever(connectivitySlots.getSlotFromName(SLOT_MOBILE)).thenReturn(null) + + getTunable().onTuningChanged(HIDDEN_ICONS_TUNABLE_KEY, "$SLOT_WIFI,$SLOT_MOBILE") + + assertThat(latest).containsExactly(ConnectivitySlot.WIFI) + + job.cancel() + } + + @Test + fun forceHiddenSlots_someEmptySlotNames_flowHasValidSlotsOnly() = runBlocking(IMMEDIATE) { + setUpEthernetWifiMobileSlotNames() + + var latest: Set<ConnectivitySlot>? = null + val job = underTest + .forceHiddenSlots + .onEach { latest = it } + .launchIn(this) + + // WHEN there's empty and blank slot names + getTunable().onTuningChanged( + HIDDEN_ICONS_TUNABLE_KEY, "$SLOT_MOBILE, ,,$SLOT_WIFI" + ) + + // THEN we skip that slot but still process the other ones + assertThat(latest).containsExactly(ConnectivitySlot.WIFI, ConnectivitySlot.MOBILE) + + job.cancel() + } + + @Test + fun forceHiddenSlots_allInvalidOrEmptySlotNames_flowHasEmpty() = runBlocking(IMMEDIATE) { + var latest: Set<ConnectivitySlot>? = null + val job = underTest + .forceHiddenSlots + .onEach { latest = it } + .launchIn(this) + + whenever(connectivitySlots.getSlotFromName(SLOT_WIFI)).thenReturn(null) + whenever(connectivitySlots.getSlotFromName(SLOT_ETHERNET)).thenReturn(null) + whenever(connectivitySlots.getSlotFromName(SLOT_MOBILE)).thenReturn(null) + + getTunable().onTuningChanged( + HIDDEN_ICONS_TUNABLE_KEY, "$SLOT_MOBILE,,$SLOT_WIFI,$SLOT_ETHERNET,,," + ) + + assertThat(latest).isEmpty() + + job.cancel() + } + + @Test + fun forceHiddenSlots_newSubscriberGetsCurrentValue() = runBlocking(IMMEDIATE) { + setUpEthernetWifiMobileSlotNames() + + var latest1: Set<ConnectivitySlot>? = null + val job1 = underTest + .forceHiddenSlots + .onEach { latest1 = it } + .launchIn(this) + + getTunable().onTuningChanged(HIDDEN_ICONS_TUNABLE_KEY, "$SLOT_WIFI,$SLOT_ETHERNET") + + assertThat(latest1).containsExactly(ConnectivitySlot.WIFI, ConnectivitySlot.ETHERNET) + + // WHEN we add a second subscriber after having already emitted a value + var latest2: Set<ConnectivitySlot>? = null + val job2 = underTest + .forceHiddenSlots + .onEach { latest2 = it } + .launchIn(this) + + // THEN the second subscribe receives the already-emitted value + assertThat(latest2).containsExactly(ConnectivitySlot.WIFI, ConnectivitySlot.ETHERNET) + + job1.cancel() + job2.cancel() + } + + private fun getTunable(): TunerService.Tunable { + val callbackCaptor = argumentCaptor<TunerService.Tunable>() + Mockito.verify(tunerService).addTunable(callbackCaptor.capture(), any()) + return callbackCaptor.value!! + } + + private fun setUpEthernetWifiMobileSlotNames() { + whenever(connectivitySlots.getSlotFromName(SLOT_ETHERNET)) + .thenReturn(ConnectivitySlot.ETHERNET) + whenever(connectivitySlots.getSlotFromName(SLOT_WIFI)) + .thenReturn(ConnectivitySlot.WIFI) + whenever(connectivitySlots.getSlotFromName(SLOT_MOBILE)) + .thenReturn(ConnectivitySlot.MOBILE) + } + + companion object { + private const val SLOT_ETHERNET = "ethernet" + private const val SLOT_WIFI = "wifi" + private const val SLOT_MOBILE = "mobile" + private val IMMEDIATE = Dispatchers.Main.immediate + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/data/repository/FakeConnectivityRepository.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/data/repository/FakeConnectivityRepository.kt new file mode 100644 index 000000000000..bd70034b13de --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/pipeline/shared/data/repository/FakeConnectivityRepository.kt @@ -0,0 +1,32 @@ +/* + * 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.pipeline.shared.data.repository + +import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlot +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow + +/** Fake implementation of [ConnectivityRepository] exposing set methods for all the flows. */ +class FakeConnectivityRepository : ConnectivityRepository { + private val _forceHiddenIcons: MutableStateFlow<Set<ConnectivitySlot>> = + MutableStateFlow(emptySet()) + override val forceHiddenSlots: StateFlow<Set<ConnectivitySlot>> = _forceHiddenIcons + + fun setForceHiddenIcons(hiddenIcons: Set<ConnectivitySlot>) { + _forceHiddenIcons.value = hiddenIcons + } +} 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/WifiInteractorTest.kt index 9d8b4bcabc8a..e896749d9a94 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/WifiInteractorTest.kt @@ -18,6 +18,8 @@ package com.android.systemui.statusbar.pipeline.wifi.domain.interactor import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase +import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlot +import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiActivityModel import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiNetworkModel import com.android.systemui.statusbar.pipeline.wifi.data.repository.FakeWifiRepository @@ -37,18 +39,22 @@ class WifiInteractorTest : SysuiTestCase() { private lateinit var underTest: WifiInteractor - private lateinit var repository: FakeWifiRepository + private lateinit var connectivityRepository: FakeConnectivityRepository + private lateinit var wifiRepository: FakeWifiRepository @Before fun setUp() { - repository = FakeWifiRepository() - underTest = WifiInteractor(repository) + connectivityRepository = FakeConnectivityRepository() + wifiRepository = FakeWifiRepository() + underTest = WifiInteractor(connectivityRepository, wifiRepository) } @Test fun hasActivityIn_noInOrOut_outputsFalse() = runBlocking(IMMEDIATE) { - repository.setWifiNetwork(VALID_WIFI_NETWORK_MODEL) - repository.setWifiActivity(WifiActivityModel(hasActivityIn = false, hasActivityOut = false)) + wifiRepository.setWifiNetwork(VALID_WIFI_NETWORK_MODEL) + wifiRepository.setWifiActivity( + WifiActivityModel(hasActivityIn = false, hasActivityOut = false) + ) var latest: Boolean? = null val job = underTest @@ -63,8 +69,10 @@ class WifiInteractorTest : SysuiTestCase() { @Test fun hasActivityIn_onlyOut_outputsFalse() = runBlocking(IMMEDIATE) { - repository.setWifiNetwork(VALID_WIFI_NETWORK_MODEL) - repository.setWifiActivity(WifiActivityModel(hasActivityIn = false, hasActivityOut = true)) + wifiRepository.setWifiNetwork(VALID_WIFI_NETWORK_MODEL) + wifiRepository.setWifiActivity( + WifiActivityModel(hasActivityIn = false, hasActivityOut = true) + ) var latest: Boolean? = null val job = underTest @@ -79,8 +87,10 @@ class WifiInteractorTest : SysuiTestCase() { @Test fun hasActivityIn_onlyIn_outputsTrue() = runBlocking(IMMEDIATE) { - repository.setWifiNetwork(VALID_WIFI_NETWORK_MODEL) - repository.setWifiActivity(WifiActivityModel(hasActivityIn = true, hasActivityOut = false)) + wifiRepository.setWifiNetwork(VALID_WIFI_NETWORK_MODEL) + wifiRepository.setWifiActivity( + WifiActivityModel(hasActivityIn = true, hasActivityOut = false) + ) var latest: Boolean? = null val job = underTest @@ -95,8 +105,10 @@ class WifiInteractorTest : SysuiTestCase() { @Test fun hasActivityIn_inAndOut_outputsTrue() = runBlocking(IMMEDIATE) { - repository.setWifiNetwork(VALID_WIFI_NETWORK_MODEL) - repository.setWifiActivity(WifiActivityModel(hasActivityIn = true, hasActivityOut = true)) + wifiRepository.setWifiNetwork(VALID_WIFI_NETWORK_MODEL) + wifiRepository.setWifiActivity( + WifiActivityModel(hasActivityIn = true, hasActivityOut = true) + ) var latest: Boolean? = null val job = underTest @@ -111,8 +123,10 @@ class WifiInteractorTest : SysuiTestCase() { @Test fun hasActivityIn_ssidNull_outputsFalse() = runBlocking(IMMEDIATE) { - repository.setWifiNetwork(WifiNetworkModel.Active(networkId = 1, ssid = null)) - repository.setWifiActivity(WifiActivityModel(hasActivityIn = true, hasActivityOut = true)) + wifiRepository.setWifiNetwork(WifiNetworkModel.Active(networkId = 1, ssid = null)) + wifiRepository.setWifiActivity( + WifiActivityModel(hasActivityIn = true, hasActivityOut = true) + ) var latest: Boolean? = null val job = underTest @@ -127,8 +141,10 @@ class WifiInteractorTest : SysuiTestCase() { @Test fun hasActivityIn_inactiveNetwork_outputsFalse() = runBlocking(IMMEDIATE) { - repository.setWifiNetwork(WifiNetworkModel.Inactive) - repository.setWifiActivity(WifiActivityModel(hasActivityIn = true, hasActivityOut = true)) + wifiRepository.setWifiNetwork(WifiNetworkModel.Inactive) + wifiRepository.setWifiActivity( + WifiActivityModel(hasActivityIn = true, hasActivityOut = true) + ) var latest: Boolean? = null val job = underTest @@ -143,8 +159,10 @@ class WifiInteractorTest : SysuiTestCase() { @Test fun hasActivityIn_carrierMergedNetwork_outputsFalse() = runBlocking(IMMEDIATE) { - repository.setWifiNetwork(WifiNetworkModel.CarrierMerged) - repository.setWifiActivity(WifiActivityModel(hasActivityIn = true, hasActivityOut = true)) + wifiRepository.setWifiNetwork(WifiNetworkModel.CarrierMerged) + wifiRepository.setWifiActivity( + WifiActivityModel(hasActivityIn = true, hasActivityOut = true) + ) var latest: Boolean? = null val job = underTest @@ -159,7 +177,7 @@ class WifiInteractorTest : SysuiTestCase() { @Test fun hasActivityIn_multipleChanges_multipleOutputChanges() = runBlocking(IMMEDIATE) { - repository.setWifiNetwork(VALID_WIFI_NETWORK_MODEL) + wifiRepository.setWifiNetwork(VALID_WIFI_NETWORK_MODEL) var latest: Boolean? = null val job = underTest @@ -168,23 +186,33 @@ class WifiInteractorTest : SysuiTestCase() { .launchIn(this) // Conduct a series of changes and verify we catch each of them in succession - repository.setWifiActivity(WifiActivityModel(hasActivityIn = true, hasActivityOut = false)) + wifiRepository.setWifiActivity( + WifiActivityModel(hasActivityIn = true, hasActivityOut = false) + ) yield() assertThat(latest).isTrue() - repository.setWifiActivity(WifiActivityModel(hasActivityIn = false, hasActivityOut = true)) + wifiRepository.setWifiActivity( + WifiActivityModel(hasActivityIn = false, hasActivityOut = true) + ) yield() assertThat(latest).isFalse() - repository.setWifiActivity(WifiActivityModel(hasActivityIn = true, hasActivityOut = true)) + wifiRepository.setWifiActivity( + WifiActivityModel(hasActivityIn = true, hasActivityOut = true) + ) yield() assertThat(latest).isTrue() - repository.setWifiActivity(WifiActivityModel(hasActivityIn = true, hasActivityOut = false)) + wifiRepository.setWifiActivity( + WifiActivityModel(hasActivityIn = true, hasActivityOut = false) + ) yield() assertThat(latest).isTrue() - repository.setWifiActivity(WifiActivityModel(hasActivityIn = false, hasActivityOut = false)) + wifiRepository.setWifiActivity( + WifiActivityModel(hasActivityIn = false, hasActivityOut = false) + ) yield() assertThat(latest).isFalse() @@ -200,7 +228,7 @@ class WifiInteractorTest : SysuiTestCase() { ssid = "AB", passpointProviderFriendlyName = "friendly" ) - repository.setWifiNetwork(wifiNetwork) + wifiRepository.setWifiNetwork(wifiNetwork) var latest: WifiNetworkModel? = null val job = underTest @@ -213,6 +241,36 @@ class WifiInteractorTest : SysuiTestCase() { job.cancel() } + @Test + fun isForceHidden_repoHasWifiHidden_outputsTrue() = runBlocking(IMMEDIATE) { + connectivityRepository.setForceHiddenIcons(setOf(ConnectivitySlot.WIFI)) + + var latest: Boolean? = null + val job = underTest + .isForceHidden + .onEach { latest = it } + .launchIn(this) + + assertThat(latest).isTrue() + + job.cancel() + } + + @Test + fun isForceHidden_repoDoesNotHaveWifiHidden_outputsFalse() = runBlocking(IMMEDIATE) { + connectivityRepository.setForceHiddenIcons(setOf()) + + var latest: Boolean? = null + val job = underTest + .isForceHidden + .onEach { latest = it } + .launchIn(this) + + assertThat(latest).isFalse() + + job.cancel() + } + companion object { val VALID_WIFI_NETWORK_MODEL = WifiNetworkModel.Active(networkId = 1, ssid = "AB") } 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 f0a775b52297..43103a065e68 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 @@ -17,17 +17,24 @@ package com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel import androidx.test.filters.SmallTest +import com.android.settingslib.AccessibilityContentDescriptions.WIFI_CONNECTION_STRENGTH +import com.android.settingslib.AccessibilityContentDescriptions.WIFI_NO_CONNECTION import com.android.systemui.SysuiTestCase +import com.android.systemui.common.shared.model.ContentDescription +import com.android.systemui.common.shared.model.Icon import com.android.systemui.statusbar.connectivity.WifiIcons.WIFI_FULL_ICONS import com.android.systemui.statusbar.connectivity.WifiIcons.WIFI_NO_INTERNET_ICONS import com.android.systemui.statusbar.connectivity.WifiIcons.WIFI_NO_NETWORK import com.android.systemui.statusbar.pipeline.StatusBarPipelineFlags import com.android.systemui.statusbar.pipeline.shared.ConnectivityPipelineLogger +import com.android.systemui.statusbar.pipeline.shared.data.model.ConnectivitySlot +import com.android.systemui.statusbar.pipeline.shared.data.repository.FakeConnectivityRepository import com.android.systemui.statusbar.pipeline.wifi.data.model.WifiActivityModel 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.shared.WifiConstants +import com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel.WifiViewModel.Companion.NO_INTERNET import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -50,60 +57,101 @@ class WifiViewModelTest : SysuiTestCase() { @Mock private lateinit var statusBarPipelineFlags: StatusBarPipelineFlags @Mock private lateinit var logger: ConnectivityPipelineLogger @Mock private lateinit var constants: WifiConstants - private lateinit var repository: FakeWifiRepository + private lateinit var connectivityRepository: FakeConnectivityRepository + private lateinit var wifiRepository: FakeWifiRepository private lateinit var interactor: WifiInteractor @Before fun setUp() { MockitoAnnotations.initMocks(this) - repository = FakeWifiRepository() - interactor = WifiInteractor(repository) + connectivityRepository = FakeConnectivityRepository() + wifiRepository = FakeWifiRepository() + interactor = WifiInteractor(connectivityRepository, wifiRepository) underTest = WifiViewModel( statusBarPipelineFlags, constants, + context, logger, interactor ) } @Test - fun wifiIconResId_inactiveNetwork_outputsNoNetworkIcon() = runBlocking(IMMEDIATE) { - repository.setWifiNetwork(WifiNetworkModel.Inactive) + fun wifiIcon_forceHidden_outputsNull() = runBlocking(IMMEDIATE) { + connectivityRepository.setForceHiddenIcons(setOf(ConnectivitySlot.WIFI)) + wifiRepository.setWifiNetwork(WifiNetworkModel.Active(NETWORK_ID, level = 2)) - var latest: Int? = null + var latest: Icon? = null val job = underTest - .wifiIconResId - .onEach { latest = it } - .launchIn(this) + .wifiIcon + .onEach { latest = it } + .launchIn(this) - assertThat(latest).isEqualTo(WIFI_NO_NETWORK) + assertThat(latest).isNull() job.cancel() } @Test - fun wifiIconResId_carrierMergedNetwork_outputsNull() = runBlocking(IMMEDIATE) { - repository.setWifiNetwork(WifiNetworkModel.CarrierMerged) + fun wifiIcon_notForceHidden_outputsVisible() = runBlocking(IMMEDIATE) { + connectivityRepository.setForceHiddenIcons(setOf()) + wifiRepository.setWifiNetwork(WifiNetworkModel.Active(NETWORK_ID, level = 2)) - var latest: Int? = null + var latest: Icon? = null val job = underTest - .wifiIconResId + .wifiIcon + .onEach { latest = it } + .launchIn(this) + + assertThat(latest).isInstanceOf(Icon.Resource::class.java) + + job.cancel() + } + + @Test + fun wifiIcon_inactiveNetwork_outputsNoNetworkIcon() = runBlocking(IMMEDIATE) { + wifiRepository.setWifiNetwork(WifiNetworkModel.Inactive) + + var latest: Icon? = null + val job = underTest + .wifiIcon .onEach { latest = it } .launchIn(this) + assertThat(latest).isInstanceOf(Icon.Resource::class.java) + val icon = latest as Icon.Resource + assertThat(icon.res).isEqualTo(WIFI_NO_NETWORK) + assertThat(icon.contentDescription?.getAsString()) + .contains(context.getString(WIFI_NO_CONNECTION)) + assertThat(icon.contentDescription?.getAsString()) + .contains(context.getString(NO_INTERNET)) + + job.cancel() + } + + @Test + fun wifiIcon_carrierMergedNetwork_outputsNull() = runBlocking(IMMEDIATE) { + wifiRepository.setWifiNetwork(WifiNetworkModel.CarrierMerged) + + var latest: Icon? = null + val job = underTest + .wifiIcon + .onEach { latest = it } + .launchIn(this) + assertThat(latest).isNull() job.cancel() } @Test - fun wifiIconResId_isActiveNullLevel_outputsNull() = runBlocking(IMMEDIATE) { - repository.setWifiNetwork(WifiNetworkModel.Active(NETWORK_ID, level = null)) + fun wifiIcon_isActiveNullLevel_outputsNull() = runBlocking(IMMEDIATE) { + wifiRepository.setWifiNetwork(WifiNetworkModel.Active(NETWORK_ID, level = null)) - var latest: Int? = null + var latest: Icon? = null val job = underTest - .wifiIconResId + .wifiIcon .onEach { latest = it } .launchIn(this) @@ -113,10 +161,10 @@ class WifiViewModelTest : SysuiTestCase() { } @Test - fun wifiIconResId_isActiveAndValidated_level1_outputsFull1Icon() = runBlocking(IMMEDIATE) { + fun wifiIcon_isActiveAndValidated_level1_outputsFull1Icon() = runBlocking(IMMEDIATE) { val level = 1 - repository.setWifiNetwork( + wifiRepository.setWifiNetwork( WifiNetworkModel.Active( NETWORK_ID, isValidated = true, @@ -124,22 +172,28 @@ class WifiViewModelTest : SysuiTestCase() { ) ) - var latest: Int? = null + var latest: Icon? = null val job = underTest - .wifiIconResId - .onEach { latest = it } - .launchIn(this) + .wifiIcon + .onEach { latest = it } + .launchIn(this) - assertThat(latest).isEqualTo(WIFI_FULL_ICONS[level]) + assertThat(latest).isInstanceOf(Icon.Resource::class.java) + val icon = latest as Icon.Resource + assertThat(icon.res).isEqualTo(WIFI_FULL_ICONS[level]) + assertThat(icon.contentDescription?.getAsString()) + .contains(context.getString(WIFI_CONNECTION_STRENGTH[level])) + assertThat(icon.contentDescription?.getAsString()) + .doesNotContain(context.getString(NO_INTERNET)) job.cancel() } @Test - fun wifiIconResId_isActiveAndNotValidated_level4_outputsEmpty4Icon() = runBlocking(IMMEDIATE) { + fun wifiIcon_isActiveAndNotValidated_level4_outputsEmpty4Icon() = runBlocking(IMMEDIATE) { val level = 4 - repository.setWifiNetwork( + wifiRepository.setWifiNetwork( WifiNetworkModel.Active( NETWORK_ID, isValidated = false, @@ -147,13 +201,19 @@ class WifiViewModelTest : SysuiTestCase() { ) ) - var latest: Int? = null + var latest: Icon? = null val job = underTest - .wifiIconResId - .onEach { latest = it } - .launchIn(this) + .wifiIcon + .onEach { latest = it } + .launchIn(this) - assertThat(latest).isEqualTo(WIFI_NO_INTERNET_ICONS[level]) + assertThat(latest).isInstanceOf(Icon.Resource::class.java) + val icon = latest as Icon.Resource + assertThat(icon.res).isEqualTo(WIFI_NO_INTERNET_ICONS[level]) + assertThat(icon.contentDescription?.getAsString()) + .contains(context.getString(WIFI_CONNECTION_STRENGTH[level])) + assertThat(icon.contentDescription?.getAsString()) + .contains(context.getString(NO_INTERNET)) job.cancel() } @@ -161,7 +221,7 @@ class WifiViewModelTest : SysuiTestCase() { @Test fun activityInVisible_showActivityConfigFalse_outputsFalse() = runBlocking(IMMEDIATE) { whenever(constants.shouldShowActivityConfig).thenReturn(false) - repository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK) + wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK) var latest: Boolean? = null val job = underTest @@ -178,7 +238,7 @@ class WifiViewModelTest : SysuiTestCase() { @Test fun activityInVisible_showActivityConfigFalse_noUpdatesReceived() = runBlocking(IMMEDIATE) { whenever(constants.shouldShowActivityConfig).thenReturn(false) - repository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK) + wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK) var latest: Boolean? = null val job = underTest @@ -187,7 +247,9 @@ class WifiViewModelTest : SysuiTestCase() { .launchIn(this) // Update the repo to have activityIn - repository.setWifiActivity(WifiActivityModel(hasActivityIn = true, hasActivityOut = false)) + wifiRepository.setWifiActivity( + WifiActivityModel(hasActivityIn = true, hasActivityOut = false) + ) yield() // Verify that we didn't update to activityIn=true (because our config is false) @@ -199,7 +261,7 @@ class WifiViewModelTest : SysuiTestCase() { @Test fun activityInVisible_showActivityConfigTrue_outputsUpdate() = runBlocking(IMMEDIATE) { whenever(constants.shouldShowActivityConfig).thenReturn(true) - repository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK) + wifiRepository.setWifiNetwork(ACTIVE_VALID_WIFI_NETWORK) var latest: Boolean? = null val job = underTest @@ -208,7 +270,9 @@ class WifiViewModelTest : SysuiTestCase() { .launchIn(this) // Update the repo to have activityIn - repository.setWifiActivity(WifiActivityModel(hasActivityIn = true, hasActivityOut = false)) + wifiRepository.setWifiActivity( + WifiActivityModel(hasActivityIn = true, hasActivityOut = false) + ) yield() // Verify that we updated to activityIn=true @@ -217,6 +281,13 @@ class WifiViewModelTest : SysuiTestCase() { job.cancel() } + private fun ContentDescription.getAsString(): String? { + return when (this) { + is ContentDescription.Loaded -> this.description + is ContentDescription.Resource -> context.getString(this.res) + } + } + companion object { private const val NETWORK_ID = 2 private val ACTIVE_VALID_WIFI_NETWORK = WifiNetworkModel.Active(NETWORK_ID, ssid = "AB") diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BluetoothControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BluetoothControllerImplTest.java index 3dd36d134cf7..d0391ac0795c 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BluetoothControllerImplTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/BluetoothControllerImplTest.java @@ -41,6 +41,7 @@ import com.android.settingslib.bluetooth.LocalBluetoothManager; import com.android.settingslib.bluetooth.LocalBluetoothProfile; import com.android.settingslib.bluetooth.LocalBluetoothProfileManager; import com.android.systemui.SysuiTestCase; +import com.android.systemui.bluetooth.BluetoothLogger; import com.android.systemui.dump.DumpManager; import org.junit.Before; @@ -81,6 +82,7 @@ public class BluetoothControllerImplTest extends SysuiTestCase { mBluetoothControllerImpl = new BluetoothControllerImpl(mContext, mMockDumpManager, + mock(BluetoothLogger.class), mTestableLooper.getLooper(), mTestableLooper.getLooper(), mMockBluetoothManager); @@ -233,4 +235,11 @@ public class BluetoothControllerImplTest extends SysuiTestCase { assertTrue(mBluetoothControllerImpl.isBluetoothAudioActive()); assertTrue(mBluetoothControllerImpl.isBluetoothAudioProfileOnly()); } + + /** Regression test for b/246876230. */ + @Test + public void testOnActiveDeviceChanged_null_noCrash() { + mBluetoothControllerImpl.onActiveDeviceChanged(null, BluetoothProfile.HEADSET); + // No assert, just need no crash. + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardStateControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardStateControllerTest.java index 4a8170fc2955..8f363efd9f51 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardStateControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardStateControllerTest.java @@ -31,6 +31,7 @@ import androidx.test.filters.SmallTest; import com.android.internal.widget.LockPatternUtils; import com.android.keyguard.KeyguardUpdateMonitor; +import com.android.keyguard.logging.KeyguardUpdateMonitorLogger; import com.android.systemui.SysuiTestCase; import com.android.systemui.dump.DumpManager; import com.android.systemui.keyguard.KeyguardUnlockAnimationController; @@ -57,6 +58,8 @@ public class KeyguardStateControllerTest extends SysuiTestCase { private DumpManager mDumpManager; @Mock private Lazy<KeyguardUnlockAnimationController> mKeyguardUnlockAnimationControllerLazy; + @Mock + private KeyguardUpdateMonitorLogger mLogger; @Before public void setup() { @@ -66,6 +69,7 @@ public class KeyguardStateControllerTest extends SysuiTestCase { mKeyguardUpdateMonitor, mLockPatternUtils, mKeyguardUnlockAnimationControllerLazy, + mLogger, mDumpManager); } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherAdapterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherAdapterTest.kt index c3805ad36533..8290dab19bdf 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherAdapterTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/KeyguardUserSwitcherAdapterTest.kt @@ -57,8 +57,6 @@ class KeyguardUserSwitcherAdapterTest : SysuiTestCase() { @Mock private lateinit var inflatedUserDetailItemView: KeyguardUserDetailItemView @Mock - private lateinit var userInfo: UserInfo - @Mock private lateinit var layoutInflater: LayoutInflater @Mock private lateinit var keyguardUserSwitcherController: KeyguardUserSwitcherController @@ -188,7 +186,7 @@ class KeyguardUserSwitcherAdapterTest : SysuiTestCase() { private fun createUserRecord(isCurrentUser: Boolean, isGuestUser: Boolean) = UserRecord( - userInfo, + UserInfo(0 /* id */, "name", 0 /* flags */), picture, isGuestUser, isCurrentUser, diff --git a/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayControllerTest.kt new file mode 100644 index 000000000000..921b7efc38eb --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TemporaryViewDisplayControllerTest.kt @@ -0,0 +1,250 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.temporarydisplay + +import android.content.Context +import android.os.PowerManager +import android.view.ViewGroup +import android.view.WindowManager +import android.view.accessibility.AccessibilityManager +import androidx.test.filters.SmallTest +import com.android.systemui.R +import com.android.systemui.SysuiTestCase +import com.android.systemui.dagger.qualifiers.Main +import com.android.systemui.statusbar.policy.ConfigurationController +import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener +import com.android.systemui.util.concurrency.DelayableExecutor +import com.android.systemui.util.concurrency.FakeExecutor +import com.android.systemui.util.mockito.any +import com.android.systemui.util.mockito.argumentCaptor +import com.android.systemui.util.mockito.capture +import com.android.systemui.util.time.FakeSystemClock +import com.google.common.truth.Truth.assertThat +import org.junit.Before +import org.junit.Test +import org.mockito.Mock +import org.mockito.Mockito.never +import org.mockito.Mockito.reset +import org.mockito.Mockito.verify +import org.mockito.Mockito.`when` as whenever +import org.mockito.MockitoAnnotations + +@SmallTest +class TemporaryViewDisplayControllerTest : SysuiTestCase() { + private lateinit var underTest: TestController + + private lateinit var fakeClock: FakeSystemClock + private lateinit var fakeExecutor: FakeExecutor + + @Mock + private lateinit var logger: TemporaryViewLogger + @Mock + private lateinit var accessibilityManager: AccessibilityManager + @Mock + private lateinit var configurationController: ConfigurationController + @Mock + private lateinit var windowManager: WindowManager + @Mock + private lateinit var powerManager: PowerManager + + @Before + fun setUp() { + MockitoAnnotations.initMocks(this) + + whenever(accessibilityManager.getRecommendedTimeoutMillis(any(), any())) + .thenReturn(TIMEOUT_MS.toInt()) + + fakeClock = FakeSystemClock() + fakeExecutor = FakeExecutor(fakeClock) + + underTest = TestController( + context, + logger, + windowManager, + fakeExecutor, + accessibilityManager, + configurationController, + powerManager, + ) + } + + @Test + fun displayView_viewAdded() { + underTest.displayView(getState()) + + verify(windowManager).addView(any(), any()) + } + + @Test + fun displayView_screenOff_screenWakes() { + whenever(powerManager.isScreenOn).thenReturn(false) + + underTest.displayView(getState()) + + verify(powerManager).wakeUp(any(), any(), any()) + } + + @Test + fun displayView_screenAlreadyOn_screenNotWoken() { + whenever(powerManager.isScreenOn).thenReturn(true) + + underTest.displayView(getState()) + + verify(powerManager, never()).wakeUp(any(), any(), any()) + } + + @Test + fun displayView_twice_viewNotAddedTwice() { + underTest.displayView(getState()) + reset(windowManager) + + underTest.displayView(getState()) + verify(windowManager, never()).addView(any(), any()) + } + + @Test + fun displayView_viewDoesNotDisappearsBeforeTimeout() { + val state = getState() + underTest.displayView(state) + reset(windowManager) + + fakeClock.advanceTime(TIMEOUT_MS - 1) + + verify(windowManager, never()).removeView(any()) + } + + @Test + fun displayView_viewDisappearsAfterTimeout() { + val state = getState() + underTest.displayView(state) + reset(windowManager) + + fakeClock.advanceTime(TIMEOUT_MS + 1) + + verify(windowManager).removeView(any()) + } + + @Test + fun displayView_calledAgainBeforeTimeout_timeoutReset() { + // First, display the view + val state = getState() + underTest.displayView(state) + + // After some time, re-display the view + val waitTime = 1000L + fakeClock.advanceTime(waitTime) + underTest.displayView(getState()) + + // Wait until the timeout for the first display would've happened + fakeClock.advanceTime(TIMEOUT_MS - waitTime + 1) + + // Verify we didn't hide the view + verify(windowManager, never()).removeView(any()) + } + + @Test + fun displayView_calledAgainBeforeTimeout_eventuallyTimesOut() { + // First, display the view + val state = getState() + underTest.displayView(state) + + // After some time, re-display the view + fakeClock.advanceTime(1000L) + underTest.displayView(getState()) + + // Ensure we still hide the view eventually + fakeClock.advanceTime(TIMEOUT_MS + 1) + + verify(windowManager).removeView(any()) + } + + @Test + fun displayScaleChange_viewReinflatedWithMostRecentState() { + underTest.displayView(getState(name = "First name")) + underTest.displayView(getState(name = "Second name")) + reset(windowManager) + + getConfigurationListener().onDensityOrFontScaleChanged() + + verify(windowManager).removeView(any()) + verify(windowManager).addView(any(), any()) + assertThat(underTest.mostRecentViewInfo?.name).isEqualTo("Second name") + } + + @Test + fun removeView_viewRemovedAndRemovalLogged() { + // First, add the view + underTest.displayView(getState()) + + // Then, remove it + val reason = "test reason" + underTest.removeView(reason) + + verify(windowManager).removeView(any()) + verify(logger).logChipRemoval(reason) + } + + @Test + fun removeView_noAdd_viewNotRemoved() { + underTest.removeView("reason") + + verify(windowManager, never()).removeView(any()) + } + + private fun getState(name: String = "name") = ViewInfo(name) + + private fun getConfigurationListener(): ConfigurationListener { + val callbackCaptor = argumentCaptor<ConfigurationListener>() + verify(configurationController).addCallback(capture(callbackCaptor)) + return callbackCaptor.value + } + + inner class TestController( + context: Context, + logger: TemporaryViewLogger, + windowManager: WindowManager, + @Main mainExecutor: DelayableExecutor, + accessibilityManager: AccessibilityManager, + configurationController: ConfigurationController, + powerManager: PowerManager, + ) : TemporaryViewDisplayController<ViewInfo, TemporaryViewLogger>( + context, + logger, + windowManager, + mainExecutor, + accessibilityManager, + configurationController, + powerManager, + R.layout.media_ttt_chip, + "Window Title", + "WAKE_REASON", + ) { + var mostRecentViewInfo: ViewInfo? = null + + override val windowLayoutParams = commonWindowLayoutParams + override fun updateView(newInfo: ViewInfo, currentView: ViewGroup) { + super.updateView(newInfo, currentView) + mostRecentViewInfo = newInfo + } + } + + inner class ViewInfo(val name: String) : TemporaryViewInfo { + override fun getTimeoutMs() = 1L + } +} + +private const val TIMEOUT_MS = 10000L diff --git a/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TemporaryViewLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TemporaryViewLoggerTest.kt new file mode 100644 index 000000000000..c9f2b4db81ef --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/temporarydisplay/TemporaryViewLoggerTest.kt @@ -0,0 +1,70 @@ +/* + * 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.temporarydisplay + +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.dump.DumpManager +import com.android.systemui.log.LogBuffer +import com.android.systemui.log.LogBufferFactory +import com.android.systemui.log.LogcatEchoTracker +import com.google.common.truth.Truth.assertThat +import java.io.PrintWriter +import java.io.StringWriter +import org.junit.Before +import org.junit.Test +import org.mockito.Mockito + +@SmallTest +class TemporaryViewLoggerTest : SysuiTestCase() { + private lateinit var buffer: LogBuffer + private lateinit var logger: TemporaryViewLogger + + @Before + fun setUp() { + buffer = + LogBufferFactory(DumpManager(), Mockito.mock(LogcatEchoTracker::class.java)) + .create("buffer", 10) + logger = TemporaryViewLogger(buffer, TAG) + } + + @Test + fun logChipAddition_bufferHasLog() { + logger.logChipAddition() + + val stringWriter = StringWriter() + buffer.dump(PrintWriter(stringWriter), tailLength = 0) + val actualString = stringWriter.toString() + + assertThat(actualString).contains(TAG) + } + + @Test + fun logChipRemoval_bufferHasTagAndReason() { + val reason = "test reason" + logger.logChipRemoval(reason) + + val stringWriter = StringWriter() + buffer.dump(PrintWriter(stringWriter), tailLength = 0) + val actualString = stringWriter.toString() + + assertThat(actualString).contains(TAG) + assertThat(actualString).contains(reason) + } +} + +private const val TAG = "TestTag" diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldAodAnimationControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldAodAnimationControllerTest.kt index f51f78315dbd..8645298682d6 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldAodAnimationControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/FoldAodAnimationControllerTest.kt @@ -18,24 +18,28 @@ package com.android.systemui.unfold import android.hardware.devicestate.DeviceStateManager import android.hardware.devicestate.DeviceStateManager.FoldStateListener -import android.os.Handler import android.os.PowerManager import android.testing.AndroidTestingRunner -import android.testing.TestableLooper -import android.testing.TestableLooper.RunWithLooper import android.view.ViewGroup import android.view.ViewTreeObserver import androidx.test.filters.SmallTest import com.android.internal.util.LatencyTracker import com.android.systemui.SysuiTestCase import com.android.systemui.keyguard.WakefulnessLifecycle +import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository +import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor import com.android.systemui.shade.NotificationPanelViewController import com.android.systemui.statusbar.LightRevealScrim import com.android.systemui.statusbar.phone.CentralSurfaces import com.android.systemui.unfold.util.FoldableDeviceStates import com.android.systemui.unfold.util.FoldableTestUtils +import com.android.systemui.util.concurrency.FakeExecutor import com.android.systemui.util.mockito.any import com.android.systemui.util.settings.GlobalSettings +import com.android.systemui.util.time.FakeSystemClock +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.yield import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -49,7 +53,6 @@ import org.mockito.MockitoAnnotations @RunWith(AndroidTestingRunner::class) @SmallTest -@RunWithLooper class FoldAodAnimationControllerTest : SysuiTestCase() { @Mock lateinit var deviceStateManager: DeviceStateManager @@ -74,26 +77,15 @@ class FoldAodAnimationControllerTest : SysuiTestCase() { private lateinit var deviceStates: FoldableDeviceStates - private lateinit var testableLooper: TestableLooper + lateinit var keyguardRepository: FakeKeyguardRepository - lateinit var foldAodAnimationController: FoldAodAnimationController + lateinit var underTest: FoldAodAnimationController + private val fakeExecutor = FakeExecutor(FakeSystemClock()) @Before fun setup() { MockitoAnnotations.initMocks(this) - testableLooper = TestableLooper.get(this) - - foldAodAnimationController = - FoldAodAnimationController( - Handler(testableLooper.looper), - context.mainExecutor, - context, - deviceStateManager, - wakefulnessLifecycle, - globalSettings, - latencyTracker, - ) - .apply { initialize(centralSurfaces, lightRevealScrim) } + deviceStates = FoldableTestUtils.findDeviceStates(context) whenever(notificationPanelViewController.view).thenReturn(viewGroup) @@ -107,60 +99,102 @@ class FoldAodAnimationControllerTest : SysuiTestCase() { val onActionStarted = it.arguments[0] as Runnable onActionStarted.run() } - verify(deviceStateManager).registerCallback(any(), foldStateListenerCaptor.capture()) - foldAodAnimationController.setIsDozing(dozing = true) - setAodEnabled(enabled = true) - sendFoldEvent(folded = false) + keyguardRepository = FakeKeyguardRepository() + val keyguardInteractor = KeyguardInteractor(repository = keyguardRepository) + + // Needs to be run on the main thread + runBlocking(IMMEDIATE) { + underTest = + FoldAodAnimationController( + fakeExecutor, + context, + deviceStateManager, + wakefulnessLifecycle, + globalSettings, + latencyTracker, + { keyguardInteractor }, + ) + .apply { initialize(centralSurfaces, lightRevealScrim) } + + verify(deviceStateManager).registerCallback(any(), foldStateListenerCaptor.capture()) + + setAodEnabled(enabled = true) + sendFoldEvent(folded = false) + } } @Test - fun onFolded_aodDisabled_doesNotLogLatency() { - setAodEnabled(enabled = false) + fun onFolded_aodDisabled_doesNotLogLatency() = + runBlocking(IMMEDIATE) { + val job = underTest.listenForDozing(this) + keyguardRepository.setDozing(true) + setAodEnabled(enabled = false) - fold() - simulateScreenTurningOn() + yield() - verifyNoMoreInteractions(latencyTracker) - } + fold() + simulateScreenTurningOn() + + verifyNoMoreInteractions(latencyTracker) + + job.cancel() + } @Test - fun onFolded_aodEnabled_logsLatency() { - setAodEnabled(enabled = true) + fun onFolded_aodEnabled_logsLatency() = + runBlocking(IMMEDIATE) { + val job = underTest.listenForDozing(this) + keyguardRepository.setDozing(true) + setAodEnabled(enabled = true) - fold() - simulateScreenTurningOn() + yield() - verify(latencyTracker).onActionStart(any()) - verify(latencyTracker).onActionEnd(any()) - } + fold() + simulateScreenTurningOn() + + verify(latencyTracker).onActionStart(any()) + verify(latencyTracker).onActionEnd(any()) + + job.cancel() + } @Test - fun onFolded_animationCancelled_doesNotLogLatency() { - setAodEnabled(enabled = true) + fun onFolded_animationCancelled_doesNotLogLatency() = + runBlocking(IMMEDIATE) { + val job = underTest.listenForDozing(this) + keyguardRepository.setDozing(true) + setAodEnabled(enabled = true) - fold() - foldAodAnimationController.onScreenTurningOn({}) - foldAodAnimationController.onStartedWakingUp() - testableLooper.processAllMessages() + yield() - verify(latencyTracker).onActionStart(any()) - verify(latencyTracker).onActionCancel(any()) - } + fold() + underTest.onScreenTurningOn({}) + underTest.onStartedWakingUp() + fakeExecutor.runAllReady() + + verify(latencyTracker).onActionStart(any()) + verify(latencyTracker).onActionCancel(any()) + + job.cancel() + } private fun simulateScreenTurningOn() { - foldAodAnimationController.onScreenTurningOn({}) - foldAodAnimationController.onScreenTurnedOn() - testableLooper.processAllMessages() + underTest.onScreenTurningOn({}) + underTest.onScreenTurnedOn() + fakeExecutor.runAllReady() } private fun fold() = sendFoldEvent(folded = true) - private fun setAodEnabled(enabled: Boolean) = - foldAodAnimationController.onAlwaysOnChanged(alwaysOn = enabled) + private fun setAodEnabled(enabled: Boolean) = underTest.onAlwaysOnChanged(alwaysOn = enabled) private fun sendFoldEvent(folded: Boolean) { val state = if (folded) deviceStates.folded else deviceStates.unfolded foldStateListenerCaptor.value.onStateChanged(state) } + + companion object { + private val IMMEDIATE = Dispatchers.Main.immediate + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/UserSwitcherActivityTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/UserSwitcherActivityTest.kt index 66367ecfc95c..3968bb798bb7 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/user/UserSwitcherActivityTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/user/UserSwitcherActivityTest.kt @@ -16,23 +16,44 @@ package com.android.systemui.user +import android.app.Application import android.os.UserManager import android.testing.AndroidTestingRunner import android.testing.TestableLooper.RunWithLooper import android.view.LayoutInflater +import android.view.View +import android.view.Window +import android.window.OnBackInvokedCallback +import android.window.OnBackInvokedDispatcher import androidx.test.filters.SmallTest +import com.android.systemui.R import com.android.systemui.SysuiTestCase import com.android.systemui.broadcast.BroadcastDispatcher import com.android.systemui.classifier.FalsingCollector +import com.android.systemui.flags.FeatureFlags import com.android.systemui.plugins.FalsingManager import com.android.systemui.settings.UserTracker import com.android.systemui.statusbar.policy.UserSwitcherController +import com.android.systemui.user.ui.viewmodel.UserSwitcherViewModel +import com.android.systemui.util.concurrency.FakeExecutor +import com.android.systemui.util.time.FakeSystemClock import com.google.common.truth.Truth.assertThat import org.junit.Before import org.junit.Test import org.junit.runner.RunWith +import org.mockito.ArgumentCaptor +import org.mockito.Captor import org.mockito.Mock +import org.mockito.Mockito.`when` +import org.mockito.Mockito.any +import org.mockito.Mockito.anyInt +import org.mockito.Mockito.doNothing +import org.mockito.Mockito.eq +import org.mockito.Mockito.mock +import org.mockito.Mockito.spy +import org.mockito.Mockito.verify import org.mockito.MockitoAnnotations +import java.util.concurrent.Executor @SmallTest @RunWith(AndroidTestingRunner::class) @@ -54,19 +75,49 @@ class UserSwitcherActivityTest : SysuiTestCase() { private lateinit var userManager: UserManager @Mock private lateinit var userTracker: UserTracker + @Mock + private lateinit var flags: FeatureFlags + @Mock + private lateinit var viewModelFactoryLazy: dagger.Lazy<UserSwitcherViewModel.Factory> + @Mock + private lateinit var onBackDispatcher: OnBackInvokedDispatcher + @Mock + private lateinit var decorView: View + @Mock + private lateinit var window: Window + @Mock + private lateinit var userSwitcherRootView: UserSwitcherRootView + @Captor + private lateinit var onBackInvokedCallback: ArgumentCaptor<OnBackInvokedCallback> + var isFinished = false @Before fun setUp() { MockitoAnnotations.initMocks(this) - activity = UserSwitcherActivity( + activity = spy(object : UserSwitcherActivity( userSwitcherController, broadcastDispatcher, - layoutInflater, falsingCollector, falsingManager, userManager, - userTracker - ) + userTracker, + flags, + viewModelFactoryLazy, + ) { + override fun getOnBackInvokedDispatcher() = onBackDispatcher + override fun getMainExecutor(): Executor = FakeExecutor(FakeSystemClock()) + override fun finish() { + isFinished = true + } + }) + `when`(activity.window).thenReturn(window) + `when`(window.decorView).thenReturn(decorView) + `when`(activity.findViewById<UserSwitcherRootView>(R.id.user_switcher_root)) + .thenReturn(userSwitcherRootView) + `when`(activity.findViewById<View>(R.id.cancel)).thenReturn(mock(View::class.java)) + `when`(activity.findViewById<View>(R.id.add)).thenReturn(mock(View::class.java)) + `when`(activity.application).thenReturn(mock(Application::class.java)) + doNothing().`when`(activity).setContentView(anyInt()) } @Test @@ -78,4 +129,24 @@ class UserSwitcherActivityTest : SysuiTestCase() { assertThat(activity.getMaxColumns(7)).isEqualTo(4) assertThat(activity.getMaxColumns(9)).isEqualTo(5) } + + @Test + fun onCreate_callbackRegistration() { + activity.createActivity() + verify(onBackDispatcher).registerOnBackInvokedCallback( + eq(OnBackInvokedDispatcher.PRIORITY_DEFAULT), any()) + + activity.destroyActivity() + verify(onBackDispatcher).unregisterOnBackInvokedCallback(any()) + } + + @Test + fun onBackInvokedCallback_finishesActivity() { + activity.createActivity() + verify(onBackDispatcher).registerOnBackInvokedCallback( + eq(OnBackInvokedDispatcher.PRIORITY_DEFAULT), onBackInvokedCallback.capture()) + + onBackInvokedCallback.value.onBackInvoked() + assertThat(isFinished).isTrue() + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplTest.kt new file mode 100644 index 000000000000..6b466e1ac2d8 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplTest.kt @@ -0,0 +1,217 @@ +/* + * 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.user.data.repository + +import android.content.pm.UserInfo +import android.os.UserManager +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.statusbar.policy.UserSwitcherController +import com.android.systemui.user.data.source.UserRecord +import com.android.systemui.user.shared.model.UserActionModel +import com.android.systemui.user.shared.model.UserModel +import com.android.systemui.util.mockito.any +import com.android.systemui.util.mockito.capture +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.runBlocking +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 +import org.mockito.ArgumentCaptor +import org.mockito.Captor +import org.mockito.Mock +import org.mockito.Mockito.verify +import org.mockito.Mockito.`when` as whenever +import org.mockito.MockitoAnnotations + +@SmallTest +@RunWith(JUnit4::class) +class UserRepositoryImplTest : SysuiTestCase() { + + @Mock private lateinit var manager: UserManager + @Mock private lateinit var controller: UserSwitcherController + @Captor + private lateinit var userSwitchCallbackCaptor: + ArgumentCaptor<UserSwitcherController.UserSwitchCallback> + + private lateinit var underTest: UserRepositoryImpl + + @Before + fun setUp() { + MockitoAnnotations.initMocks(this) + whenever(controller.addUsersFromLockScreen).thenReturn(MutableStateFlow(false)) + whenever(controller.isGuestUserAutoCreated).thenReturn(false) + whenever(controller.isGuestUserResetting).thenReturn(false) + + underTest = + UserRepositoryImpl( + appContext = context, + manager = manager, + controller = controller, + ) + } + + @Test + fun `users - registers for updates`() = + runBlocking(IMMEDIATE) { + val job = underTest.users.onEach {}.launchIn(this) + + verify(controller).addUserSwitchCallback(any()) + + job.cancel() + } + + @Test + fun `users - unregisters from updates`() = + runBlocking(IMMEDIATE) { + val job = underTest.users.onEach {}.launchIn(this) + verify(controller).addUserSwitchCallback(capture(userSwitchCallbackCaptor)) + + job.cancel() + + verify(controller).removeUserSwitchCallback(userSwitchCallbackCaptor.value) + } + + @Test + fun `users - does not include actions`() = + runBlocking(IMMEDIATE) { + whenever(controller.users) + .thenReturn( + arrayListOf( + createUserRecord(0, isSelected = true), + createActionRecord(UserActionModel.ADD_USER), + createUserRecord(1), + createUserRecord(2), + createActionRecord(UserActionModel.ADD_SUPERVISED_USER), + createActionRecord(UserActionModel.ENTER_GUEST_MODE), + ) + ) + var models: List<UserModel>? = null + val job = underTest.users.onEach { models = it }.launchIn(this) + + assertThat(models).hasSize(3) + assertThat(models?.get(0)?.id).isEqualTo(0) + assertThat(models?.get(0)?.isSelected).isTrue() + assertThat(models?.get(1)?.id).isEqualTo(1) + assertThat(models?.get(1)?.isSelected).isFalse() + assertThat(models?.get(2)?.id).isEqualTo(2) + assertThat(models?.get(2)?.isSelected).isFalse() + job.cancel() + } + + @Test + fun selectedUser() = + runBlocking(IMMEDIATE) { + whenever(controller.users) + .thenReturn( + arrayListOf( + createUserRecord(0, isSelected = true), + createUserRecord(1), + createUserRecord(2), + ) + ) + var id: Int? = null + val job = underTest.selectedUser.map { it.id }.onEach { id = it }.launchIn(this) + + assertThat(id).isEqualTo(0) + + whenever(controller.users) + .thenReturn( + arrayListOf( + createUserRecord(0), + createUserRecord(1), + createUserRecord(2, isSelected = true), + ) + ) + verify(controller).addUserSwitchCallback(capture(userSwitchCallbackCaptor)) + userSwitchCallbackCaptor.value.onUserSwitched() + assertThat(id).isEqualTo(2) + + job.cancel() + } + + @Test + fun `actions - unregisters from updates`() = + runBlocking(IMMEDIATE) { + val job = underTest.actions.onEach {}.launchIn(this) + verify(controller).addUserSwitchCallback(capture(userSwitchCallbackCaptor)) + + job.cancel() + + verify(controller).removeUserSwitchCallback(userSwitchCallbackCaptor.value) + } + + @Test + fun `actions - registers for updates`() = + runBlocking(IMMEDIATE) { + val job = underTest.actions.onEach {}.launchIn(this) + + verify(controller).addUserSwitchCallback(any()) + + job.cancel() + } + + @Test + fun `actopms - does not include users`() = + runBlocking(IMMEDIATE) { + whenever(controller.users) + .thenReturn( + arrayListOf( + createUserRecord(0, isSelected = true), + createActionRecord(UserActionModel.ADD_USER), + createUserRecord(1), + createUserRecord(2), + createActionRecord(UserActionModel.ADD_SUPERVISED_USER), + createActionRecord(UserActionModel.ENTER_GUEST_MODE), + ) + ) + var models: List<UserActionModel>? = null + val job = underTest.actions.onEach { models = it }.launchIn(this) + + assertThat(models).hasSize(3) + assertThat(models?.get(0)).isEqualTo(UserActionModel.ADD_USER) + assertThat(models?.get(1)).isEqualTo(UserActionModel.ADD_SUPERVISED_USER) + assertThat(models?.get(2)).isEqualTo(UserActionModel.ENTER_GUEST_MODE) + job.cancel() + } + + private fun createUserRecord(id: Int, isSelected: Boolean = false): UserRecord { + return UserRecord( + info = UserInfo(id, "name$id", 0), + isCurrent = isSelected, + ) + } + + private fun createActionRecord(action: UserActionModel): UserRecord { + return UserRecord( + isAddUser = action == UserActionModel.ADD_USER, + isAddSupervisedUser = action == UserActionModel.ADD_SUPERVISED_USER, + isGuest = action == UserActionModel.ENTER_GUEST_MODE, + ) + } + + companion object { + private val IMMEDIATE = Dispatchers.Main.immediate + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorTest.kt new file mode 100644 index 000000000000..e914e2e0a1da --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/user/domain/interactor/UserInteractorTest.kt @@ -0,0 +1,213 @@ +/* + * 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.user.domain.interactor + +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository +import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor +import com.android.systemui.plugins.ActivityStarter +import com.android.systemui.statusbar.policy.UserSwitcherController +import com.android.systemui.user.data.repository.FakeUserRepository +import com.android.systemui.user.shared.model.UserActionModel +import com.android.systemui.util.mockito.any +import com.android.systemui.util.mockito.eq +import com.android.systemui.util.mockito.nullable +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.runBlocking +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 +import org.mockito.Mock +import org.mockito.Mockito.anyBoolean +import org.mockito.Mockito.verify +import org.mockito.MockitoAnnotations + +@SmallTest +@RunWith(JUnit4::class) +class UserInteractorTest : SysuiTestCase() { + + @Mock private lateinit var controller: UserSwitcherController + @Mock private lateinit var activityStarter: ActivityStarter + + private lateinit var underTest: UserInteractor + + private lateinit var userRepository: FakeUserRepository + private lateinit var keyguardRepository: FakeKeyguardRepository + + @Before + fun setUp() { + MockitoAnnotations.initMocks(this) + + userRepository = FakeUserRepository() + keyguardRepository = FakeKeyguardRepository() + underTest = + UserInteractor( + repository = userRepository, + controller = controller, + activityStarter = activityStarter, + keyguardInteractor = + KeyguardInteractor( + repository = keyguardRepository, + ), + ) + } + + @Test + fun `actions - not actionable when locked and locked - no actions`() = + runBlocking(IMMEDIATE) { + userRepository.setActions(UserActionModel.values().toList()) + userRepository.setActionableWhenLocked(false) + keyguardRepository.setKeyguardShowing(true) + + var actions: List<UserActionModel>? = null + val job = underTest.actions.onEach { actions = it }.launchIn(this) + + assertThat(actions).isEmpty() + job.cancel() + } + + @Test + fun `actions - not actionable when locked and not locked`() = + runBlocking(IMMEDIATE) { + userRepository.setActions( + listOf( + UserActionModel.ENTER_GUEST_MODE, + UserActionModel.ADD_USER, + UserActionModel.ADD_SUPERVISED_USER, + ) + ) + userRepository.setActionableWhenLocked(false) + keyguardRepository.setKeyguardShowing(false) + + var actions: List<UserActionModel>? = null + val job = underTest.actions.onEach { actions = it }.launchIn(this) + + assertThat(actions) + .isEqualTo( + listOf( + UserActionModel.ENTER_GUEST_MODE, + UserActionModel.ADD_USER, + UserActionModel.ADD_SUPERVISED_USER, + UserActionModel.NAVIGATE_TO_USER_MANAGEMENT, + ) + ) + job.cancel() + } + + @Test + fun `actions - actionable when locked and not locked`() = + runBlocking(IMMEDIATE) { + userRepository.setActions( + listOf( + UserActionModel.ENTER_GUEST_MODE, + UserActionModel.ADD_USER, + UserActionModel.ADD_SUPERVISED_USER, + ) + ) + userRepository.setActionableWhenLocked(true) + keyguardRepository.setKeyguardShowing(false) + + var actions: List<UserActionModel>? = null + val job = underTest.actions.onEach { actions = it }.launchIn(this) + + assertThat(actions) + .isEqualTo( + listOf( + UserActionModel.ENTER_GUEST_MODE, + UserActionModel.ADD_USER, + UserActionModel.ADD_SUPERVISED_USER, + UserActionModel.NAVIGATE_TO_USER_MANAGEMENT, + ) + ) + job.cancel() + } + + @Test + fun `actions - actionable when locked and locked`() = + runBlocking(IMMEDIATE) { + userRepository.setActions( + listOf( + UserActionModel.ENTER_GUEST_MODE, + UserActionModel.ADD_USER, + UserActionModel.ADD_SUPERVISED_USER, + ) + ) + userRepository.setActionableWhenLocked(true) + keyguardRepository.setKeyguardShowing(true) + + var actions: List<UserActionModel>? = null + val job = underTest.actions.onEach { actions = it }.launchIn(this) + + assertThat(actions) + .isEqualTo( + listOf( + UserActionModel.ENTER_GUEST_MODE, + UserActionModel.ADD_USER, + UserActionModel.ADD_SUPERVISED_USER, + UserActionModel.NAVIGATE_TO_USER_MANAGEMENT, + ) + ) + job.cancel() + } + + @Test + fun selectUser() { + val userId = 3 + + underTest.selectUser(userId) + + verify(controller).onUserSelected(eq(userId), nullable()) + } + + @Test + fun `executeAction - guest`() { + underTest.executeAction(UserActionModel.ENTER_GUEST_MODE) + + verify(controller).createAndSwitchToGuestUser(nullable()) + } + + @Test + fun `executeAction - add user`() { + underTest.executeAction(UserActionModel.ADD_USER) + + verify(controller).showAddUserDialog(nullable()) + } + + @Test + fun `executeAction - add supervised user`() { + underTest.executeAction(UserActionModel.ADD_SUPERVISED_USER) + + verify(controller).startSupervisedUserActivity() + } + + @Test + fun `executeAction - manage users`() { + underTest.executeAction(UserActionModel.NAVIGATE_TO_USER_MANAGEMENT) + + verify(activityStarter).startActivity(any(), anyBoolean()) + } + + companion object { + private val IMMEDIATE = Dispatchers.Main.immediate + } +} 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 new file mode 100644 index 000000000000..ef4500df3600 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/user/ui/viewmodel/UserSwitcherViewModelTest.kt @@ -0,0 +1,297 @@ +/* + * 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.user.ui.viewmodel + +import android.graphics.drawable.Drawable +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.common.shared.model.Text +import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository +import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor +import com.android.systemui.plugins.ActivityStarter +import com.android.systemui.power.data.repository.FakePowerRepository +import com.android.systemui.power.domain.interactor.PowerInteractor +import com.android.systemui.statusbar.policy.UserSwitcherController +import com.android.systemui.user.data.repository.FakeUserRepository +import com.android.systemui.user.domain.interactor.UserInteractor +import com.android.systemui.user.legacyhelper.ui.LegacyUserUiHelper +import com.android.systemui.user.shared.model.UserActionModel +import com.android.systemui.user.shared.model.UserModel +import com.android.systemui.util.mockito.mock +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.yield +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 +import org.mockito.Mock +import org.mockito.MockitoAnnotations + +@SmallTest +@RunWith(JUnit4::class) +class UserSwitcherViewModelTest : SysuiTestCase() { + + @Mock private lateinit var controller: UserSwitcherController + @Mock private lateinit var activityStarter: ActivityStarter + + private lateinit var underTest: UserSwitcherViewModel + + private lateinit var userRepository: FakeUserRepository + private lateinit var keyguardRepository: FakeKeyguardRepository + private lateinit var powerRepository: FakePowerRepository + + @Before + fun setUp() { + MockitoAnnotations.initMocks(this) + + userRepository = FakeUserRepository() + keyguardRepository = FakeKeyguardRepository() + powerRepository = FakePowerRepository() + underTest = + UserSwitcherViewModel.Factory( + userInteractor = + UserInteractor( + repository = userRepository, + controller = controller, + activityStarter = activityStarter, + keyguardInteractor = + KeyguardInteractor( + repository = keyguardRepository, + ) + ), + powerInteractor = + PowerInteractor( + repository = powerRepository, + ), + ) + .create(UserSwitcherViewModel::class.java) + } + + @Test + fun users() = + runBlocking(IMMEDIATE) { + userRepository.setUsers( + listOf( + UserModel( + id = 0, + name = Text.Loaded("zero"), + image = USER_IMAGE, + isSelected = true, + isSelectable = true, + ), + UserModel( + id = 1, + name = Text.Loaded("one"), + image = USER_IMAGE, + isSelected = false, + isSelectable = true, + ), + UserModel( + id = 2, + name = Text.Loaded("two"), + image = USER_IMAGE, + isSelected = false, + isSelectable = false, + ), + ) + ) + + var userViewModels: List<UserViewModel>? = null + val job = underTest.users.onEach { userViewModels = it }.launchIn(this) + + assertThat(userViewModels).hasSize(3) + assertUserViewModel( + viewModel = userViewModels?.get(0), + viewKey = 0, + name = "zero", + isSelectionMarkerVisible = true, + alpha = LegacyUserUiHelper.USER_SWITCHER_USER_VIEW_SELECTABLE_ALPHA, + isClickable = true, + ) + assertUserViewModel( + viewModel = userViewModels?.get(1), + viewKey = 1, + name = "one", + isSelectionMarkerVisible = false, + alpha = LegacyUserUiHelper.USER_SWITCHER_USER_VIEW_SELECTABLE_ALPHA, + isClickable = true, + ) + assertUserViewModel( + viewModel = userViewModels?.get(2), + viewKey = 2, + name = "two", + isSelectionMarkerVisible = false, + alpha = LegacyUserUiHelper.USER_SWITCHER_USER_VIEW_NOT_SELECTABLE_ALPHA, + isClickable = false, + ) + job.cancel() + } + + @Test + fun `maximumUserColumns - few users`() = + runBlocking(IMMEDIATE) { + setUsers(count = 2) + var value: Int? = null + val job = underTest.maximumUserColumns.onEach { value = it }.launchIn(this) + + assertThat(value).isEqualTo(4) + job.cancel() + } + + @Test + fun `maximumUserColumns - many users`() = + runBlocking(IMMEDIATE) { + setUsers(count = 5) + var value: Int? = null + val job = underTest.maximumUserColumns.onEach { value = it }.launchIn(this) + + assertThat(value).isEqualTo(3) + job.cancel() + } + + @Test + fun `isOpenMenuButtonVisible - has actions - true`() = + runBlocking(IMMEDIATE) { + userRepository.setActions(UserActionModel.values().toList()) + + var isVisible: Boolean? = null + val job = underTest.isOpenMenuButtonVisible.onEach { isVisible = it }.launchIn(this) + + assertThat(isVisible).isTrue() + job.cancel() + } + + @Test + fun `isOpenMenuButtonVisible - no actions - false`() = + runBlocking(IMMEDIATE) { + userRepository.setActions(emptyList()) + + var isVisible: Boolean? = null + val job = underTest.isOpenMenuButtonVisible.onEach { isVisible = it }.launchIn(this) + + assertThat(isVisible).isFalse() + job.cancel() + } + + @Test + fun menu() = + runBlocking(IMMEDIATE) { + userRepository.setActions(UserActionModel.values().toList()) + var isMenuVisible: Boolean? = null + val job = underTest.isMenuVisible.onEach { isMenuVisible = it }.launchIn(this) + assertThat(isMenuVisible).isFalse() + + underTest.onOpenMenuButtonClicked() + assertThat(isMenuVisible).isTrue() + + underTest.onMenuClosed() + assertThat(isMenuVisible).isFalse() + + job.cancel() + } + + @Test + fun `isFinishRequested - finishes when user is switched`() = + runBlocking(IMMEDIATE) { + setUsers(count = 2) + var isFinishRequested: Boolean? = null + val job = underTest.isFinishRequested.onEach { isFinishRequested = it }.launchIn(this) + assertThat(isFinishRequested).isFalse() + + userRepository.setSelectedUser(1) + yield() + assertThat(isFinishRequested).isTrue() + + job.cancel() + } + + @Test + fun `isFinishRequested - finishes when the screen turns off`() = + runBlocking(IMMEDIATE) { + setUsers(count = 2) + powerRepository.setInteractive(true) + var isFinishRequested: Boolean? = null + val job = underTest.isFinishRequested.onEach { isFinishRequested = it }.launchIn(this) + assertThat(isFinishRequested).isFalse() + + powerRepository.setInteractive(false) + yield() + assertThat(isFinishRequested).isTrue() + + job.cancel() + } + + @Test + fun `isFinishRequested - finishes when cancel button is clicked`() = + runBlocking(IMMEDIATE) { + setUsers(count = 2) + powerRepository.setInteractive(true) + var isFinishRequested: Boolean? = null + val job = underTest.isFinishRequested.onEach { isFinishRequested = it }.launchIn(this) + assertThat(isFinishRequested).isFalse() + + underTest.onCancelButtonClicked() + yield() + assertThat(isFinishRequested).isTrue() + + underTest.onFinished() + yield() + assertThat(isFinishRequested).isFalse() + + job.cancel() + } + + private fun setUsers(count: Int) { + userRepository.setUsers( + (0 until count).map { index -> + UserModel( + id = index, + name = Text.Loaded("$index"), + image = USER_IMAGE, + isSelected = index == 0, + isSelectable = true, + ) + } + ) + } + + private fun assertUserViewModel( + viewModel: UserViewModel?, + viewKey: Int, + name: String, + isSelectionMarkerVisible: Boolean, + alpha: Float, + isClickable: Boolean, + ) { + checkNotNull(viewModel) + assertThat(viewModel.viewKey).isEqualTo(viewKey) + assertThat(viewModel.name).isEqualTo(Text.Loaded(name)) + assertThat(viewModel.isSelectionMarkerVisible).isEqualTo(isSelectionMarkerVisible) + assertThat(viewModel.alpha).isEqualTo(alpha) + assertThat(viewModel.onClicked != null).isEqualTo(isClickable) + } + + companion object { + private val IMMEDIATE = Dispatchers.Main.immediate + private val USER_IMAGE = mock<Drawable>() + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/kotlin/FlowUtilTests.kt b/packages/SystemUI/tests/src/com/android/systemui/util/kotlin/FlowUtilTests.kt index 092e82c526e3..7df707789290 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/util/kotlin/FlowUtilTests.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/util/kotlin/FlowUtilTests.kt @@ -28,12 +28,14 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asFlow import kotlinx.coroutines.flow.emptyFlow import kotlinx.coroutines.flow.filterIsInstance +import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.merge import kotlinx.coroutines.flow.takeWhile import kotlinx.coroutines.flow.toList import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.yield import org.junit.Test import org.junit.runner.RunWith @@ -127,6 +129,53 @@ class SetChangesFlowTest : SysuiTestCase() { ) ) } + + @Test + fun dontEmitFirstEvent() = runBlocking { + assertThatFlow(flowOf(setOf(1, 2), setOf(2, 3)).setChanges(emitFirstEvent = false)) + .emitsExactly( + SetChanges( + removed = setOf(1), + added = setOf(3), + ) + ) + } +} + +@SmallTest +@RunWith(AndroidTestingRunner::class) +class SampleFlowTest : SysuiTestCase() { + @Test + fun simple() = runBlocking { + assertThatFlow(flow { yield(); emit(1) }.sample(flowOf(2)) { a, b -> a to b }) + .emitsExactly(1 to 2) + } + + @Test + fun otherFlowNoValueYet() = runBlocking { + assertThatFlow(flowOf(1).sample(emptyFlow<Unit>())) + .emitsNothing() + } + + @Test + fun multipleSamples() = runBlocking { + val samplee = MutableSharedFlow<Int>() + val sampler = flow { + emit(1) + samplee.emit(1) + emit(2) + samplee.emit(2) + samplee.emit(3) + emit(3) + emit(4) + } + assertThatFlow(sampler.sample(samplee) { a, b -> a to b }) + .emitsExactly( + 2 to 1, + 3 to 3, + 4 to 3, + ) + } } private fun <T> assertThatFlow(flow: Flow<T>) = object { diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/kotlin/SuspendUtilTests.kt b/packages/SystemUI/tests/src/com/android/systemui/util/kotlin/SuspendUtilTests.kt new file mode 100644 index 000000000000..6848b836a348 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/util/kotlin/SuspendUtilTests.kt @@ -0,0 +1,55 @@ +/* + * 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.util.kotlin + +import android.testing.AndroidTestingRunner +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.google.common.truth.Truth.assertThat +import kotlinx.coroutines.CompletableDeferred +import kotlinx.coroutines.async +import kotlinx.coroutines.awaitCancellation +import kotlinx.coroutines.runBlocking +import org.junit.Test +import org.junit.runner.RunWith + +@SmallTest +@RunWith(AndroidTestingRunner::class) +class RaceSuspendTest : SysuiTestCase() { + @Test + fun raceSimple() = runBlocking { + val winner = CompletableDeferred<Int>() + val result = async { + race( + { winner.await() }, + { awaitCancellation() }, + ) + } + winner.complete(1) + assertThat(result.await()).isEqualTo(1) + } + + @Test + fun raceImmediate() = runBlocking { + assertThat( + race<Int>( + { 1 }, + { 2 }, + ) + ).isEqualTo(1) + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/ImageWallpaperTest.java b/packages/SystemUI/tests/src/com/android/systemui/wallpapers/ImageWallpaperTest.java index e1ddaada44cf..e47acd8d3834 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/ImageWallpaperTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/wallpapers/ImageWallpaperTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui; +package com.android.systemui.wallpapers; import static com.google.common.truth.Truth.assertWithMessage; @@ -40,7 +40,8 @@ import android.view.Display; import android.view.DisplayInfo; import android.view.SurfaceHolder; -import com.android.systemui.glwallpaper.ImageWallpaperRenderer; +import com.android.systemui.SysuiTestCase; +import com.android.systemui.wallpapers.gl.ImageWallpaperRenderer; import org.junit.Before; import org.junit.Ignore; diff --git a/packages/SystemUI/tests/src/com/android/systemui/glwallpaper/EglHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/wallpapers/gl/EglHelperTest.java index a3221b58e937..a42badeb228f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/glwallpaper/EglHelperTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/wallpapers/gl/EglHelperTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui.glwallpaper; +package com.android.systemui.wallpapers.gl; import static com.google.common.truth.Truth.assertThat; diff --git a/packages/SystemUI/tests/src/com/android/systemui/glwallpaper/ImageWallpaperRendererTest.java b/packages/SystemUI/tests/src/com/android/systemui/wallpapers/gl/ImageWallpaperRendererTest.java index 510b90722650..89b2222df69e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/glwallpaper/ImageWallpaperRendererTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/wallpapers/gl/ImageWallpaperRendererTest.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.android.systemui.glwallpaper; +package com.android.systemui.wallpapers.gl; import static com.google.common.truth.Truth.assertThat; diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt index 11eb4e3de354..42b434a9deaf 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt @@ -12,6 +12,7 @@ * 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 diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/power/data/repository/FakePowerRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/power/data/repository/FakePowerRepository.kt new file mode 100644 index 000000000000..15465f4d40fe --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/power/data/repository/FakePowerRepository.kt @@ -0,0 +1,34 @@ +/* + * 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.power.data.repository + +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow + +class FakePowerRepository( + initialInteractive: Boolean = true, +) : PowerRepository { + + private val _isInteractive = MutableStateFlow(initialInteractive) + override val isInteractive: Flow<Boolean> = _isInteractive.asStateFlow() + + fun setInteractive(value: Boolean) { + _isInteractive.value = value + } +} diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/user/data/repository/FakeUserRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/user/data/repository/FakeUserRepository.kt new file mode 100644 index 000000000000..20f1e367944f --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/user/data/repository/FakeUserRepository.kt @@ -0,0 +1,82 @@ +/* + * 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.user.data.repository + +import com.android.systemui.user.shared.model.UserActionModel +import com.android.systemui.user.shared.model.UserModel +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.map + +class FakeUserRepository : UserRepository { + + private val _users = MutableStateFlow<List<UserModel>>(emptyList()) + override val users: Flow<List<UserModel>> = _users.asStateFlow() + override val selectedUser: Flow<UserModel> = + users.map { models -> models.first { model -> model.isSelected } } + + private val _actions = MutableStateFlow<List<UserActionModel>>(emptyList()) + override val actions: Flow<List<UserActionModel>> = _actions.asStateFlow() + + private val _isActionableWhenLocked = MutableStateFlow(false) + override val isActionableWhenLocked: Flow<Boolean> = _isActionableWhenLocked.asStateFlow() + + private var _isGuestUserAutoCreated: Boolean = false + override val isGuestUserAutoCreated: Boolean + get() = _isGuestUserAutoCreated + private var _isGuestUserResetting: Boolean = false + override val isGuestUserResetting: Boolean + get() = _isGuestUserResetting + + fun setUsers(models: List<UserModel>) { + _users.value = models + } + + fun setSelectedUser(userId: Int) { + check(_users.value.find { it.id == userId } != null) { + "Cannot select a user with ID $userId - no user with that ID found!" + } + + setUsers( + _users.value.map { model -> + when { + model.isSelected && model.id != userId -> model.copy(isSelected = false) + !model.isSelected && model.id == userId -> model.copy(isSelected = true) + else -> model + } + } + ) + } + + fun setActions(models: List<UserActionModel>) { + _actions.value = models + } + + fun setActionableWhenLocked(value: Boolean) { + _isActionableWhenLocked.value = value + } + + fun setGuestUserAutoCreated(value: Boolean) { + _isGuestUserAutoCreated = value + } + + fun setGuestUserResetting(value: Boolean) { + _isGuestUserResetting = value + } +} diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/util/mockito/KotlinMockitoHelpers.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/util/mockito/KotlinMockitoHelpers.kt index f539dbdf76a0..8d171be87cb6 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/util/mockito/KotlinMockitoHelpers.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/util/mockito/KotlinMockitoHelpers.kt @@ -26,6 +26,7 @@ package com.android.systemui.util.mockito import org.mockito.ArgumentCaptor import org.mockito.ArgumentMatcher import org.mockito.Mockito +import org.mockito.stubbing.OngoingStubbing /** * Returns Mockito.eq() as nullable type to avoid java.lang.IllegalStateException when @@ -77,8 +78,18 @@ inline fun <reified T : Any> argumentCaptor(): ArgumentCaptor<T> = * Helper function for creating new mocks, without the need to pass in a [Class] instance. * * Generic T is nullable because implicitly bounded by Any?. + * + * @param apply builder function to simplify stub configuration by improving type inference. */ -inline fun <reified T : Any> mock(): T = Mockito.mock(T::class.java) +inline fun <reified T : Any> mock(apply: T.() -> Unit = {}): T = Mockito.mock(T::class.java) + .apply(apply) + +/** + * Helper function for stubbing methods without the need to use backticks. + * + * @see Mockito.when + */ +fun <T> whenever(methodCall: T): OngoingStubbing<T> = Mockito.`when`(methodCall) /** * A kotlin implemented wrapper of [ArgumentCaptor] which prevents the following exception when @@ -118,3 +129,17 @@ inline fun <reified T : Any> kotlinArgumentCaptor(): KotlinArgumentCaptor<T> = */ inline fun <reified T : Any> withArgCaptor(block: KotlinArgumentCaptor<T>.() -> Unit): T = kotlinArgumentCaptor<T>().apply { block() }.value + +/** + * Variant of [withArgCaptor] for capturing multiple arguments. + * + * val captor = argumentCaptor<Foo>() + * verify(...).someMethod(captor.capture()) + * val captured: List<Foo> = captor.allValues + * + * becomes: + * + * val capturedList = captureMany<Foo> { verify(...).someMethod(capture()) } + */ +inline fun <reified T : Any> captureMany(block: KotlinArgumentCaptor<T>.() -> Unit): List<T> = + kotlinArgumentCaptor<T>().apply{ block() }.allValues diff --git a/services/autofill/java/com/android/server/autofill/PresentationStatsEventLogger.java b/services/autofill/java/com/android/server/autofill/PresentationStatsEventLogger.java index 01cee33fd81a..b5fdaca838df 100644 --- a/services/autofill/java/com/android/server/autofill/PresentationStatsEventLogger.java +++ b/services/autofill/java/com/android/server/autofill/PresentationStatsEventLogger.java @@ -41,7 +41,12 @@ import static com.android.server.autofill.Helper.sVerbose; import android.annotation.IntDef; import android.annotation.Nullable; +import android.content.ComponentName; +import android.content.Context; +import android.content.pm.PackageManager; +import android.provider.Settings; import android.service.autofill.Dataset; +import android.text.TextUtils; import android.util.Slog; import android.view.autofill.AutofillId; import android.view.autofill.AutofillManager; @@ -61,7 +66,7 @@ public final class PresentationStatsEventLogger { * Reasons why presentation was not shown. These are wrappers around * {@link com.android.os.AtomsProto.AutofillPresentationEventReported.PresentationEventResult}. */ - @IntDef(prefix = { "NOT_SHOWN_REASON" }, value = { + @IntDef(prefix = {"NOT_SHOWN_REASON"}, value = { NOT_SHOWN_REASON_ANY_SHOWN, NOT_SHOWN_REASON_VIEW_FOCUS_CHANGED, NOT_SHOWN_REASON_VIEW_CHANGED, @@ -72,6 +77,7 @@ public final class PresentationStatsEventLogger { }) @Retention(RetentionPolicy.SOURCE) public @interface NotShownReason {} + public static final int NOT_SHOWN_REASON_ANY_SHOWN = AUTOFILL_PRESENTATION_EVENT_REPORTED__PRESENTATION_EVENT_RESULT__ANY_SHOWN; public static final int NOT_SHOWN_REASON_VIEW_FOCUS_CHANGED = AUTOFILL_PRESENTATION_EVENT_REPORTED__PRESENTATION_EVENT_RESULT__NONE_SHOWN_VIEW_FOCUS_CHANGED; public static final int NOT_SHOWN_REASON_VIEW_CHANGED = AUTOFILL_PRESENTATION_EVENT_REPORTED__PRESENTATION_EVENT_RESULT__NONE_SHOWN_VIEW_CHANGED; @@ -172,6 +178,45 @@ public final class PresentationStatsEventLogger { }); } + public void maybeSetInlinePresentationAndSuggestionHostUid(Context context, int userId) { + mEventInternal.ifPresent(event -> { + event.mDisplayPresentationType = UI_TYPE_INLINE; + String imeString = Settings.Secure.getStringForUser(context.getContentResolver(), + Settings.Secure.DEFAULT_INPUT_METHOD, userId); + if (TextUtils.isEmpty(imeString)) { + Slog.w(TAG, "No default IME found"); + return; + } + ComponentName imeComponent = ComponentName.unflattenFromString(imeString); + if (imeComponent == null) { + Slog.w(TAG, "No default IME found"); + return; + } + int imeUid; + String packageName = imeComponent.getPackageName(); + try { + imeUid = context.getPackageManager().getApplicationInfoAsUser(packageName, + PackageManager.ApplicationInfoFlags.of(0), userId).uid; + } catch (PackageManager.NameNotFoundException e) { + Slog.w(TAG, "Couldn't find packageName: " + packageName); + return; + } + event.mInlineSuggestionHostUid = imeUid; + }); + } + + public void maybeSetAutofillServiceUid(int uid) { + mEventInternal.ifPresent(event -> { + event.mAutofillServiceUid = uid; + }); + } + + public void maybeSetIsNewRequest(boolean isRequestTriggered) { + mEventInternal.ifPresent(event -> { + event.mIsRequestTriggered = isRequestTriggered; + }); + } + public void logAndEndEvent() { if (!mEventInternal.isPresent()) { Slog.w(TAG, "Shouldn't be logging AutofillPresentationEventReported again for same " @@ -190,7 +235,10 @@ public final class PresentationStatsEventLogger { + " mCountNotShownImePresentationNotDrawn=" + event.mCountNotShownImePresentationNotDrawn + " mCountNotShownImeUserNotSeen=" + event.mCountNotShownImeUserNotSeen - + " mDisplayPresentationType=" + event.mDisplayPresentationType); + + " mDisplayPresentationType=" + event.mDisplayPresentationType + + " mAutofillServiceUid=" + event.mAutofillServiceUid + + " mInlineSuggestionHostUid=" + event.mInlineSuggestionHostUid + + " mIsRequestTriggered=" + event.mIsRequestTriggered); } // TODO(b/234185326): Distinguish empty responses from other no presentation reasons. @@ -208,7 +256,10 @@ public final class PresentationStatsEventLogger { event.mCountFilteredUserTyping, event.mCountNotShownImePresentationNotDrawn, event.mCountNotShownImeUserNotSeen, - event.mDisplayPresentationType); + event.mDisplayPresentationType, + event.mAutofillServiceUid, + event.mInlineSuggestionHostUid, + event.mIsRequestTriggered); mEventInternal = Optional.empty(); } @@ -222,6 +273,9 @@ public final class PresentationStatsEventLogger { int mCountNotShownImePresentationNotDrawn; int mCountNotShownImeUserNotSeen; int mDisplayPresentationType = AUTOFILL_PRESENTATION_EVENT_REPORTED__DISPLAY_PRESENTATION_TYPE__UNKNOWN_AUTOFILL_DISPLAY_PRESENTATION_TYPE; + int mAutofillServiceUid = -1; + int mInlineSuggestionHostUid = -1; + boolean mIsRequestTriggered; PresentationStatsEventInternal() {} } diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java index 0fe9f8f90cea..bd9c03a75f71 100644 --- a/services/autofill/java/com/android/server/autofill/Session.java +++ b/services/autofill/java/com/android/server/autofill/Session.java @@ -66,6 +66,7 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.IntentSender; +import android.content.pm.ServiceInfo; import android.graphics.Bitmap; import android.graphics.Rect; import android.graphics.drawable.Drawable; @@ -77,6 +78,7 @@ import android.os.Handler; import android.os.IBinder; import android.os.IBinder.DeathRecipient; import android.os.Parcelable; +import android.os.Process; import android.os.RemoteCallback; import android.os.RemoteException; import android.os.SystemClock; @@ -2968,6 +2970,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState mSessionFlags.mFillDialogDisabled = true; } mPresentationStatsEventLogger.startNewEvent(); + mPresentationStatsEventLogger.maybeSetAutofillServiceUid(getAutofillServiceUid()); requestNewFillResponseLocked(viewState, ViewState.STATE_STARTED_SESSION, flags); break; case ACTION_VALUE_CHANGED: @@ -3057,6 +3060,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState } mPresentationStatsEventLogger.startNewEvent(); + mPresentationStatsEventLogger.maybeSetAutofillServiceUid(getAutofillServiceUid()); if (requestNewFillResponseOnViewEnteredIfNecessaryLocked(id, viewState, flags)) { return; } @@ -3292,7 +3296,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState // shown, inflated, and filtered. mPresentationStatsEventLogger.maybeSetCountShown( response.getDatasets(), mCurrentViewId); - mPresentationStatsEventLogger.maybeSetDisplayPresentationType(UI_TYPE_INLINE); + mPresentationStatsEventLogger.maybeSetInlinePresentationAndSuggestionHostUid( + mContext, userId); return; } } @@ -4639,4 +4644,9 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState return "UNKNOWN_SESSION_STATE_" + sessionState; } } + + private int getAutofillServiceUid() { + ServiceInfo serviceInfo = mService.getServiceInfo(); + return serviceInfo == null ? Process.INVALID_UID : serviceInfo.applicationInfo.uid; + } } diff --git a/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java b/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java index 593a63c2f0c9..fc628cfdced2 100644 --- a/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java +++ b/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java @@ -250,7 +250,9 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController // The callback is fired only when windowFlags are changed. To let VirtualDevice owner // aware that the virtual display has a secure window on top. if ((windowFlags & FLAG_SECURE) != 0) { - mSecureWindowCallback.onSecureWindowShown(mDisplayId, activityInfo.applicationInfo.uid); + // Post callback on the main thread, so it doesn't block activity launching. + mHandler.post(() -> mSecureWindowCallback.onSecureWindowShown(mDisplayId, + activityInfo.applicationInfo.uid)); } if (!canContainActivity(activityInfo, windowFlags, systemWindowFlags)) { diff --git a/services/core/java/com/android/server/am/OWNERS b/services/core/java/com/android/server/am/OWNERS index c4efbd7e8f51..7fa1e134181d 100644 --- a/services/core/java/com/android/server/am/OWNERS +++ b/services/core/java/com/android/server/am/OWNERS @@ -40,3 +40,7 @@ per-file SettingsToPropertiesMapper.java = omakoto@google.com, svetoslavganov@go per-file CarUserSwitchingDialog.java = keunyoung@google.com, felipeal@google.com, gurunagarajan@google.com per-file ContentProviderHelper.java = varunshah@google.com, omakoto@google.com, jsharkey@google.com, yamasani@google.com + +# Multiuser +per-file User* = file:/MULTIUSER_OWNERS + diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java index 7ffea26638f5..44b186e1541f 100644 --- a/services/core/java/com/android/server/am/UserController.java +++ b/services/core/java/com/android/server/am/UserController.java @@ -106,6 +106,7 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.policy.IKeyguardDismissCallback; import com.android.internal.util.ArrayUtils; import com.android.internal.util.FrameworkStatsLog; +import com.android.internal.util.Preconditions; import com.android.internal.widget.LockPatternUtils; import com.android.server.FactoryResetter; import com.android.server.FgThread; @@ -368,6 +369,11 @@ class UserController implements Handler.Callback { private boolean mDelayUserDataLocking; /** + * Users are only allowed to be unlocked after boot complete. + */ + private volatile boolean mAllowUserUnlocking; + + /** * Keep track of last active users for mDelayUserDataLocking. * The latest stopped user is placed in front while the least recently stopped user in back. */ @@ -426,6 +432,11 @@ class UserController implements Handler.Callback { mUserLru.add(UserHandle.USER_SYSTEM); mLockPatternUtils = mInjector.getLockPatternUtils(); updateStartedUserArrayLU(); + + // TODO(b/232452368): currently mAllowUserUnlocking is only used on devices with HSUM + // (Headless System User Mode), but on master it will be used by all devices (and hence this + // initial assignment should be removed). + mAllowUserUnlocking = !UserManager.isHeadlessSystemUserMode(); } void setInitialConfig(boolean userSwitchUiEnabled, int maxRunningUsers, @@ -1742,6 +1753,22 @@ class UserController implements Handler.Callback { private boolean unlockUserCleared(final @UserIdInt int userId, byte[] secret, IProgressListener listener) { + // Delay user unlocking for headless system user mode until the system boot + // completes. When the system boot completes, the {@link #onBootCompleted()} + // method unlocks all started users for headless system user mode. This is done + // to prevent unlocking the users too early during the system boot up. + // Otherwise, emulated volumes are mounted too early during the system + // boot up. When vold is reset on boot complete, vold kills all apps/services + // (that use these emulated volumes) before unmounting the volumes(b/241929666). + // In the past, these killings have caused the system to become too unstable on + // some occasions. + // Any unlocks that get delayed by this will be done by onBootComplete() instead. + if (!mAllowUserUnlocking) { + Slogf.i(TAG, "Not unlocking user %d yet because boot hasn't completed", userId); + notifyFinished(userId, listener); + return false; + } + UserState uss; if (!StorageManager.isUserKeyUnlocked(userId)) { final UserInfo userInfo = getUserInfo(userId); @@ -2331,7 +2358,44 @@ class UserController implements Handler.Callback { } } + @VisibleForTesting + void setAllowUserUnlocking(boolean allowed) { + mAllowUserUnlocking = allowed; + if (DEBUG_MU) { + // TODO(b/245335748): use Slogf.d instead + // Slogf.d(TAG, new Exception(), "setAllowUserUnlocking(%b)", allowed); + android.util.Slog.d(TAG, "setAllowUserUnlocking():" + allowed, new Exception()); + } + } + + /** + * @deprecated TODO(b/232452368): this logic will be merged into sendBootCompleted + */ + @Deprecated + private void onBootCompletedOnHeadlessSystemUserModeDevices() { + setAllowUserUnlocking(true); + + // Get a copy of mStartedUsers to use outside of lock. + SparseArray<UserState> startedUsers; + synchronized (mLock) { + startedUsers = mStartedUsers.clone(); + } + // USER_SYSTEM must be processed first. It will be first in the array, as its ID is lowest. + Preconditions.checkArgument(startedUsers.keyAt(0) == UserHandle.USER_SYSTEM); + for (int i = 0; i < startedUsers.size(); i++) { + UserState uss = startedUsers.valueAt(i); + int userId = uss.mHandle.getIdentifier(); + Slogf.i(TAG, "Attempting to unlock user %d on boot complete", userId); + maybeUnlockUser(userId); + } + } + void sendBootCompleted(IIntentReceiver resultTo) { + if (UserManager.isHeadlessSystemUserMode()) { + // Unlocking users is delayed until boot complete for headless system user mode. + onBootCompletedOnHeadlessSystemUserModeDevices(); + } + // Get a copy of mStartedUsers to use outside of lock SparseArray<UserState> startedUsers; synchronized (mLock) { @@ -2773,6 +2837,7 @@ class UserController implements Handler.Callback { pw.println(" mTargetUserId:" + mTargetUserId); pw.println(" mLastActiveUsers:" + mLastActiveUsers); pw.println(" mDelayUserDataLocking:" + mDelayUserDataLocking); + pw.println(" mAllowUserUnlocking:" + mAllowUserUnlocking); pw.println(" shouldStopUserOnSwitch():" + shouldStopUserOnSwitch()); pw.println(" mStopUserOnSwitch:" + mStopUserOnSwitch); pw.println(" mMaxRunningUsers:" + mMaxRunningUsers); diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java index 2b8d6a33bb1b..0d08db91f35e 100644 --- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java +++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java @@ -17,9 +17,12 @@ package com.android.server.audio; import android.annotation.NonNull; import android.annotation.Nullable; +import android.app.compat.CompatChanges; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothHeadset; import android.bluetooth.BluetoothProfile; +import android.compat.annotation.ChangeId; +import android.compat.annotation.EnabledSince; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; @@ -118,8 +121,39 @@ import java.util.concurrent.atomic.AtomicBoolean; // TODO do not "share" the lock between AudioService and BtHelpr, see b/123769055 /*package*/ final Object mSetModeLock = new Object(); - /** PID of current audio mode owner communicated by AudioService */ - private int mModeOwnerPid = 0; + /** AudioModeInfo contains information on current audio mode owner + * communicated by AudioService */ + /* package */ static final class AudioModeInfo { + /** Current audio mode */ + final int mMode; + /** PID of current audio mode owner */ + final int mPid; + /** UID of current audio mode owner */ + final int mUid; + + AudioModeInfo(int mode, int pid, int uid) { + mMode = mode; + mPid = pid; + mUid = uid; + } + + @Override + public String toString() { + return "AudioModeInfo: mMode=" + AudioSystem.modeToString(mMode) + + ", mPid=" + mPid + + ", mUid=" + mUid; + } + }; + + private AudioModeInfo mAudioModeOwner = new AudioModeInfo(AudioSystem.MODE_NORMAL, 0, 0); + + /** + * Indicates that default communication device is chosen by routing rules in audio policy + * manager and not forced by AudioDeviceBroker. + */ + @ChangeId + @EnabledSince(targetSdkVersion = android.os.Build.VERSION_CODES.S_V2) + public static final long USE_SET_COMMUNICATION_DEVICE = 243827847L; //------------------------------------------------------------------- /*package*/ AudioDeviceBroker(@NonNull Context context, @NonNull AudioService service) { @@ -187,7 +221,7 @@ import java.util.concurrent.atomic.AtomicBoolean; /*package*/ void onSystemReady() { synchronized (mSetModeLock) { synchronized (mDeviceStateLock) { - mModeOwnerPid = mAudioService.getModeOwnerPid(); + mAudioModeOwner = mAudioService.getAudioModeOwner(); mBtHelper.onSystemReady(); } } @@ -368,11 +402,11 @@ import java.util.concurrent.atomic.AtomicBoolean; @GuardedBy("mDeviceStateLock") private CommunicationRouteClient topCommunicationRouteClient() { for (CommunicationRouteClient crc : mCommunicationRouteClients) { - if (crc.getPid() == mModeOwnerPid) { + if (crc.getPid() == mAudioModeOwner.mPid) { return crc; } } - if (!mCommunicationRouteClients.isEmpty() && mModeOwnerPid == 0) { + if (!mCommunicationRouteClients.isEmpty() && mAudioModeOwner.mPid == 0) { return mCommunicationRouteClients.get(0); } return null; @@ -390,7 +424,7 @@ import java.util.concurrent.atomic.AtomicBoolean; AudioDeviceAttributes device = crc != null ? crc.getDevice() : null; if (AudioService.DEBUG_COMM_RTE) { Log.v(TAG, "requestedCommunicationDevice, device: " - + device + " mode owner pid: " + mModeOwnerPid); + + device + "mAudioModeOwner: " + mAudioModeOwner.toString()); } return device; } @@ -774,8 +808,9 @@ import java.util.concurrent.atomic.AtomicBoolean; sendLMsgNoDelay(MSG_II_SET_LE_AUDIO_OUT_VOLUME, SENDMSG_REPLACE, info); } - /*package*/ void postSetModeOwnerPid(int pid, int mode) { - sendIIMsgNoDelay(MSG_I_SET_MODE_OWNER_PID, SENDMSG_REPLACE, pid, mode); + /*package*/ void postSetModeOwner(int mode, int pid, int uid) { + sendLMsgNoDelay(MSG_I_SET_MODE_OWNER, SENDMSG_REPLACE, + new AudioModeInfo(mode, pid, uid)); } /*package*/ void postBluetoothA2dpDeviceConfigChange(@NonNull BluetoothDevice device) { @@ -1162,7 +1197,7 @@ import java.util.concurrent.atomic.AtomicBoolean; pw.println(prefix + "mAccessibilityStrategyId: " + mAccessibilityStrategyId); - pw.println("\n" + prefix + "mModeOwnerPid: " + mModeOwnerPid); + pw.println("\n" + prefix + "mAudioModeOwner: " + mAudioModeOwner); mBtHelper.dump(pw, prefix); } @@ -1288,12 +1323,19 @@ import java.util.concurrent.atomic.AtomicBoolean; } break; case MSG_L_SET_BT_ACTIVE_DEVICE: - synchronized (mDeviceStateLock) { - BtDeviceInfo btInfo = (BtDeviceInfo) msg.obj; - mDeviceInventory.onSetBtActiveDevice(btInfo, - (btInfo.mProfile != BluetoothProfile.LE_AUDIO || btInfo.mIsLeOutput) - ? mAudioService.getBluetoothContextualVolumeStream() - : AudioSystem.STREAM_DEFAULT); + synchronized (mSetModeLock) { + synchronized (mDeviceStateLock) { + BtDeviceInfo btInfo = (BtDeviceInfo) msg.obj; + mDeviceInventory.onSetBtActiveDevice(btInfo, + (btInfo.mProfile + != BluetoothProfile.LE_AUDIO || btInfo.mIsLeOutput) + ? mAudioService.getBluetoothContextualVolumeStream() + : AudioSystem.STREAM_DEFAULT); + if (btInfo.mProfile == BluetoothProfile.LE_AUDIO + || btInfo.mProfile == BluetoothProfile.HEARING_AID) { + onUpdateCommunicationRouteClient("setBluetoothActiveDevice"); + } + } } break; case MSG_BT_HEADSET_CNCT_FAILED: @@ -1337,11 +1379,11 @@ import java.util.concurrent.atomic.AtomicBoolean; mBtHelper.setAvrcpAbsoluteVolumeIndex(msg.arg1); } break; - case MSG_I_SET_MODE_OWNER_PID: + case MSG_I_SET_MODE_OWNER: synchronized (mSetModeLock) { synchronized (mDeviceStateLock) { - mModeOwnerPid = msg.arg1; - if (msg.arg2 != AudioSystem.MODE_RINGTONE) { + mAudioModeOwner = (AudioModeInfo) msg.obj; + if (mAudioModeOwner.mMode != AudioSystem.MODE_RINGTONE) { onUpdateCommunicationRouteClient("setNewModeOwner"); } } @@ -1503,7 +1545,7 @@ import java.util.concurrent.atomic.AtomicBoolean; private static final int MSG_REPORT_NEW_ROUTES = 13; private static final int MSG_II_SET_HEARING_AID_VOLUME = 14; private static final int MSG_I_SET_AVRCP_ABSOLUTE_VOLUME = 15; - private static final int MSG_I_SET_MODE_OWNER_PID = 16; + private static final int MSG_I_SET_MODE_OWNER = 16; private static final int MSG_I_BT_SERVICE_DISCONNECTED_PROFILE = 22; private static final int MSG_IL_BT_SERVICE_CONNECTED_PROFILE = 23; @@ -1825,8 +1867,16 @@ import java.util.concurrent.atomic.AtomicBoolean; AudioSystem.setParameters("BT_SCO=on"); } if (preferredCommunicationDevice == null) { - removePreferredDevicesForStrategySync(mCommunicationStrategyId); - removePreferredDevicesForStrategySync(mAccessibilityStrategyId); + AudioDeviceAttributes defaultDevice = getDefaultCommunicationDevice(); + if (defaultDevice != null) { + setPreferredDevicesForStrategySync( + mCommunicationStrategyId, Arrays.asList(defaultDevice)); + setPreferredDevicesForStrategySync( + mAccessibilityStrategyId, Arrays.asList(defaultDevice)); + } else { + removePreferredDevicesForStrategySync(mCommunicationStrategyId); + removePreferredDevicesForStrategySync(mAccessibilityStrategyId); + } } else { setPreferredDevicesForStrategySync( mCommunicationStrategyId, Arrays.asList(preferredCommunicationDevice)); @@ -1855,26 +1905,24 @@ import java.util.concurrent.atomic.AtomicBoolean; } } + // @GuardedBy("mSetModeLock") + @GuardedBy("mDeviceStateLock") private void onUpdatePhoneStrategyDevice(AudioDeviceAttributes device) { - synchronized (mSetModeLock) { - synchronized (mDeviceStateLock) { - boolean wasSpeakerphoneActive = isSpeakerphoneActive(); - mPreferredCommunicationDevice = device; - updateActiveCommunicationDevice(); - if (wasSpeakerphoneActive != isSpeakerphoneActive()) { - try { - mContext.sendBroadcastAsUser( - new Intent(AudioManager.ACTION_SPEAKERPHONE_STATE_CHANGED) - .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY), - UserHandle.ALL); - } catch (Exception e) { - Log.w(TAG, "failed to broadcast ACTION_SPEAKERPHONE_STATE_CHANGED: " + e); - } - } - mAudioService.postUpdateRingerModeServiceInt(); - dispatchCommunicationDevice(); + boolean wasSpeakerphoneActive = isSpeakerphoneActive(); + mPreferredCommunicationDevice = device; + updateActiveCommunicationDevice(); + if (wasSpeakerphoneActive != isSpeakerphoneActive()) { + try { + mContext.sendBroadcastAsUser( + new Intent(AudioManager.ACTION_SPEAKERPHONE_STATE_CHANGED) + .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY), + UserHandle.ALL); + } catch (Exception e) { + Log.w(TAG, "failed to broadcast ACTION_SPEAKERPHONE_STATE_CHANGED: " + e); } } + mAudioService.postUpdateRingerModeServiceInt(); + dispatchCommunicationDevice(); } private CommunicationRouteClient removeCommunicationRouteClient( @@ -1914,6 +1962,32 @@ import java.util.concurrent.atomic.AtomicBoolean; return null; } + @GuardedBy("mDeviceStateLock") + private boolean communnicationDeviceCompatOn() { + return mAudioModeOwner.mMode == AudioSystem.MODE_IN_COMMUNICATION + && !(CompatChanges.isChangeEnabled( + USE_SET_COMMUNICATION_DEVICE, mAudioModeOwner.mUid) + || mAudioModeOwner.mUid == android.os.Process.SYSTEM_UID); + } + + @GuardedBy("mDeviceStateLock") + AudioDeviceAttributes getDefaultCommunicationDevice() { + // For system server (Telecom) and APKs targeting S and above, we let the audio + // policy routing rules select the default communication device. + // For older APKs, we force Hearing Aid or LE Audio headset when connected as + // those APKs cannot select a LE Audio or Hearing Aid device explicitly. + AudioDeviceAttributes device = null; + if (communnicationDeviceCompatOn()) { + // If both LE and Hearing Aid are active (thie should not happen), + // priority to Hearing Aid. + device = mDeviceInventory.getDeviceOfType(AudioSystem.DEVICE_OUT_HEARING_AID); + if (device == null) { + device = mDeviceInventory.getDeviceOfType(AudioSystem.DEVICE_OUT_BLE_HEADSET); + } + } + return device; + } + @Nullable UUID getDeviceSensorUuid(AudioDeviceAttributes device) { synchronized (mDeviceStateLock) { return mDeviceInventory.getDeviceSensorUuid(device); diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java index 54b2d56aa2af..ee0d79f49af7 100644 --- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java +++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java @@ -294,6 +294,7 @@ public class AudioDeviceInventory { } } + // @GuardedBy("AudioDeviceBroker.mSetModeLock") @GuardedBy("AudioDeviceBroker.mDeviceStateLock") void onSetBtActiveDevice(@NonNull AudioDeviceBroker.BtDeviceInfo btInfo, int streamType) { if (AudioService.DEBUG_DEVICES) { @@ -1510,6 +1511,19 @@ public class AudioDeviceInventory { return di.mSensorUuid; } } + + /* package */ AudioDeviceAttributes getDeviceOfType(int type) { + synchronized (mDevicesLock) { + for (DeviceInfo di : mConnectedDevices.values()) { + if (di.mDeviceType == type) { + return new AudioDeviceAttributes( + di.mDeviceType, di.mDeviceAddress, di.mDeviceName); + } + } + } + return null; + } + //---------------------------------------------------------- // For tests only diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java index 0c4ea9764f51..0b6b89074cfc 100644 --- a/services/core/java/com/android/server/audio/AudioService.java +++ b/services/core/java/com/android/server/audio/AudioService.java @@ -3355,8 +3355,7 @@ public class AudioService extends IAudioService.Stub dispatchAbsoluteVolumeChanged(streamType, info, newIndex); } - if ((device == AudioSystem.DEVICE_OUT_BLE_HEADSET - || device == AudioSystem.DEVICE_OUT_BLE_BROADCAST) + if (AudioSystem.isLeAudioDeviceType(device) && streamType == getBluetoothContextualVolumeStream() && (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) { if (DEBUG_VOL) { @@ -4112,8 +4111,7 @@ public class AudioService extends IAudioService.Stub dispatchAbsoluteVolumeChanged(streamType, info, index); } - if ((device == AudioSystem.DEVICE_OUT_BLE_HEADSET - || device == AudioSystem.DEVICE_OUT_BLE_BROADCAST) + if (AudioSystem.isLeAudioDeviceType(device) && streamType == getBluetoothContextualVolumeStream() && (flags & AudioManager.FLAG_BLUETOOTH_ABS_VOLUME) == 0) { if (DEBUG_VOL) { @@ -5227,16 +5225,17 @@ public class AudioService extends IAudioService.Stub } /** - * Return the pid of the current audio mode owner + * Return information on the current audio mode owner * @return 0 if nobody owns the mode */ @GuardedBy("mDeviceBroker.mSetModeLock") - /*package*/ int getModeOwnerPid() { + /*package*/ AudioDeviceBroker.AudioModeInfo getAudioModeOwner() { SetModeDeathHandler hdlr = getAudioModeOwnerHandler(); if (hdlr != null) { - return hdlr.getPid(); + return new AudioDeviceBroker.AudioModeInfo( + hdlr.getMode(), hdlr.getPid(), hdlr.getUid()); } - return 0; + return new AudioDeviceBroker.AudioModeInfo(AudioSystem.MODE_NORMAL, 0 , 0); } /** @@ -5422,7 +5421,7 @@ public class AudioService extends IAudioService.Stub // when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all SCO // connections not started by the application changing the mode when pid changes - mDeviceBroker.postSetModeOwnerPid(pid, mode); + mDeviceBroker.postSetModeOwner(mode, pid, uid); } else { Log.w(TAG, "onUpdateAudioMode: failed to set audio mode to: " + mode); } @@ -5750,7 +5749,10 @@ public class AudioService extends IAudioService.Stub } return deviceIds.stream().mapToInt(Integer::intValue).toArray(); } - /** @see AudioManager#setCommunicationDevice(int) */ + /** + * @see AudioManager#setCommunicationDevice(int) + * @see AudioManager#clearCommunicationDevice() + */ public boolean setCommunicationDevice(IBinder cb, int portId) { final int uid = Binder.getCallingUid(); final int pid = Binder.getCallingPid(); @@ -5765,7 +5767,8 @@ public class AudioService extends IAudioService.Stub throw new IllegalArgumentException("invalid device type " + device.getType()); } } - final String eventSource = new StringBuilder("setCommunicationDevice(") + final String eventSource = new StringBuilder() + .append(device == null ? "clearCommunicationDevice(" : "setCommunicationDevice(") .append(") from u/pid:").append(uid).append("/") .append(pid).toString(); @@ -6952,7 +6955,8 @@ public class AudioService extends IAudioService.Stub return AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE_MULTI_MODE; } if (isAbsoluteVolumeDevice(audioSystemDeviceOut) - || isA2dpAbsoluteVolumeDevice(audioSystemDeviceOut)) { + || isA2dpAbsoluteVolumeDevice(audioSystemDeviceOut) + || AudioSystem.isLeAudioDeviceType(audioSystemDeviceOut)) { return AudioManager.DEVICE_VOLUME_BEHAVIOR_ABSOLUTE; } return AudioManager.DEVICE_VOLUME_BEHAVIOR_VARIABLE; @@ -7719,7 +7723,9 @@ public class AudioService extends IAudioService.Stub int index; if (isFullyMuted()) { index = 0; - } else if (isAbsoluteVolumeDevice(device) || isA2dpAbsoluteVolumeDevice(device)) { + } else if (isAbsoluteVolumeDevice(device) + || isA2dpAbsoluteVolumeDevice(device) + || AudioSystem.isLeAudioDeviceType(device)) { index = getAbsoluteVolumeIndex((getIndex(device) + 5)/10); } else if (isFullVolumeDevice(device)) { index = (mIndexMax + 5)/10; @@ -7741,7 +7747,8 @@ public class AudioService extends IAudioService.Stub if (isFullyMuted()) { index = 0; } else if (isAbsoluteVolumeDevice(device) - || isA2dpAbsoluteVolumeDevice(device)) { + || isA2dpAbsoluteVolumeDevice(device) + || AudioSystem.isLeAudioDeviceType(device)) { index = getAbsoluteVolumeIndex((getIndex(device) + 5)/10); } else if (isFullVolumeDevice(device)) { index = (mIndexMax + 5)/10; @@ -8162,7 +8169,8 @@ public class AudioService extends IAudioService.Stub int streamDevice = getDeviceForStream(streamType); if ((device != streamDevice) && (isAbsoluteVolumeDevice(device) - || isA2dpAbsoluteVolumeDevice(device))) { + || isA2dpAbsoluteVolumeDevice(device) + || AudioSystem.isLeAudioDeviceType(device))) { mStreamStates[streamType].applyDeviceVolume_syncVSS(device); } mStreamStates[streamType].applyDeviceVolume_syncVSS(streamDevice); diff --git a/services/core/java/com/android/server/audio/AudioServiceEvents.java b/services/core/java/com/android/server/audio/AudioServiceEvents.java index b5835ce0c847..30a9e0a70e96 100644 --- a/services/core/java/com/android/server/audio/AudioServiceEvents.java +++ b/services/core/java/com/android/server/audio/AudioServiceEvents.java @@ -433,7 +433,7 @@ public class AudioServiceEvents { case VOL_SET_LE_AUDIO_VOL: return new StringBuilder("setLeAudioVolume:") .append(" index:").append(mVal1) - .append(" gain dB:").append(mVal2) + .append(" maxIndex:").append(mVal2) .toString(); case VOL_SET_AVRCP_VOL: return new StringBuilder("setAvrcpVolume:") diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java index 9a7c6626aa24..d0f5470a7304 100644 --- a/services/core/java/com/android/server/audio/BtHelper.java +++ b/services/core/java/com/android/server/audio/BtHelper.java @@ -412,9 +412,8 @@ public class BtHelper { } return; } - /* leaudio expect volume value in range 0 to 255 - */ - int volume = (index * (BT_LE_AUDIO_MAX_VOL - BT_LE_AUDIO_MIN_VOL)) / maxIndex ; + /* leaudio expect volume value in range 0 to 255 */ + int volume = (int) Math.round((double) index * BT_LE_AUDIO_MAX_VOL / maxIndex); if (AudioService.DEBUG_VOL) { Log.i(TAG, "setLeAudioVolume: calling mLeAudio.setVolume idx=" diff --git a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java index b3e7e31d37fc..93841fe288e1 100644 --- a/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java +++ b/services/core/java/com/android/server/audio/PlaybackActivityMonitor.java @@ -49,6 +49,7 @@ import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Set; +import java.util.concurrent.ConcurrentLinkedQueue; import java.util.function.Consumer; /** @@ -104,11 +105,7 @@ public final class PlaybackActivityMonitor private static final VolumeShaper.Operation PLAY_SKIP_RAMP = new VolumeShaper.Operation.Builder(PLAY_CREATE_IF_NEEDED).setXOffset(1.0f).build(); - private final ArrayList<PlayMonitorClient> mClients = new ArrayList<PlayMonitorClient>(); - // a public client is one that needs an anonymized version of the playback configurations, we - // keep track of whether there is at least one to know when we need to create the list of - // playback configurations that do not contain uid/pid/package name information. - private boolean mHasPublicClients = false; + private final ConcurrentLinkedQueue<PlayMonitorClient> mClients = new ConcurrentLinkedQueue<>(); private final Object mPlayerLock = new Object(); @GuardedBy("mPlayerLock") @@ -458,11 +455,9 @@ public final class PlaybackActivityMonitor + DateFormat.getTimeInstance().format(new Date())); synchronized(mPlayerLock) { pw.println("\n playback listeners:"); - synchronized(mClients) { - for (PlayMonitorClient pmc : mClients) { - pw.print(" " + (pmc.mIsPrivileged ? "(S)" : "(P)") - + pmc.toString()); - } + for (PlayMonitorClient pmc : mClients) { + pw.print(" " + (pmc.isPrivileged() ? "(S)" : "(P)") + + pmc.toString()); } pw.println("\n"); // all players @@ -534,48 +529,33 @@ public final class PlaybackActivityMonitor * @param iplayerReleased indicates if the change was due to a player being released */ private void dispatchPlaybackChange(boolean iplayerReleased) { - synchronized (mClients) { - // typical use case, nobody is listening, don't do any work - if (mClients.isEmpty()) { - return; - } - } if (DEBUG) { Log.v(TAG, "dispatchPlaybackChange to " + mClients.size() + " clients"); } final List<AudioPlaybackConfiguration> configsSystem; - // list of playback configurations for "public consumption". It is only computed if there + // list of playback configurations for "public consumption". It is computed lazy if there // are non-system playback activity listeners. - final List<AudioPlaybackConfiguration> configsPublic; + List<AudioPlaybackConfiguration> configsPublic = null; synchronized (mPlayerLock) { if (mPlayers.isEmpty()) { return; } - configsSystem = new ArrayList<AudioPlaybackConfiguration>(mPlayers.values()); + configsSystem = new ArrayList<>(mPlayers.values()); } - synchronized (mClients) { - // was done at beginning of method, but could have changed - if (mClients.isEmpty()) { - return; - } - configsPublic = mHasPublicClients ? anonymizeForPublicConsumption(configsSystem) : null; - final Iterator<PlayMonitorClient> clientIterator = mClients.iterator(); - while (clientIterator.hasNext()) { - final PlayMonitorClient pmc = clientIterator.next(); - try { - // do not spam the logs if there are problems communicating with this client - if (pmc.mErrorCount < PlayMonitorClient.MAX_ERRORS) { - if (pmc.mIsPrivileged) { - pmc.mDispatcherCb.dispatchPlaybackConfigChange(configsSystem, - iplayerReleased); - } else { - // non-system clients don't have the control interface IPlayer, so - // they don't need to flush commands when a player was released - pmc.mDispatcherCb.dispatchPlaybackConfigChange(configsPublic, false); - } + + final Iterator<PlayMonitorClient> clientIterator = mClients.iterator(); + while (clientIterator.hasNext()) { + final PlayMonitorClient pmc = clientIterator.next(); + // do not spam the logs if there are problems communicating with this client + if (!pmc.reachedMaxErrorCount()) { + if (pmc.isPrivileged()) { + pmc.dispatchPlaybackConfigChange(configsSystem, + iplayerReleased); + } else { + if (configsPublic == null) { + configsPublic = anonymizeForPublicConsumption(configsSystem); } - } catch (RemoteException e) { - pmc.mErrorCount++; - Log.e(TAG, "Error (" + pmc.mErrorCount + - ") trying to dispatch playback config change to " + pmc, e); + // non-system clients don't have the control interface IPlayer, so + // they don't need to flush commands when a player was released + pmc.dispatchPlaybackConfigChange(configsPublic, false); } } } @@ -798,14 +778,9 @@ public final class PlaybackActivityMonitor if (pcdb == null) { return; } - synchronized(mClients) { - final PlayMonitorClient pmc = new PlayMonitorClient(pcdb, isPrivileged); - if (pmc.init()) { - if (!isPrivileged) { - mHasPublicClients = true; - } - mClients.add(pmc); - } + final PlayMonitorClient pmc = new PlayMonitorClient(pcdb, isPrivileged); + if (pmc.init()) { + mClients.add(pmc); } } @@ -813,23 +788,14 @@ public final class PlaybackActivityMonitor if (pcdb == null) { return; } - synchronized(mClients) { - final Iterator<PlayMonitorClient> clientIterator = mClients.iterator(); - boolean hasPublicClients = false; - // iterate over the clients to remove the dispatcher to remove, and reevaluate at - // the same time if we still have a public client. - while (clientIterator.hasNext()) { - PlayMonitorClient pmc = clientIterator.next(); - if (pcdb.asBinder().equals(pmc.mDispatcherCb.asBinder())) { - pmc.release(); - clientIterator.remove(); - } else { - if (!pmc.mIsPrivileged) { - hasPublicClients = true; - } - } + final Iterator<PlayMonitorClient> clientIterator = mClients.iterator(); + // iterate over the clients to remove the dispatcher + while (clientIterator.hasNext()) { + PlayMonitorClient pmc = clientIterator.next(); + if (pmc.equalsDispatcher(pcdb)) { + pmc.release(); + clientIterator.remove(); } - mHasPublicClients = hasPublicClients; } } @@ -857,24 +823,34 @@ public final class PlaybackActivityMonitor // can afford to be static because only one PlaybackActivityMonitor ever instantiated static PlaybackActivityMonitor sListenerDeathMonitor; - final IPlaybackConfigDispatcher mDispatcherCb; - final boolean mIsPrivileged; - - int mErrorCount = 0; // number of errors after which we don't update this client anymore to not spam the logs - static final int MAX_ERRORS = 5; + private static final int MAX_ERRORS = 5; + + private final IPlaybackConfigDispatcher mDispatcherCb; + + @GuardedBy("this") + private final boolean mIsPrivileged; + @GuardedBy("this") + private boolean mIsReleased = false; + @GuardedBy("this") + private int mErrorCount = 0; PlayMonitorClient(IPlaybackConfigDispatcher pcdb, boolean isPrivileged) { mDispatcherCb = pcdb; mIsPrivileged = isPrivileged; } + @Override public void binderDied() { Log.w(TAG, "client died"); sListenerDeathMonitor.unregisterPlaybackCallback(mDispatcherCb); } - boolean init() { + synchronized boolean init() { + if (mIsReleased) { + // Do not init after release + return false; + } try { mDispatcherCb.asBinder().linkToDeath(this, 0); return true; @@ -884,8 +860,43 @@ public final class PlaybackActivityMonitor } } - void release() { + synchronized void release() { mDispatcherCb.asBinder().unlinkToDeath(this, 0); + mIsReleased = true; + } + + void dispatchPlaybackConfigChange(List<AudioPlaybackConfiguration> configs, + boolean flush) { + synchronized (this) { + if (mIsReleased) { + // Do not dispatch anything after release + return; + } + } + try { + mDispatcherCb.dispatchPlaybackConfigChange(configs, flush); + } catch (RemoteException e) { + synchronized (this) { + mErrorCount++; + Log.e(TAG, "Error (" + mErrorCount + + ") trying to dispatch playback config change to " + this, e); + } + } + } + + synchronized boolean isPrivileged() { + return mIsPrivileged; + } + + synchronized boolean reachedMaxErrorCount() { + return mErrorCount >= MAX_ERRORS; + } + + synchronized boolean equalsDispatcher(IPlaybackConfigDispatcher pcdb) { + if (pcdb == null) { + return false; + } + return pcdb.asBinder().equals(mDispatcherCb.asBinder()); } } diff --git a/services/core/java/com/android/server/biometrics/sensors/ClientMonitorCallbackConverter.java b/services/core/java/com/android/server/biometrics/sensors/ClientMonitorCallbackConverter.java index 46d863d7aaec..2e1a363bcc68 100644 --- a/services/core/java/com/android/server/biometrics/sensors/ClientMonitorCallbackConverter.java +++ b/services/core/java/com/android/server/biometrics/sensors/ClientMonitorCallbackConverter.java @@ -59,7 +59,7 @@ public class ClientMonitorCallbackConverter { // The following apply to all clients - void onAcquired(int sensorId, int acquiredInfo, int vendorCode) throws RemoteException { + public void onAcquired(int sensorId, int acquiredInfo, int vendorCode) throws RemoteException { if (mSensorReceiver != null) { mSensorReceiver.onAcquired(sensorId, acquiredInfo, vendorCode); } else if (mFaceServiceReceiver != null) { diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java index e0393b54d2c5..612d90670888 100644 --- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java +++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java @@ -50,12 +50,14 @@ import com.android.server.biometrics.sensors.ClientMonitorCompositeCallback; import com.android.server.biometrics.sensors.EnrollClient; import com.android.server.biometrics.sensors.SensorOverlays; import com.android.server.biometrics.sensors.fingerprint.FingerprintUtils; +import com.android.server.biometrics.sensors.fingerprint.PowerPressHandler; import com.android.server.biometrics.sensors.fingerprint.Udfps; import com.android.server.biometrics.sensors.fingerprint.UdfpsHelper; import java.util.function.Supplier; -class FingerprintEnrollClient extends EnrollClient<AidlSession> implements Udfps { +class FingerprintEnrollClient extends EnrollClient<AidlSession> implements Udfps, + PowerPressHandler { private static final String TAG = "FingerprintEnrollClient"; @@ -266,4 +268,10 @@ class FingerprintEnrollClient extends EnrollClient<AidlSession> implements Udfps Slog.e(TAG, "Unable to send UI ready", e); } } + + @Override + public void onPowerPressed() { + onAcquired(BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_POWER_PRESSED, + 0 /* vendorCode */); + } } diff --git a/services/core/java/com/android/server/camera/CameraServiceProxy.java b/services/core/java/com/android/server/camera/CameraServiceProxy.java index b425420479f0..aec60deba933 100644 --- a/services/core/java/com/android/server/camera/CameraServiceProxy.java +++ b/services/core/java/com/android/server/camera/CameraServiceProxy.java @@ -582,13 +582,18 @@ public class CameraServiceProxy extends SystemService } @Override - public boolean isCameraDisabled() { + public boolean isCameraDisabled(int userId) { DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class); if (dpm == null) { Slog.e(TAG, "Failed to get the device policy manager service"); return false; } - return dpm.getCameraDisabled(null); + try { + return dpm.getCameraDisabled(null, userId); + } catch (Exception e) { + e.printStackTrace(); + return false; + } } }; diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java index b988b5731f9b..481c5db559cf 100644 --- a/services/core/java/com/android/server/connectivity/Vpn.java +++ b/services/core/java/com/android/server/connectivity/Vpn.java @@ -222,6 +222,11 @@ public class Vpn { */ private static final int VPN_DEFAULT_SCORE = 101; + /** + * The initial token value of IKE session. + */ + private static final int STARTING_TOKEN = -1; + // TODO: create separate trackers for each unique VPN to support // automated reconnection @@ -795,7 +800,7 @@ public class Vpn { } } - private boolean isVpnApp(String packageName) { + private static boolean isVpnApp(String packageName) { return packageName != null && !VpnConfig.LEGACY_VPN.equals(packageName); } @@ -1191,25 +1196,7 @@ public class Vpn { mContext.unbindService(mConnection); cleanupVpnStateLocked(); } else if (mVpnRunner != null) { - // Build intent first because the sessionKey will be reset after performing - // VpnRunner.exit(). Also, cache mOwnerUID even if ownerUID will not be changed in - // VpnRunner.exit() to prevent design being changed in the future. - // TODO(b/230548427): Remove SDK check once VPN related stuff are decoupled from - // ConnectivityServiceTest. - final int ownerUid = mOwnerUID; - Intent intent = null; - if (SdkLevel.isAtLeastT() && isVpnApp(mPackage)) { - intent = buildVpnManagerEventIntent( - VpnManager.CATEGORY_EVENT_DEACTIVATED_BY_USER, - -1 /* errorClass */, -1 /* errorCode*/, mPackage, - getSessionKeyLocked(), makeVpnProfileStateLocked(), - null /* underlyingNetwork */, null /* nc */, null /* lp */); - } - // cleanupVpnStateLocked() is called from mVpnRunner.exit() - mVpnRunner.exit(); - if (intent != null && isVpnApp(mPackage)) { - notifyVpnManagerVpnStopped(mPackage, ownerUid, intent); - } + stopVpnRunnerAndNotifyAppLocked(mPackage); } try { @@ -2611,7 +2598,7 @@ public class Vpn { } @Nullable - protected synchronized NetworkCapabilities getRedactedNetworkCapabilitiesOfUnderlyingNetwork( + private synchronized NetworkCapabilities getRedactedNetworkCapabilities( NetworkCapabilities nc) { if (nc == null) return null; return mConnectivityManager.getRedactedNetworkCapabilitiesForPackage( @@ -2619,8 +2606,7 @@ public class Vpn { } @Nullable - protected synchronized LinkProperties getRedactedLinkPropertiesOfUnderlyingNetwork( - LinkProperties lp) { + private synchronized LinkProperties getRedactedLinkProperties(LinkProperties lp) { if (lp == null) return null; return mConnectivityManager.getRedactedLinkPropertiesForPackage(lp, mOwnerUID, mPackage); } @@ -2734,11 +2720,13 @@ public class Vpn { private boolean mIsRunning = true; /** - * The token used by the primary/current/active IKE session. + * The token that identifies the most recently created IKE session. * - * <p>This token MUST be updated when the VPN switches to use a new IKE session. + * <p>This token is monotonically increasing and will never be reset in the lifetime of this + * Ikev2VpnRunner, but it does get reset across runs. It also MUST be accessed on the + * executor thread and updated when a new IKE session is created. */ - private int mCurrentToken = -1; + private int mCurrentToken = STARTING_TOKEN; @Nullable private IpSecTunnelInterface mTunnelIface; @Nullable private Network mActiveNetwork; @@ -3241,7 +3229,7 @@ public class Vpn { mExecutor.schedule( () -> { if (isActiveToken(token)) { - handleSessionLost(null, network); + handleSessionLost(null /* exception */, network); } else { Log.d( TAG, @@ -3258,7 +3246,7 @@ public class Vpn { TimeUnit.MILLISECONDS); } else { Log.d(TAG, "Call handleSessionLost for losing network " + network); - handleSessionLost(null, network); + handleSessionLost(null /* exception */, network); } } @@ -3329,119 +3317,71 @@ public class Vpn { // already terminated due to other failures. cancelHandleNetworkLostTimeout(); + String category = null; + int errorClass = -1; + int errorCode = -1; + if (exception instanceof IllegalArgumentException) { + // Failed to build IKE/ChildSessionParams; fatal profile configuration error + markFailedAndDisconnect(exception); + return; + } + + if (exception instanceof IkeProtocolException) { + final IkeProtocolException ikeException = (IkeProtocolException) exception; + category = VpnManager.CATEGORY_EVENT_IKE_ERROR; + errorCode = ikeException.getErrorType(); + + switch (ikeException.getErrorType()) { + case IkeProtocolException.ERROR_TYPE_NO_PROPOSAL_CHOSEN: // Fallthrough + case IkeProtocolException.ERROR_TYPE_INVALID_KE_PAYLOAD: // Fallthrough + case IkeProtocolException.ERROR_TYPE_AUTHENTICATION_FAILED: // Fallthrough + case IkeProtocolException.ERROR_TYPE_SINGLE_PAIR_REQUIRED: // Fallthrough + case IkeProtocolException.ERROR_TYPE_FAILED_CP_REQUIRED: // Fallthrough + case IkeProtocolException.ERROR_TYPE_TS_UNACCEPTABLE: + // All the above failures are configuration errors, and are terminal + errorClass = VpnManager.ERROR_CLASS_NOT_RECOVERABLE; + break; + // All other cases possibly recoverable. + default: + errorClass = VpnManager.ERROR_CLASS_RECOVERABLE; + } + } else if (exception instanceof IkeNetworkLostException) { + category = VpnManager.CATEGORY_EVENT_NETWORK_ERROR; + errorClass = VpnManager.ERROR_CLASS_RECOVERABLE; + errorCode = VpnManager.ERROR_CODE_NETWORK_LOST; + } else if (exception instanceof IkeNonProtocolException) { + category = VpnManager.CATEGORY_EVENT_NETWORK_ERROR; + errorClass = VpnManager.ERROR_CLASS_RECOVERABLE; + if (exception.getCause() instanceof UnknownHostException) { + errorCode = VpnManager.ERROR_CODE_NETWORK_UNKNOWN_HOST; + } else if (exception.getCause() instanceof IkeTimeoutException) { + errorCode = VpnManager.ERROR_CODE_NETWORK_PROTOCOL_TIMEOUT; + } else if (exception.getCause() instanceof IOException) { + errorCode = VpnManager.ERROR_CODE_NETWORK_IO; + } + } else if (exception != null) { + Log.wtf(TAG, "onSessionLost: exception = " + exception); + } + synchronized (Vpn.this) { // Ignore stale runner. if (mVpnRunner != this) return; - if (exception instanceof IkeProtocolException) { - final IkeProtocolException ikeException = (IkeProtocolException) exception; - - switch (ikeException.getErrorType()) { - case IkeProtocolException.ERROR_TYPE_NO_PROPOSAL_CHOSEN: // Fallthrough - case IkeProtocolException.ERROR_TYPE_INVALID_KE_PAYLOAD: // Fallthrough - case IkeProtocolException.ERROR_TYPE_AUTHENTICATION_FAILED: // Fallthrough - case IkeProtocolException.ERROR_TYPE_SINGLE_PAIR_REQUIRED: // Fallthrough - case IkeProtocolException.ERROR_TYPE_FAILED_CP_REQUIRED: // Fallthrough - case IkeProtocolException.ERROR_TYPE_TS_UNACCEPTABLE: - // All the above failures are configuration errors, and are terminal - // TODO(b/230548427): Remove SDK check once VPN related stuff are - // decoupled from ConnectivityServiceTest. - if (SdkLevel.isAtLeastT() && isVpnApp(mPackage)) { - sendEventToVpnManagerApp(VpnManager.CATEGORY_EVENT_IKE_ERROR, - VpnManager.ERROR_CLASS_NOT_RECOVERABLE, - ikeException.getErrorType(), - getPackage(), mSessionKey, makeVpnProfileStateLocked(), - network, - getRedactedNetworkCapabilitiesOfUnderlyingNetwork( - mUnderlyingNetworkCapabilities), - getRedactedLinkPropertiesOfUnderlyingNetwork( - mUnderlyingLinkProperties)); - } - markFailedAndDisconnect(exception); - return; - // All other cases possibly recoverable. - default: - // All the above failures are configuration errors, and are terminal - // TODO(b/230548427): Remove SDK check once VPN related stuff are - // decoupled from ConnectivityServiceTest. - if (SdkLevel.isAtLeastT() && isVpnApp(mPackage)) { - sendEventToVpnManagerApp(VpnManager.CATEGORY_EVENT_IKE_ERROR, - VpnManager.ERROR_CLASS_RECOVERABLE, - ikeException.getErrorType(), - getPackage(), mSessionKey, makeVpnProfileStateLocked(), - network, - getRedactedNetworkCapabilitiesOfUnderlyingNetwork( - mUnderlyingNetworkCapabilities), - getRedactedLinkPropertiesOfUnderlyingNetwork( - mUnderlyingLinkProperties)); - } - } - } else if (exception instanceof IllegalArgumentException) { - // Failed to build IKE/ChildSessionParams; fatal profile configuration error - markFailedAndDisconnect(exception); - return; - } else if (exception instanceof IkeNetworkLostException) { - // TODO(b/230548427): Remove SDK check once VPN related stuff are - // decoupled from ConnectivityServiceTest. - if (SdkLevel.isAtLeastT() && isVpnApp(mPackage)) { - sendEventToVpnManagerApp(VpnManager.CATEGORY_EVENT_NETWORK_ERROR, - VpnManager.ERROR_CLASS_RECOVERABLE, - VpnManager.ERROR_CODE_NETWORK_LOST, - getPackage(), mSessionKey, makeVpnProfileStateLocked(), - network, - getRedactedNetworkCapabilitiesOfUnderlyingNetwork( - mUnderlyingNetworkCapabilities), - getRedactedLinkPropertiesOfUnderlyingNetwork( - mUnderlyingLinkProperties)); - } - } else if (exception instanceof IkeNonProtocolException) { - if (exception.getCause() instanceof UnknownHostException) { - // TODO(b/230548427): Remove SDK check once VPN related stuff are - // decoupled from ConnectivityServiceTest. - if (SdkLevel.isAtLeastT() && isVpnApp(mPackage)) { - sendEventToVpnManagerApp(VpnManager.CATEGORY_EVENT_NETWORK_ERROR, - VpnManager.ERROR_CLASS_RECOVERABLE, - VpnManager.ERROR_CODE_NETWORK_UNKNOWN_HOST, - getPackage(), mSessionKey, makeVpnProfileStateLocked(), - network, - getRedactedNetworkCapabilitiesOfUnderlyingNetwork( - mUnderlyingNetworkCapabilities), - getRedactedLinkPropertiesOfUnderlyingNetwork( - mUnderlyingLinkProperties)); - } - } else if (exception.getCause() instanceof IkeTimeoutException) { - // TODO(b/230548427): Remove SDK check once VPN related stuff are - // decoupled from ConnectivityServiceTest. - if (SdkLevel.isAtLeastT() && isVpnApp(mPackage)) { - sendEventToVpnManagerApp(VpnManager.CATEGORY_EVENT_NETWORK_ERROR, - VpnManager.ERROR_CLASS_RECOVERABLE, - VpnManager.ERROR_CODE_NETWORK_PROTOCOL_TIMEOUT, - getPackage(), mSessionKey, makeVpnProfileStateLocked(), - network, - getRedactedNetworkCapabilitiesOfUnderlyingNetwork( - mUnderlyingNetworkCapabilities), - getRedactedLinkPropertiesOfUnderlyingNetwork( - mUnderlyingLinkProperties)); - } - } else if (exception.getCause() instanceof IOException) { - // TODO(b/230548427): Remove SDK check once VPN related stuff are - // decoupled from ConnectivityServiceTest. - if (SdkLevel.isAtLeastT() && isVpnApp(mPackage)) { - sendEventToVpnManagerApp(VpnManager.CATEGORY_EVENT_NETWORK_ERROR, - VpnManager.ERROR_CLASS_RECOVERABLE, - VpnManager.ERROR_CODE_NETWORK_IO, - getPackage(), mSessionKey, makeVpnProfileStateLocked(), - network, - getRedactedNetworkCapabilitiesOfUnderlyingNetwork( - mUnderlyingNetworkCapabilities), - getRedactedLinkPropertiesOfUnderlyingNetwork( - mUnderlyingLinkProperties)); - } - } - } else if (exception != null) { - Log.wtf(TAG, "onSessionLost: exception = " + exception); + // TODO(b/230548427): Remove SDK check once VPN related stuff are + // decoupled from ConnectivityServiceTest. + if (SdkLevel.isAtLeastT() && category != null && isVpnApp(mPackage)) { + sendEventToVpnManagerApp(category, errorClass, errorCode, + getPackage(), mSessionKey, makeVpnProfileStateLocked(), + mActiveNetwork, + getRedactedNetworkCapabilities(mUnderlyingNetworkCapabilities), + getRedactedLinkProperties(mUnderlyingLinkProperties)); } + } + if (errorClass == VpnManager.ERROR_CLASS_NOT_RECOVERABLE) { + markFailedAndDisconnect(exception); + return; + } else { scheduleRetryNewIkeSession(); } @@ -4110,6 +4050,29 @@ public class Vpn { } } + @GuardedBy("this") + private void stopVpnRunnerAndNotifyAppLocked(@NonNull String packageName) { + // Build intent first because the sessionKey will be reset after performing + // VpnRunner.exit(). Also, cache mOwnerUID even if ownerUID will not be changed in + // VpnRunner.exit() to prevent design being changed in the future. + // TODO(b/230548427): Remove SDK check once VPN related stuff are decoupled from + // ConnectivityServiceTest. + final int ownerUid = mOwnerUID; + Intent intent = null; + if (SdkLevel.isAtLeastT() && isVpnApp(packageName)) { + intent = buildVpnManagerEventIntent( + VpnManager.CATEGORY_EVENT_DEACTIVATED_BY_USER, + -1 /* errorClass */, -1 /* errorCode*/, packageName, + getSessionKeyLocked(), makeVpnProfileStateLocked(), + null /* underlyingNetwork */, null /* nc */, null /* lp */); + } + // cleanupVpnStateLocked() is called from mVpnRunner.exit() + mVpnRunner.exit(); + if (intent != null && isVpnApp(packageName)) { + notifyVpnManagerVpnStopped(packageName, ownerUid, intent); + } + } + /** * Stops an already running VPN Profile for the given package. * @@ -4126,18 +4089,7 @@ public class Vpn { // To stop the VPN profile, the caller must be the current prepared package and must be // running an Ikev2VpnProfile. if (isCurrentIkev2VpnLocked(packageName)) { - // Build intent first because the sessionKey will be reset after performing - // VpnRunner.exit(). Also, cache mOwnerUID even if ownerUID will not be changed in - // VpnRunner.exit() to prevent design being changed in the future. - final int ownerUid = mOwnerUID; - final Intent intent = buildVpnManagerEventIntent( - VpnManager.CATEGORY_EVENT_DEACTIVATED_BY_USER, - -1 /* errorClass */, -1 /* errorCode*/, packageName, - getSessionKeyLocked(), makeVpnProfileStateLocked(), - null /* underlyingNetwork */, null /* nc */, null /* lp */); - - mVpnRunner.exit(); - notifyVpnManagerVpnStopped(packageName, ownerUid, intent); + stopVpnRunnerAndNotifyAppLocked(packageName); } } diff --git a/services/core/java/com/android/server/display/AutomaticBrightnessController.java b/services/core/java/com/android/server/display/AutomaticBrightnessController.java index 31562c735f3a..a7d372977ebb 100644 --- a/services/core/java/com/android/server/display/AutomaticBrightnessController.java +++ b/services/core/java/com/android/server/display/AutomaticBrightnessController.java @@ -131,6 +131,8 @@ class AutomaticBrightnessController { // Configuration object for determining thresholds to change brightness dynamically private final HysteresisLevels mAmbientBrightnessThresholds; private final HysteresisLevels mScreenBrightnessThresholds; + private final HysteresisLevels mAmbientBrightnessThresholdsIdle; + private final HysteresisLevels mScreenBrightnessThresholdsIdle; private boolean mLoggingEnabled; @@ -242,7 +244,9 @@ class AutomaticBrightnessController { float dozeScaleFactor, int lightSensorRate, int initialLightSensorRate, long brighteningLightDebounceConfig, long darkeningLightDebounceConfig, boolean resetAmbientLuxAfterWarmUpConfig, HysteresisLevels ambientBrightnessThresholds, - HysteresisLevels screenBrightnessThresholds, Context context, + HysteresisLevels screenBrightnessThresholds, + HysteresisLevels ambientBrightnessThresholdsIdle, + HysteresisLevels screenBrightnessThresholdsIdle, Context context, HighBrightnessModeController hbmController, BrightnessThrottler brightnessThrottler, BrightnessMappingStrategy idleModeBrightnessMapper, int ambientLightHorizonShort, int ambientLightHorizonLong) { @@ -251,7 +255,8 @@ class AutomaticBrightnessController { lightSensorWarmUpTime, brightnessMin, brightnessMax, dozeScaleFactor, lightSensorRate, initialLightSensorRate, brighteningLightDebounceConfig, darkeningLightDebounceConfig, resetAmbientLuxAfterWarmUpConfig, - ambientBrightnessThresholds, screenBrightnessThresholds, context, + ambientBrightnessThresholds, screenBrightnessThresholds, + ambientBrightnessThresholdsIdle, screenBrightnessThresholdsIdle, context, hbmController, brightnessThrottler, idleModeBrightnessMapper, ambientLightHorizonShort, ambientLightHorizonLong ); @@ -265,7 +270,9 @@ class AutomaticBrightnessController { float dozeScaleFactor, int lightSensorRate, int initialLightSensorRate, long brighteningLightDebounceConfig, long darkeningLightDebounceConfig, boolean resetAmbientLuxAfterWarmUpConfig, HysteresisLevels ambientBrightnessThresholds, - HysteresisLevels screenBrightnessThresholds, Context context, + HysteresisLevels screenBrightnessThresholds, + HysteresisLevels ambientBrightnessThresholdsIdle, + HysteresisLevels screenBrightnessThresholdsIdle, Context context, HighBrightnessModeController hbmController, BrightnessThrottler brightnessThrottler, BrightnessMappingStrategy idleModeBrightnessMapper, int ambientLightHorizonShort, int ambientLightHorizonLong) { @@ -289,7 +296,9 @@ class AutomaticBrightnessController { mAmbientLightHorizonShort = ambientLightHorizonShort; mWeightingIntercept = ambientLightHorizonLong; mAmbientBrightnessThresholds = ambientBrightnessThresholds; + mAmbientBrightnessThresholdsIdle = ambientBrightnessThresholdsIdle; mScreenBrightnessThresholds = screenBrightnessThresholds; + mScreenBrightnessThresholdsIdle = screenBrightnessThresholdsIdle; mShortTermModelValid = true; mShortTermModelAnchor = -1; mHandler = new AutomaticBrightnessHandler(looper); @@ -585,6 +594,8 @@ class AutomaticBrightnessController { pw.println(); mAmbientBrightnessThresholds.dump(pw); mScreenBrightnessThresholds.dump(pw); + mScreenBrightnessThresholdsIdle.dump(pw); + mScreenBrightnessThresholdsIdle.dump(pw); } private String configStateToString(int state) { @@ -679,8 +690,17 @@ class AutomaticBrightnessController { lux = 0; } mAmbientLux = lux; - mAmbientBrighteningThreshold = mAmbientBrightnessThresholds.getBrighteningThreshold(lux); - mAmbientDarkeningThreshold = mAmbientBrightnessThresholds.getDarkeningThreshold(lux); + if (isInIdleMode()) { + mAmbientBrighteningThreshold = + mAmbientBrightnessThresholdsIdle.getBrighteningThreshold(lux); + mAmbientDarkeningThreshold = + mAmbientBrightnessThresholdsIdle.getDarkeningThreshold(lux); + } else { + mAmbientBrighteningThreshold = + mAmbientBrightnessThresholds.getBrighteningThreshold(lux); + mAmbientDarkeningThreshold = + mAmbientBrightnessThresholds.getDarkeningThreshold(lux); + } mHbmController.onAmbientLuxChange(mAmbientLux); // If the short term model was invalidated and the change is drastic enough, reset it. @@ -902,10 +922,20 @@ class AutomaticBrightnessController { mPreThresholdBrightness = mScreenAutoBrightness; } mScreenAutoBrightness = newScreenAutoBrightness; - mScreenBrighteningThreshold = clampScreenBrightness( - mScreenBrightnessThresholds.getBrighteningThreshold(newScreenAutoBrightness)); - mScreenDarkeningThreshold = clampScreenBrightness( - mScreenBrightnessThresholds.getDarkeningThreshold(newScreenAutoBrightness)); + if (isInIdleMode()) { + mScreenBrighteningThreshold = clampScreenBrightness( + mScreenBrightnessThresholdsIdle.getBrighteningThreshold( + newScreenAutoBrightness)); + mScreenDarkeningThreshold = clampScreenBrightness( + mScreenBrightnessThresholdsIdle.getDarkeningThreshold( + newScreenAutoBrightness)); + } else { + mScreenBrighteningThreshold = clampScreenBrightness( + mScreenBrightnessThresholds.getBrighteningThreshold( + newScreenAutoBrightness)); + mScreenDarkeningThreshold = clampScreenBrightness( + mScreenBrightnessThresholds.getDarkeningThreshold(newScreenAutoBrightness)); + } if (sendUpdate) { mCallbacks.updateBrightness(); diff --git a/services/core/java/com/android/server/display/DisplayDeviceConfig.java b/services/core/java/com/android/server/display/DisplayDeviceConfig.java index 12b2f4773387..416518613568 100644 --- a/services/core/java/com/android/server/display/DisplayDeviceConfig.java +++ b/services/core/java/com/android/server/display/DisplayDeviceConfig.java @@ -188,8 +188,8 @@ import javax.xml.datatype.DatatypeConfigurationException; * <ambientLightHorizonLong>10001</ambientLightHorizonLong> * <ambientLightHorizonShort>2001</ambientLightHorizonShort> * - * <displayBrightnessChangeThresholds> - * <brighteningThresholds> + * <displayBrightnessChangeThresholds> // Thresholds for screen changes + * <brighteningThresholds> // Thresholds for active mode brightness changes. * <minimum>0.001</minimum> // Minimum change needed in screen brightness to brighten. * </brighteningThresholds> * <darkeningThresholds> @@ -197,8 +197,8 @@ import javax.xml.datatype.DatatypeConfigurationException; * </darkeningThresholds> * </displayBrightnessChangeThresholds> * - * <ambientBrightnessChangeThresholds> - * <brighteningThresholds> + * <ambientBrightnessChangeThresholds> // Thresholds for lux changes + * <brighteningThresholds> // Thresholds for active mode brightness changes. * <minimum>0.003</minimum> // Minimum change needed in ambient brightness to brighten. * </brighteningThresholds> * <darkeningThresholds> @@ -206,6 +206,24 @@ import javax.xml.datatype.DatatypeConfigurationException; * </darkeningThresholds> * </ambientBrightnessChangeThresholds> * + * <displayBrightnessChangeThresholdsIdle> // Thresholds for screen changes in idle mode + * <brighteningThresholds> // Thresholds for idle mode brightness changes. + * <minimum>0.001</minimum> // Minimum change needed in screen brightness to brighten. + * </brighteningThresholds> + * <darkeningThresholds> + * <minimum>0.002</minimum> // Minimum change needed in screen brightness to darken. + * </darkeningThresholds> + * </displayBrightnessChangeThresholdsIdle> + * + * <ambientBrightnessChangeThresholdsIdle> // Thresholds for lux changes in idle mode + * <brighteningThresholds> // Thresholds for idle mode brightness changes. + * <minimum>0.003</minimum> // Minimum change needed in ambient brightness to brighten. + * </brighteningThresholds> + * <darkeningThresholds> + * <minimum>0.004</minimum> // Minimum change needed in ambient brightness to darken. + * </darkeningThresholds> + * </ambientBrightnessChangeThresholdsIdle> + * * </displayConfiguration> * } * </pre> @@ -319,9 +337,13 @@ public class DisplayDeviceConfig { private int mAmbientHorizonLong = AMBIENT_LIGHT_LONG_HORIZON_MILLIS; private int mAmbientHorizonShort = AMBIENT_LIGHT_SHORT_HORIZON_MILLIS; private float mScreenBrighteningMinThreshold = 0.0f; // Retain behaviour as though there is - private float mScreenDarkeningMinThreshold = 0.0f; // no minimum threshold for change in - private float mAmbientLuxBrighteningMinThreshold = 0.0f; // screen brightness or ambient - private float mAmbientLuxDarkeningMinThreshold = 0.0f; // brightness. + private float mScreenBrighteningMinThresholdIdle = 0.0f; // no minimum threshold for change in + private float mScreenDarkeningMinThreshold = 0.0f; // screen brightness or ambient + private float mScreenDarkeningMinThresholdIdle = 0.0f; // brightness. + private float mAmbientLuxBrighteningMinThreshold = 0.0f; + private float mAmbientLuxBrighteningMinThresholdIdle = 0.0f; + private float mAmbientLuxDarkeningMinThreshold = 0.0f; + private float mAmbientLuxDarkeningMinThresholdIdle = 0.0f; private Spline mBrightnessToBacklightSpline; private Spline mBacklightToBrightnessSpline; private Spline mBacklightToNitsSpline; @@ -625,22 +647,76 @@ public class DisplayDeviceConfig { return mAmbientHorizonShort; } + /** + * The minimum value for the screen brightness increase to actually occur. + * @return float value in brightness scale of 0 - 1. + */ public float getScreenBrighteningMinThreshold() { return mScreenBrighteningMinThreshold; } + /** + * The minimum value for the screen brightness decrease to actually occur. + * @return float value in brightness scale of 0 - 1. + */ public float getScreenDarkeningMinThreshold() { return mScreenDarkeningMinThreshold; } + /** + * The minimum value for the screen brightness increase to actually occur while in idle screen + * brightness mode. + * @return float value in brightness scale of 0 - 1. + */ + public float getScreenBrighteningMinThresholdIdle() { + return mScreenBrighteningMinThresholdIdle; + } + + /** + * The minimum value for the screen brightness decrease to actually occur while in idle screen + * brightness mode. + * @return float value in brightness scale of 0 - 1. + */ + public float getScreenDarkeningMinThresholdIdle() { + return mScreenDarkeningMinThresholdIdle; + } + + /** + * The minimum value for the ambient lux increase for a screen brightness change to actually + * occur. + * @return float value in brightness scale of 0 - 1. + */ public float getAmbientLuxBrighteningMinThreshold() { return mAmbientLuxBrighteningMinThreshold; } + /** + * The minimum value for the ambient lux decrease for a screen brightness change to actually + * occur. + * @return float value in brightness scale of 0 - 1. + */ public float getAmbientLuxDarkeningMinThreshold() { return mAmbientLuxDarkeningMinThreshold; } + /** + * The minimum value for the ambient lux increase for a screen brightness change to actually + * occur while in idle screen brightness mode. + * @return float value in brightness scale of 0 - 1. + */ + public float getAmbientLuxBrighteningMinThresholdIdle() { + return mAmbientLuxBrighteningMinThresholdIdle; + } + + /** + * The minimum value for the ambient lux decrease for a screen brightness change to actually + * occur while in idle screen brightness mode. + * @return float value in brightness scale of 0 - 1. + */ + public float getAmbientLuxDarkeningMinThresholdIdle() { + return mAmbientLuxDarkeningMinThresholdIdle; + } + SensorData getAmbientLightSensor() { return mAmbientLightSensor; } @@ -745,9 +821,14 @@ public class DisplayDeviceConfig { + ", mAmbientHorizonLong=" + mAmbientHorizonLong + ", mAmbientHorizonShort=" + mAmbientHorizonShort + ", mScreenDarkeningMinThreshold=" + mScreenDarkeningMinThreshold + + ", mScreenDarkeningMinThresholdIdle=" + mScreenDarkeningMinThresholdIdle + ", mScreenBrighteningMinThreshold=" + mScreenBrighteningMinThreshold + + ", mScreenBrighteningMinThresholdIdle=" + mScreenBrighteningMinThresholdIdle + ", mAmbientLuxDarkeningMinThreshold=" + mAmbientLuxDarkeningMinThreshold + + ", mAmbientLuxDarkeningMinThresholdIdle=" + mAmbientLuxDarkeningMinThresholdIdle + ", mAmbientLuxBrighteningMinThreshold=" + mAmbientLuxBrighteningMinThreshold + + ", mAmbientLuxBrighteningMinThresholdIdle=" + + mAmbientLuxBrighteningMinThresholdIdle + ", mAmbientLightSensor=" + mAmbientLightSensor + ", mProximitySensor=" + mProximitySensor + ", mRefreshRateLimitations= " + Arrays.toString(mRefreshRateLimitations.toArray()) @@ -1376,24 +1457,34 @@ public class DisplayDeviceConfig { private void loadBrightnessChangeThresholds(DisplayConfiguration config) { Thresholds displayBrightnessThresholds = config.getDisplayBrightnessChangeThresholds(); Thresholds ambientBrightnessThresholds = config.getAmbientBrightnessChangeThresholds(); + Thresholds displayBrightnessThresholdsIdle = + config.getDisplayBrightnessChangeThresholdsIdle(); + Thresholds ambientBrightnessThresholdsIdle = + config.getAmbientBrightnessChangeThresholdsIdle(); + loadDisplayBrightnessThresholds(displayBrightnessThresholds); + loadAmbientBrightnessThresholds(ambientBrightnessThresholds); + loadIdleDisplayBrightnessThresholds(displayBrightnessThresholdsIdle); + loadIdleAmbientBrightnessThresholds(ambientBrightnessThresholdsIdle); + } + + private void loadDisplayBrightnessThresholds(Thresholds displayBrightnessThresholds) { if (displayBrightnessThresholds != null) { BrightnessThresholds brighteningScreen = displayBrightnessThresholds.getBrighteningThresholds(); BrightnessThresholds darkeningScreen = displayBrightnessThresholds.getDarkeningThresholds(); - final BigDecimal screenBrighteningThreshold = brighteningScreen.getMinimum(); - final BigDecimal screenDarkeningThreshold = darkeningScreen.getMinimum(); - - if (screenBrighteningThreshold != null) { - mScreenBrighteningMinThreshold = screenBrighteningThreshold.floatValue(); + if (brighteningScreen != null && brighteningScreen.getMinimum() != null) { + mScreenBrighteningMinThreshold = brighteningScreen.getMinimum().floatValue(); } - if (screenDarkeningThreshold != null) { - mScreenDarkeningMinThreshold = screenDarkeningThreshold.floatValue(); + if (darkeningScreen != null && darkeningScreen.getMinimum() != null) { + mScreenDarkeningMinThreshold = darkeningScreen.getMinimum().floatValue(); } } + } + private void loadAmbientBrightnessThresholds(Thresholds ambientBrightnessThresholds) { if (ambientBrightnessThresholds != null) { BrightnessThresholds brighteningAmbientLux = ambientBrightnessThresholds.getBrighteningThresholds(); @@ -1412,6 +1503,44 @@ public class DisplayDeviceConfig { } } + private void loadIdleDisplayBrightnessThresholds(Thresholds idleDisplayBrightnessThresholds) { + if (idleDisplayBrightnessThresholds != null) { + BrightnessThresholds brighteningScreenIdle = + idleDisplayBrightnessThresholds.getBrighteningThresholds(); + BrightnessThresholds darkeningScreenIdle = + idleDisplayBrightnessThresholds.getDarkeningThresholds(); + + if (brighteningScreenIdle != null + && brighteningScreenIdle.getMinimum() != null) { + mScreenBrighteningMinThresholdIdle = + brighteningScreenIdle.getMinimum().floatValue(); + } + if (darkeningScreenIdle != null && darkeningScreenIdle.getMinimum() != null) { + mScreenDarkeningMinThresholdIdle = + darkeningScreenIdle.getMinimum().floatValue(); + } + } + } + + private void loadIdleAmbientBrightnessThresholds(Thresholds idleAmbientBrightnessThresholds) { + if (idleAmbientBrightnessThresholds != null) { + BrightnessThresholds brighteningAmbientLuxIdle = + idleAmbientBrightnessThresholds.getBrighteningThresholds(); + BrightnessThresholds darkeningAmbientLuxIdle = + idleAmbientBrightnessThresholds.getDarkeningThresholds(); + + if (brighteningAmbientLuxIdle != null + && brighteningAmbientLuxIdle.getMinimum() != null) { + mAmbientLuxBrighteningMinThresholdIdle = + brighteningAmbientLuxIdle.getMinimum().floatValue(); + } + if (darkeningAmbientLuxIdle != null && darkeningAmbientLuxIdle.getMinimum() != null) { + mAmbientLuxDarkeningMinThresholdIdle = + darkeningAmbientLuxIdle.getMinimum().floatValue(); + } + } + } + private boolean thermalStatusIsValid(ThermalStatus value) { if (value == null) { return false; diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java index 2deb0565f018..8b5c3115fce4 100644 --- a/services/core/java/com/android/server/display/DisplayPowerController.java +++ b/services/core/java/com/android/server/display/DisplayPowerController.java @@ -985,6 +985,25 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call screenBrighteningThresholds, screenDarkeningThresholds, screenThresholdLevels, screenDarkeningMinThreshold, screenBrighteningMinThreshold); + // Idle screen thresholds + float screenDarkeningMinThresholdIdle = + mDisplayDeviceConfig.getScreenDarkeningMinThresholdIdle(); + float screenBrighteningMinThresholdIdle = + mDisplayDeviceConfig.getScreenBrighteningMinThresholdIdle(); + HysteresisLevels screenBrightnessThresholdsIdle = new HysteresisLevels( + screenBrighteningThresholds, screenDarkeningThresholds, screenThresholdLevels, + screenDarkeningMinThresholdIdle, screenBrighteningMinThresholdIdle); + + // Idle ambient thresholds + float ambientDarkeningMinThresholdIdle = + mDisplayDeviceConfig.getAmbientLuxDarkeningMinThresholdIdle(); + float ambientBrighteningMinThresholdIdle = + mDisplayDeviceConfig.getAmbientLuxBrighteningMinThresholdIdle(); + HysteresisLevels ambientBrightnessThresholdsIdle = new HysteresisLevels( + ambientBrighteningThresholds, ambientDarkeningThresholds, + ambientThresholdLevels, ambientDarkeningMinThresholdIdle, + ambientBrighteningMinThresholdIdle); + long brighteningLightDebounce = mDisplayDeviceConfig .getAutoBrightnessBrighteningLightDebounce(); long darkeningLightDebounce = mDisplayDeviceConfig @@ -1020,7 +1039,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call PowerManager.BRIGHTNESS_MIN, PowerManager.BRIGHTNESS_MAX, dozeScaleFactor, lightSensorRate, initialLightSensorRate, brighteningLightDebounce, darkeningLightDebounce, autoBrightnessResetAmbientLuxAfterWarmUp, - ambientBrightnessThresholds, screenBrightnessThresholds, mContext, + ambientBrightnessThresholds, screenBrightnessThresholds, + ambientBrightnessThresholdsIdle, screenBrightnessThresholdsIdle, mContext, mHbmController, mBrightnessThrottler, mIdleModeBrightnessMapper, mDisplayDeviceConfig.getAmbientHorizonShort(), mDisplayDeviceConfig.getAmbientHorizonLong()); diff --git a/services/core/java/com/android/server/display/HysteresisLevels.java b/services/core/java/com/android/server/display/HysteresisLevels.java index 7a932ce6d7cf..34134892552f 100644 --- a/services/core/java/com/android/server/display/HysteresisLevels.java +++ b/services/core/java/com/android/server/display/HysteresisLevels.java @@ -18,15 +18,12 @@ package com.android.server.display; import android.util.Slog; -import com.android.internal.annotations.VisibleForTesting; - import java.io.PrintWriter; import java.util.Arrays; /** * A helper class for handling access to illuminance hysteresis level values. */ -@VisibleForTesting public class HysteresisLevels { private static final String TAG = "HysteresisLevels"; diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java index 2a219289cf10..efb2cb7a3283 100644 --- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java +++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java @@ -411,11 +411,8 @@ final class LocalDisplayAdapter extends DisplayAdapter { // For a new display, we need to initialize the default mode ID. if (mDefaultModeId == INVALID_MODE_ID) { - mDefaultModeId = mSystemPreferredModeId != INVALID_MODE_ID - ? mSystemPreferredModeId : activeRecord.mMode.getModeId(); - mDefaultModeGroup = mSystemPreferredModeId != INVALID_MODE_ID - ? preferredSfDisplayMode.group - : mActiveSfDisplayMode.group; + mDefaultModeId = activeRecord.mMode.getModeId(); + mDefaultModeGroup = mActiveSfDisplayMode.group; } else if (modesAdded && activeModeChanged) { Slog.d(TAG, "New display modes are added and the active mode has changed, " + "use active mode as default mode."); @@ -897,6 +894,13 @@ final class LocalDisplayAdapter extends DisplayAdapter { public void setUserPreferredDisplayModeLocked(Display.Mode mode) { final int oldModeId = getPreferredModeId(); mUserPreferredMode = mode; + // When clearing the user preferred mode we need to also reset the default mode. This is + // used by DisplayModeDirector to determine the default resolution, so if we don't clear + // it then the resolution won't reset to what it would've been prior to setting a user + // preferred display mode. + if (mode == null && mSystemPreferredModeId != INVALID_MODE_ID) { + mDefaultModeId = mSystemPreferredModeId; + } if (mode != null && (mode.isRefreshRateSet() || mode.isResolutionSet())) { Display.Mode matchingSupportedMode; matchingSupportedMode = findMode(mode.getPhysicalWidth(), diff --git a/services/core/java/com/android/server/location/LocationManagerService.java b/services/core/java/com/android/server/location/LocationManagerService.java index e5eed9928411..3ff879661bda 100644 --- a/services/core/java/com/android/server/location/LocationManagerService.java +++ b/services/core/java/com/android/server/location/LocationManagerService.java @@ -675,6 +675,11 @@ public class LocationManagerService extends ILocationManager.Stub implements return mInjector.getSettingsHelper().getIgnoreSettingsAllowlist(); } + @Override + public PackageTagsList getAdasAllowlist() { + return mInjector.getSettingsHelper().getAdasAllowlist(); + } + @Nullable @Override public ICancellationSignal getCurrentLocation(String provider, LocationRequest request, diff --git a/services/core/java/com/android/server/logcat/LogAccessDialogActivity.java b/services/core/java/com/android/server/logcat/LogAccessDialogActivity.java index 98bae3dc247b..811e96ce6d82 100644 --- a/services/core/java/com/android/server/logcat/LogAccessDialogActivity.java +++ b/services/core/java/com/android/server/logcat/LogAccessDialogActivity.java @@ -96,6 +96,7 @@ public class LogAccessDialogActivity extends Activity implements // show Alert mAlert = mAlertDialog.create(); + mAlert.getWindow().setHideOverlayWindows(true); mAlert.show(); // set Alert Timeout diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java index 0fac808fb13b..4d55d4e545ee 100644 --- a/services/core/java/com/android/server/notification/ManagedServices.java +++ b/services/core/java/com/android/server/notification/ManagedServices.java @@ -1786,8 +1786,8 @@ abstract public class ManagedServices { * from receiving events from the profile. */ public boolean isPermittedForProfile(int userId) { - if (!mUserProfiles.canProfileUseBoundServices(userId)) { - return false; + if (!mUserProfiles.isProfileUser(userId)) { + return true; } DevicePolicyManager dpm = (DevicePolicyManager) mContext.getSystemService(DEVICE_POLICY_SERVICE); @@ -1862,16 +1862,16 @@ abstract public class ManagedServices { } } - public boolean canProfileUseBoundServices(int userId) { + public boolean isProfileUser(int userId) { synchronized (mCurrentProfiles) { UserInfo user = mCurrentProfiles.get(userId); if (user == null) { return false; } if (user.isManagedProfile() || user.isCloneProfile()) { - return false; + return true; } - return true; + return false; } } } diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 4e0cc61a061f..f11801f61d58 100755 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -1828,7 +1828,7 @@ public class NotificationManagerService extends SystemService { } else if (action.equals(Intent.ACTION_USER_SWITCHED)) { final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, USER_NULL); mUserProfiles.updateCache(context); - if (mUserProfiles.canProfileUseBoundServices(userId)) { + if (!mUserProfiles.isProfileUser(userId)) { // reload per-user settings mSettingsObserver.update(null); // Refresh managed services @@ -1842,7 +1842,7 @@ public class NotificationManagerService extends SystemService { final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, USER_NULL); if (userId != USER_NULL) { mUserProfiles.updateCache(context); - if (mUserProfiles.canProfileUseBoundServices(userId)) { + if (!mUserProfiles.isProfileUser(userId)) { allowDefaultApprovedServices(userId); } } @@ -1860,7 +1860,7 @@ public class NotificationManagerService extends SystemService { final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, USER_NULL); mUserProfiles.updateCache(context); mAssistants.onUserUnlocked(userId); - if (mUserProfiles.canProfileUseBoundServices(userId)) { + if (!mUserProfiles.isProfileUser(userId)) { mConditionProviders.onUserUnlocked(userId); mListeners.onUserUnlocked(userId); mZenModeHelper.onUserUnlocked(userId); diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java index 477b8da61e0f..d8aa469bcd81 100644 --- a/services/core/java/com/android/server/notification/PreferencesHelper.java +++ b/services/core/java/com/android/server/notification/PreferencesHelper.java @@ -106,7 +106,7 @@ public class PreferencesHelper implements RankingConfig { private static final String NON_BLOCKABLE_CHANNEL_DELIM = ":"; @VisibleForTesting - static final int NOTIFICATION_CHANNEL_COUNT_LIMIT = 50000; + static final int NOTIFICATION_CHANNEL_COUNT_LIMIT = 5000; @VisibleForTesting static final int NOTIFICATION_CHANNEL_GROUP_COUNT_LIMIT = 50000; diff --git a/services/core/java/com/android/server/pm/DeletePackageHelper.java b/services/core/java/com/android/server/pm/DeletePackageHelper.java index c3b479219853..0915c21dda59 100644 --- a/services/core/java/com/android/server/pm/DeletePackageHelper.java +++ b/services/core/java/com/android/server/pm/DeletePackageHelper.java @@ -657,6 +657,18 @@ final class DeletePackageHelper { final String packageName = versionedPackage.getPackageName(); final long versionCode = versionedPackage.getLongVersionCode(); + if (mPm.mProtectedPackages.isPackageDataProtected(userId, packageName)) { + mPm.mHandler.post(() -> { + try { + Slog.w(TAG, "Attempted to delete protected package: " + packageName); + observer.onPackageDeleted(packageName, + PackageManager.DELETE_FAILED_INTERNAL_ERROR, null); + } catch (RemoteException re) { + } + }); + return; + } + try { if (mPm.mInjector.getLocalService(ActivityTaskManagerInternal.class) .isBaseOfLockedTask(packageName)) { diff --git a/services/core/java/com/android/server/pm/SuspendPackageHelper.java b/services/core/java/com/android/server/pm/SuspendPackageHelper.java index 908b12e1752d..7ad4d226d801 100644 --- a/services/core/java/com/android/server/pm/SuspendPackageHelper.java +++ b/services/core/java/com/android/server/pm/SuspendPackageHelper.java @@ -160,9 +160,11 @@ public final class SuspendPackageHelper { } } - // If size one, the package will be unsuspended from this call - boolean packageUnsuspended = - !suspended && CollectionUtils.size(suspendParamsMap) <= 1; + // If only the callingPackage is suspending this package, + // it will be unsuspended when this change is committed + boolean packageUnsuspended = !suspended + && CollectionUtils.size(suspendParamsMap) == 1 + && suspendParamsMap.containsKey(callingPackage); if (suspended || packageUnsuspended) { changedPackagesList.add(packageName); changedUids.add(UserHandle.getUid(userId, packageState.getAppId())); diff --git a/services/core/java/com/android/server/powerstats/PowerStatsDataStorage.java b/services/core/java/com/android/server/powerstats/PowerStatsDataStorage.java index 06253a08d937..8b30995404f0 100644 --- a/services/core/java/com/android/server/powerstats/PowerStatsDataStorage.java +++ b/services/core/java/com/android/server/powerstats/PowerStatsDataStorage.java @@ -220,18 +220,17 @@ public class PowerStatsDataStorage { public void write(byte[] data) { if (data != null && data.length > 0) { mLock.lock(); - - long currentTimeMillis = System.currentTimeMillis(); try { + long currentTimeMillis = System.currentTimeMillis(); DataElement dataElement = new DataElement(data); mFileRotator.rewriteActive(new DataRewriter(dataElement.toByteArray()), currentTimeMillis); mFileRotator.maybeRotate(currentTimeMillis); } catch (IOException e) { Slog.e(TAG, "Failed to write to on-device storage: " + e); + } finally { + mLock.unlock(); } - - mLock.unlock(); } } @@ -240,21 +239,31 @@ public class PowerStatsDataStorage { * DataElement retrieved from on-device storage, callback is called. */ public void read(DataElementReadCallback callback) throws IOException { - mFileRotator.readMatching(new DataReader(callback), Long.MIN_VALUE, Long.MAX_VALUE); + mLock.lock(); + try { + mFileRotator.readMatching(new DataReader(callback), Long.MIN_VALUE, Long.MAX_VALUE); + } finally { + mLock.unlock(); + } } /** * Deletes all stored log data. */ public void deleteLogs() { - File[] files = mDataStorageDir.listFiles(); - for (int i = 0; i < files.length; i++) { - int versionDot = mDataStorageFilename.lastIndexOf('.'); - String beforeVersionDot = mDataStorageFilename.substring(0, versionDot); - // Check that the stems before the version match. - if (files[i].getName().startsWith(beforeVersionDot)) { - files[i].delete(); + mLock.lock(); + try { + File[] files = mDataStorageDir.listFiles(); + for (int i = 0; i < files.length; i++) { + int versionDot = mDataStorageFilename.lastIndexOf('.'); + String beforeVersionDot = mDataStorageFilename.substring(0, versionDot); + // Check that the stems before the version match. + if (files[i].getName().startsWith(beforeVersionDot)) { + files[i].delete(); + } } + } finally { + mLock.unlock(); } } } diff --git a/services/core/java/com/android/server/powerstats/PowerStatsLogger.java b/services/core/java/com/android/server/powerstats/PowerStatsLogger.java index ca675973b2fd..39ead13b03fe 100644 --- a/services/core/java/com/android/server/powerstats/PowerStatsLogger.java +++ b/services/core/java/com/android/server/powerstats/PowerStatsLogger.java @@ -159,12 +159,12 @@ public final class PowerStatsLogger extends Handler { EnergyMeasurementUtils.packProtoMessage(energyMeasurement, pos); if (DEBUG) EnergyMeasurementUtils.print(energyMeasurement); } catch (IOException e) { - Slog.e(TAG, "Failed to write energy meter data to incident report."); + Slog.e(TAG, "Failed to write energy meter data to incident report.", e); } } }); } catch (IOException e) { - Slog.e(TAG, "Failed to write energy meter info to incident report."); + Slog.e(TAG, "Failed to write energy meter info to incident report.", e); } pos.flush(); @@ -200,12 +200,12 @@ public final class PowerStatsLogger extends Handler { EnergyConsumerResultUtils.packProtoMessage(energyConsumerResult, pos, true); if (DEBUG) EnergyConsumerResultUtils.print(energyConsumerResult); } catch (IOException e) { - Slog.e(TAG, "Failed to write energy model data to incident report."); + Slog.e(TAG, "Failed to write energy model data to incident report.", e); } } }); } catch (IOException e) { - Slog.e(TAG, "Failed to write energy model info to incident report."); + Slog.e(TAG, "Failed to write energy model info to incident report.", e); } pos.flush(); @@ -241,12 +241,12 @@ public final class PowerStatsLogger extends Handler { StateResidencyResultUtils.packProtoMessage(stateResidencyResult, pos); if (DEBUG) StateResidencyResultUtils.print(stateResidencyResult); } catch (IOException e) { - Slog.e(TAG, "Failed to write residency data to incident report."); + Slog.e(TAG, "Failed to write residency data to incident report.", e); } } }); } catch (IOException e) { - Slog.e(TAG, "Failed to write residency data to incident report."); + Slog.e(TAG, "Failed to write residency data to incident report.", e); } pos.flush(); @@ -267,7 +267,7 @@ public final class PowerStatsLogger extends Handler { final FileInputStream fis = new FileInputStream(cachedFile.getPath()); fis.read(dataCached); } catch (IOException e) { - Slog.e(TAG, "Failed to read cached data from file"); + Slog.e(TAG, "Failed to read cached data from file", e); } // If the cached and current data are different, delete the data store. @@ -291,7 +291,7 @@ public final class PowerStatsLogger extends Handler { fos.write(data); atomicCachedFile.finishWrite(fos); } catch (IOException e) { - Slog.e(TAG, "Failed to write current data to cached file"); + Slog.e(TAG, "Failed to write current data to cached file", e); } } diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java index 80ce70de2138..3707c8e42e04 100644 --- a/services/core/java/com/android/server/trust/TrustManagerService.java +++ b/services/core/java/com/android/server/trust/TrustManagerService.java @@ -1211,7 +1211,7 @@ public class TrustManagerService extends SystemService { if (info.userId == userId && info.agent.isTrusted() && info.agent.shouldDisplayTrustGrantedMessage() - && !TextUtils.isEmpty(info.agent.getMessage())) { + && info.agent.getMessage() != null) { trustGrantedMessages.add(info.agent.getMessage().toString()); } } diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index af22f803d87d..4c0a0171024a 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -1522,8 +1522,17 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A this.task = newTask; if (shouldStartChangeTransition(newParent, oldParent)) { - // Animate change transition on TaskFragment level to get the correct window crop. - newParent.initializeChangeTransition(getBounds(), getSurfaceControl()); + if (mTransitionController.isShellTransitionsEnabled()) { + // For Shell transition, call #initializeChangeTransition directly to take the + // screenshot at the Activity level. And Shell will be in charge of handling the + // surface reparent and crop. + initializeChangeTransition(getBounds()); + } else { + // For legacy app transition, we want to take a screenshot of the Activity surface, + // but animate the change transition on TaskFragment level to get the correct window + // crop. + newParent.initializeChangeTransition(getBounds(), getSurfaceControl()); + } } super.onParentChanged(newParent, oldParent); @@ -2120,7 +2129,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A mActivityRecordInputSink = new ActivityRecordInputSink(this, sourceRecord); - updateEnterpriseThumbnailDrawable(mAtmService.mUiContext); + updateEnterpriseThumbnailDrawable(mAtmService.getUiContext()); } /** @@ -7433,7 +7442,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } final Rect frame = win.getRelativeFrame(); final Drawable thumbnailDrawable = task.mUserId == mWmService.mCurrentUserId - ? mAtmService.mUiContext.getDrawable(R.drawable.ic_account_circle) + ? mAtmService.getUiContext().getDrawable(R.drawable.ic_account_circle) : mEnterpriseThumbnailDrawable; final HardwareBuffer thumbnail = getDisplayContent().mAppTransition .createCrossProfileAppsThumbnail(thumbnailDrawable, frame); diff --git a/services/core/java/com/android/server/wm/ActivityStartController.java b/services/core/java/com/android/server/wm/ActivityStartController.java index 7c25b53dc420..0707b818f093 100644 --- a/services/core/java/com/android/server/wm/ActivityStartController.java +++ b/services/core/java/com/android/server/wm/ActivityStartController.java @@ -384,6 +384,14 @@ public class ActivityStartController { callingUid, realCallingUid, UserHandle.USER_NULL); final SparseArray<String> startingUidPkgs = new SparseArray<>(); final long origId = Binder.clearCallingIdentity(); + + SafeActivityOptions bottomOptions = null; + if (options != null) { + // To ensure the first N-1 activities (N == total # of activities) are also launched + // into the correct display, use a copy of the passed-in options (keeping only + // display-related info) for these activities. + bottomOptions = options.selectiveCloneDisplayOptions(); + } try { intents = ArrayUtils.filterNotNull(intents, Intent[]::new); final ActivityStarter[] starters = new ActivityStarter[intents.length]; @@ -432,7 +440,7 @@ public class ActivityStartController { final boolean top = i == intents.length - 1; final SafeActivityOptions checkedOptions = top ? options - : null; + : bottomOptions; starters[i] = obtainStarter(intent, reason) .setIntentGrants(intentGrants) .setCaller(caller) diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java index e99349621e74..75e24a89048b 100644 --- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java +++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java @@ -346,7 +346,7 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { * This Context is themable and meant for UI display (AlertDialogs, etc.). The theme can * change at runtime. Use mContext for non-UI purposes. */ - final Context mUiContext; + private final Context mUiContext; final ActivityThread mSystemThread; H mH; UiHandler mUiHandler; @@ -1041,6 +1041,10 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub { } } + Context getUiContext() { + return mUiContext; + } + UserManagerService getUserManager() { if (mUserManager == null) { IBinder b = ServiceManager.getService(Context.USER_SERVICE); diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java index 53f2c7146656..5c1a877cc865 100644 --- a/services/core/java/com/android/server/wm/AppTransition.java +++ b/services/core/java/com/android/server/wm/AppTransition.java @@ -39,6 +39,7 @@ import static android.view.WindowManager.TRANSIT_OLD_DREAM_ACTIVITY_OPEN; import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_GOING_AWAY; import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER; import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_OCCLUDE; +import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_OCCLUDE_BY_DREAM; import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_UNOCCLUDE; import static android.view.WindowManager.TRANSIT_OLD_NONE; import static android.view.WindowManager.TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE; @@ -758,7 +759,8 @@ public class AppTransition implements Dump { if (isKeyguardGoingAwayTransitOld(transit) && enter) { a = mTransitionAnimation.loadKeyguardExitAnimation(mNextAppTransitionFlags, transit == TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER); - } else if (transit == TRANSIT_OLD_KEYGUARD_OCCLUDE) { + } else if (transit == TRANSIT_OLD_KEYGUARD_OCCLUDE + || transit == TRANSIT_OLD_KEYGUARD_OCCLUDE_BY_DREAM) { a = null; } else if (transit == TRANSIT_OLD_KEYGUARD_UNOCCLUDE && !enter) { a = mTransitionAnimation.loadKeyguardUnoccludeAnimation(); @@ -1170,6 +1172,9 @@ public class AppTransition implements Dump { case TRANSIT_OLD_KEYGUARD_OCCLUDE: { return "TRANSIT_OLD_KEYGUARD_OCCLUDE"; } + case TRANSIT_OLD_KEYGUARD_OCCLUDE_BY_DREAM: { + return "TRANSIT_OLD_KEYGUARD_OCCLUDE_BY_DREAM"; + } case TRANSIT_OLD_KEYGUARD_UNOCCLUDE: { return "TRANSIT_OLD_KEYGUARD_UNOCCLUDE"; } @@ -1425,6 +1430,7 @@ public class AppTransition implements Dump { static boolean isKeyguardOccludeTransitOld(@TransitionOldType int transit) { return transit == TRANSIT_OLD_KEYGUARD_OCCLUDE + || transit == TRANSIT_OLD_KEYGUARD_OCCLUDE_BY_DREAM || transit == TRANSIT_OLD_KEYGUARD_UNOCCLUDE; } diff --git a/services/core/java/com/android/server/wm/AppTransitionController.java b/services/core/java/com/android/server/wm/AppTransitionController.java index 5ac5f2e4bdaf..5599f2cfc374 100644 --- a/services/core/java/com/android/server/wm/AppTransitionController.java +++ b/services/core/java/com/android/server/wm/AppTransitionController.java @@ -38,6 +38,7 @@ import static android.view.WindowManager.TRANSIT_OLD_DREAM_ACTIVITY_OPEN; import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_GOING_AWAY; import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER; import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_OCCLUDE; +import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_OCCLUDE_BY_DREAM; import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_UNOCCLUDE; import static android.view.WindowManager.TRANSIT_OLD_NONE; import static android.view.WindowManager.TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE; @@ -363,8 +364,14 @@ public class AppTransitionController { // When there is a closing app, the keyguard has already been occluded by an // activity, and another activity has started on top of that activity, so normal // app transition animation should be used. - return closingApps.isEmpty() ? TRANSIT_OLD_KEYGUARD_OCCLUDE - : TRANSIT_OLD_ACTIVITY_OPEN; + if (!closingApps.isEmpty()) { + return TRANSIT_OLD_ACTIVITY_OPEN; + } + if (!openingApps.isEmpty() && openingApps.valueAt(0).getActivityType() + == ACTIVITY_TYPE_DREAM) { + return TRANSIT_OLD_KEYGUARD_OCCLUDE_BY_DREAM; + } + return TRANSIT_OLD_KEYGUARD_OCCLUDE; case TRANSIT_KEYGUARD_UNOCCLUDE: return TRANSIT_OLD_KEYGUARD_UNOCCLUDE; } diff --git a/services/core/java/com/android/server/wm/AsyncRotationController.java b/services/core/java/com/android/server/wm/AsyncRotationController.java index 219092baface..1266db5bff98 100644 --- a/services/core/java/com/android/server/wm/AsyncRotationController.java +++ b/services/core/java/com/android/server/wm/AsyncRotationController.java @@ -357,7 +357,12 @@ class AsyncRotationController extends FadeAnimationController implements Consume * or seamless transformation in a rotated display. */ boolean shouldFreezeInsetsPosition(WindowState w) { - return mTransitionOp != OP_LEGACY && w.mTransitionController.inTransition() + if (TransitionController.SYNC_METHOD != BLASTSyncEngine.METHOD_BLAST) { + // Expect a screenshot layer has covered the screen, so it is fine to let client side + // insets animation runner update the position directly. + return false; + } + return mTransitionOp != OP_LEGACY && !mIsStartTransactionCommitted && isTargetToken(w.mToken); } diff --git a/services/core/java/com/android/server/wm/BackNavigationController.java b/services/core/java/com/android/server/wm/BackNavigationController.java index 35a39c048e57..028d4b3e0871 100644 --- a/services/core/java/com/android/server/wm/BackNavigationController.java +++ b/services/core/java/com/android/server/wm/BackNavigationController.java @@ -310,7 +310,7 @@ class BackNavigationController { mBackNaviAnimationController = new BackNaviAnimationController( backAnimationAdaptor.getRunner(), this, currentActivity.getDisplayId()); - prepareBackToHomeTransition(currentTask, prevTask); + prepareBackToHomeTransition(currentActivity, prevTask); infoBuilder.setPrepareAnimation(true); } } else { @@ -489,8 +489,8 @@ class BackNavigationController { mWindowManagerService = wm; } - private void prepareBackToHomeTransition(Task currentTask, Task homeTask) { - final DisplayContent dc = currentTask.getDisplayContent(); + private void prepareBackToHomeTransition(ActivityRecord currentActivity, Task homeTask) { + final DisplayContent dc = currentActivity.getDisplayContent(); final ActivityRecord homeActivity = homeTask.getTopNonFinishingActivity(); if (!homeActivity.mVisibleRequested) { homeActivity.setVisibility(true); @@ -499,7 +499,7 @@ class BackNavigationController { dc.ensureActivitiesVisible( null /* starting */, 0 /* configChanges */, false /* preserveWindows */, true); - mBackNaviAnimationController.initialize(homeActivity, currentTask.getTopMostActivity()); + mBackNaviAnimationController.initialize(homeActivity, currentActivity); } void finishAnimation() { diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 720b08285f17..95d71a36313f 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -245,6 +245,7 @@ import com.android.internal.util.function.pooled.PooledLambda; import com.android.internal.util.function.pooled.PooledPredicate; import com.android.server.inputmethod.InputMethodManagerInternal; import com.android.server.policy.WindowManagerPolicy; +import com.android.server.wm.utils.RegionUtils; import com.android.server.wm.utils.RotationCache; import com.android.server.wm.utils.WmDisplayCutout; @@ -1148,6 +1149,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp mMinSizeOfResizeableTaskDp = getMinimalTaskSizeDp(); if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Creating display=" + display); + setWindowingMode(WINDOWING_MODE_FULLSCREEN); mWmService.mDisplayWindowSettings.applySettingsToDisplayLocked(this); } @@ -1614,24 +1616,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp } config = new Configuration(); computeScreenConfiguration(config); - } else if (!(mTransitionController.isCollecting(this) - // If waiting for a remote display change, don't prematurely update configuration. - || mRemoteDisplayChangeController.isWaitingForRemoteDisplayChange())) { - // No obvious action we need to take, but if our current state mismatches the - // activity manager's, update it, disregarding font scale, which should remain set - // to the value of the previous configuration. - // Here we're calling Configuration#unset() instead of setToDefaults() because we - // need to keep override configs clear of non-empty values (e.g. fontSize). - final Configuration currentConfig = getRequestedOverrideConfiguration(); - mTmpConfiguration.unset(); - mTmpConfiguration.updateFrom(currentConfig); - computeScreenConfiguration(mTmpConfiguration); - if (currentConfig.diff(mTmpConfiguration) != 0) { - mWaitingForConfig = true; - setLayoutNeeded(); - mDisplayRotation.prepareNormalRotationAnimation(); - config = new Configuration(mTmpConfiguration); - } } return config; @@ -2670,16 +2654,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp } @Override - public void setWindowingMode(int windowingMode) { - // Intentionally call onRequestedOverrideConfigurationChanged() directly to change windowing - // mode and display windowing mode atomically. - mTmpConfiguration.setTo(getRequestedOverrideConfiguration()); - mTmpConfiguration.windowConfiguration.setWindowingMode(windowingMode); - mTmpConfiguration.windowConfiguration.setDisplayWindowingMode(windowingMode); - onRequestedOverrideConfigurationChanged(mTmpConfiguration); - } - - @Override void setDisplayWindowingMode(int windowingMode) { setWindowingMode(windowingMode); } @@ -5807,6 +5781,12 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp if (w.isVisible() && !w.inPinnedWindowingMode()) { w.getKeepClearAreas(outRestricted, outUnrestricted, tmpMatrix, tmpFloat9); + + if (w.mIsImWindow) { + Region touchableRegion = Region.obtain(); + w.getEffectiveTouchableRegion(touchableRegion); + RegionUtils.forEachRect(touchableRegion, rect -> outUnrestricted.add(rect)); + } } // We stop traversing when we reach the base of a fullscreen app. diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java index fe7cb1935f7a..b26de07461d6 100644 --- a/services/core/java/com/android/server/wm/DisplayPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayPolicy.java @@ -421,7 +421,7 @@ public class DisplayPolicy { mService = service; mContext = displayContent.isDefaultDisplay ? service.mContext : service.mContext.createDisplayContext(displayContent.getDisplay()); - mUiContext = displayContent.isDefaultDisplay ? service.mAtmService.mUiContext + mUiContext = displayContent.isDefaultDisplay ? service.mAtmService.getUiContext() : service.mAtmService.mSystemThread .getSystemUiContext(displayContent.getDisplayId()); mDisplayContent = displayContent; @@ -2184,9 +2184,7 @@ public class DisplayPolicy { } mDecorInsets.invalidate(); mDecorInsets.mInfoForRotation[rotation].set(newInfo); - // If the device is booting, let the boot procedure trigger the new configuration. - // Otherwise the display configuration needs to be recomputed now. - return mService.mDisplayEnabled; + return true; } DecorInsets.Info getDecorInsetsInfo(int rotation, int w, int h) { diff --git a/services/core/java/com/android/server/wm/DisplayWindowSettings.java b/services/core/java/com/android/server/wm/DisplayWindowSettings.java index 11bcd8ca3681..c1b6496338a4 100644 --- a/services/core/java/com/android/server/wm/DisplayWindowSettings.java +++ b/services/core/java/com/android/server/wm/DisplayWindowSettings.java @@ -150,7 +150,10 @@ class DisplayWindowSettings { final SettingsProvider.SettingsEntry overrideSettings = mSettingsProvider.getOverrideSettings(displayInfo); overrideSettings.mWindowingMode = mode; - dc.setWindowingMode(mode); + final TaskDisplayArea defaultTda = dc.getDefaultTaskDisplayArea(); + if (defaultTda != null) { + defaultTda.setWindowingMode(mode); + } mSettingsProvider.updateOverrideSettings(displayInfo, overrideSettings); } @@ -253,8 +256,10 @@ class DisplayWindowSettings { // Setting windowing mode first, because it may override overscan values later. final int windowingMode = getWindowingModeLocked(settings, dc); - dc.setWindowingMode(windowingMode); - + final TaskDisplayArea defaultTda = dc.getDefaultTaskDisplayArea(); + if (defaultTda != null) { + defaultTda.setWindowingMode(windowingMode); + } final int userRotationMode = settings.mUserRotationMode != null ? settings.mUserRotationMode : WindowManagerPolicy.USER_ROTATION_FREE; final int userRotation = settings.mUserRotation != null @@ -311,10 +316,11 @@ class DisplayWindowSettings { * changed. */ boolean updateSettingsForDisplay(DisplayContent dc) { - if (dc.getWindowingMode() != getWindowingModeLocked(dc)) { + final TaskDisplayArea defaultTda = dc.getDefaultTaskDisplayArea(); + if (defaultTda != null && defaultTda.getWindowingMode() != getWindowingModeLocked(dc)) { // For the time being the only thing that may change is windowing mode, so just update // that. - dc.setWindowingMode(getWindowingModeLocked(dc)); + defaultTda.setWindowingMode(getWindowingModeLocked(dc)); return true; } return false; diff --git a/services/core/java/com/android/server/wm/ResetTargetTaskHelper.java b/services/core/java/com/android/server/wm/ResetTargetTaskHelper.java index 1fd66fc2c2bc..d497d8cbf9cd 100644 --- a/services/core/java/com/android/server/wm/ResetTargetTaskHelper.java +++ b/services/core/java/com/android/server/wm/ResetTargetTaskHelper.java @@ -141,15 +141,16 @@ class ResetTargetTaskHelper implements Consumer<Task>, Predicate<ActivityRecord> return false; } else { - mResultActivities.add(r); if (r.resultTo != null) { // If this activity is sending a reply to a previous activity, we can't do // anything with it now until we reach the start of the reply chain. // NOTE: that we are assuming the result is always to the previous activity, // which is almost always the case but we really shouldn't count on. + mResultActivities.add(r); return false; } else if (mTargetTaskFound && allowTaskReparenting && mTargetTask.affinity != null && mTargetTask.affinity.equals(r.taskAffinity)) { + mResultActivities.add(r); // This activity has an affinity for our task. Either remove it if we are // clearing or move it over to our task. Note that we currently punt on the case // where we are resetting a task that is not at the top but who has activities diff --git a/services/core/java/com/android/server/wm/SafeActivityOptions.java b/services/core/java/com/android/server/wm/SafeActivityOptions.java index 2879e33fb71a..8bacacd1451c 100644 --- a/services/core/java/com/android/server/wm/SafeActivityOptions.java +++ b/services/core/java/com/android/server/wm/SafeActivityOptions.java @@ -116,6 +116,34 @@ public class SafeActivityOptions { } /** + * To ensure that two activities, one using this object, and the other using the + * SafeActivityOptions returned from this function, are launched into the same display through + * ActivityStartController#startActivities, all display-related information, i.e. + * displayAreaToken, launchDisplayId and callerDisplayId, are cloned. + */ + @Nullable SafeActivityOptions selectiveCloneDisplayOptions() { + final ActivityOptions options = cloneLaunchingDisplayOptions(mOriginalOptions); + final ActivityOptions callerOptions = cloneLaunchingDisplayOptions(mCallerOptions); + if (options == null && callerOptions == null) { + return null; + } + + final SafeActivityOptions safeOptions = new SafeActivityOptions(options, + mOriginalCallingPid, mOriginalCallingUid); + safeOptions.mCallerOptions = callerOptions; + safeOptions.mRealCallingPid = mRealCallingPid; + safeOptions.mRealCallingUid = mRealCallingUid; + return safeOptions; + } + + private ActivityOptions cloneLaunchingDisplayOptions(ActivityOptions options) { + return options == null ? null : ActivityOptions.makeBasic() + .setLaunchTaskDisplayArea(options.getLaunchTaskDisplayArea()) + .setLaunchDisplayId(options.getLaunchDisplayId()) + .setCallerDisplayId((options.getCallerDisplayId())); + } + + /** * Overrides options with options from a caller and records {@link Binder#getCallingPid}/ * {@link Binder#getCallingUid}. Thus, calling identity MUST NOT be cleared when calling this * method. diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 436cc4d4cbe9..91db27861a38 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -4465,6 +4465,14 @@ class Task extends TaskFragment { // transferring the transform on the leash to the task, reset this state once we're // moving out of pip setCanAffectSystemUiFlags(true); + // Turn on userLeaveHint so other app can enter PiP mode. + mTaskSupervisor.mUserLeaving = true; + // Allow entering PiP from current top most activity when we are leaving PiP. + final Task topFocused = mRootWindowContainer.getTopDisplayFocusedRootTask(); + if (topFocused != null) { + final ActivityRecord ar = topFocused.getTopResumedActivity(); + enableEnterPipOnTaskSwitch(ar, null /* toFrontTask */, ar, null /* opts */); + } mRootWindowContainer.notifyActivityPipModeChanged(this, null); } if (likelyResolvedMode == WINDOWING_MODE_PINNED) { diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java index 0f46c4f166ae..ff09163c151d 100644 --- a/services/core/java/com/android/server/wm/TaskDisplayArea.java +++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java @@ -172,6 +172,8 @@ final class TaskDisplayArea extends DisplayArea<WindowContainer> { */ private final boolean mCanHostHomeTask; + private final Configuration mTempConfiguration = new Configuration(); + TaskDisplayArea(DisplayContent displayContent, WindowManagerService service, String name, int displayAreaFeature) { this(displayContent, service, name, displayAreaFeature, false /* createdByOrganizer */, @@ -1891,6 +1893,15 @@ final class TaskDisplayArea extends DisplayArea<WindowContainer> { } @Override + public void setWindowingMode(int windowingMode) { + mTempConfiguration.setTo(getRequestedOverrideConfiguration()); + WindowConfiguration tempRequestWindowConfiguration = mTempConfiguration.windowConfiguration; + tempRequestWindowConfiguration.setWindowingMode(windowingMode); + tempRequestWindowConfiguration.setDisplayWindowingMode(windowingMode); + onRequestedOverrideConfigurationChanged(mTempConfiguration); + } + + @Override TaskDisplayArea getTaskDisplayArea() { return this; } diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java index 036a292c3174..d13cfdb5927b 100644 --- a/services/core/java/com/android/server/wm/TaskFragment.java +++ b/services/core/java/com/android/server/wm/TaskFragment.java @@ -1595,12 +1595,14 @@ class TaskFragment extends WindowContainer<WindowContainer> { boolean pauseImmediately = false; boolean shouldAutoPip = false; if (resuming != null) { + // We do not want to trigger auto-PiP upon launch of a translucent activity. + final boolean resumingOccludesParent = resuming.occludesParent(); // Resuming the new resume activity only if the previous activity can't go into Pip // since we want to give Pip activities a chance to enter Pip before resuming the // next activity. final boolean lastResumedCanPip = prev.checkEnterPictureInPictureState( "shouldAutoPipWhilePausing", userLeaving); - if (userLeaving && lastResumedCanPip + if (userLeaving && resumingOccludesParent && lastResumedCanPip && prev.pictureInPictureArgs.isAutoEnterEnabled()) { shouldAutoPip = true; } else if (!lastResumedCanPip) { diff --git a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java index 8f07bb7aad02..8e98cb793179 100644 --- a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java +++ b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java @@ -137,7 +137,7 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier { final DisplayContent display = suggestedDisplayArea.mDisplayContent; if (DEBUG) { appendLog("display-id=" + display.getDisplayId() - + " display-windowing-mode=" + display.getWindowingMode() + + " task-display-area-windowing-mode=" + suggestedDisplayArea.getWindowingMode() + " suggested-display-area=" + suggestedDisplayArea); } @@ -156,7 +156,7 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier { // source is a freeform window in a fullscreen display launching an activity on the same // display. if (launchMode == WINDOWING_MODE_UNDEFINED - && canInheritWindowingModeFromSource(display, source)) { + && canInheritWindowingModeFromSource(display, suggestedDisplayArea, source)) { // The source's windowing mode may be different from its task, e.g. activity is set // to fullscreen and its task is pinned windowing mode when the activity is entering // pip. @@ -184,7 +184,8 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier { // is set with the suggestedDisplayArea. If it is set, but the eventual TaskDisplayArea is // different, we should recalculating the bounds. boolean hasInitialBoundsForSuggestedDisplayAreaInFreeformWindow = false; - final boolean canApplyFreeformPolicy = canApplyFreeformWindowPolicy(display, launchMode); + final boolean canApplyFreeformPolicy = + canApplyFreeformWindowPolicy(suggestedDisplayArea, launchMode); if (mSupervisor.canUseActivityOptionsLaunchBounds(options) && (canApplyFreeformPolicy || canApplyPipWindowPolicy(launchMode))) { hasInitialBounds = true; @@ -239,7 +240,8 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier { == display.getDisplayId())) { // Only set windowing mode if display is in freeform. If the display is in fullscreen // mode we should only launch a task in fullscreen mode. - if (currentParams.hasWindowingMode() && display.inFreeformWindowingMode()) { + if (currentParams.hasWindowingMode() + && suggestedDisplayArea.inFreeformWindowingMode()) { launchMode = currentParams.mWindowingMode; fullyResolvedCurrentParam = launchMode != WINDOWING_MODE_FREEFORM; if (DEBUG) { @@ -267,11 +269,11 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier { // this step is to define the default policy when there is no initial bounds or a fully // resolved current params from callers. - // hasInitialBoundsForSuggestedDisplayAreaInFreeformDisplay is set if the outParams.mBounds + // hasInitialBoundsForSuggestedDisplayAreaInFreeformMode is set if the outParams.mBounds // is set with the suggestedDisplayArea. If it is set, but the eventual TaskDisplayArea is // different, we should recalcuating the bounds. - boolean hasInitialBoundsForSuggestedDisplayAreaInFreeformDisplay = false; - if (display.inFreeformWindowingMode()) { + boolean hasInitialBoundsForSuggestedDisplayAreaInFreeformMode = false; + if (suggestedDisplayArea.inFreeformWindowingMode()) { if (launchMode == WINDOWING_MODE_PINNED) { if (DEBUG) appendLog("picture-in-picture"); } else if (!root.isResizeable()) { @@ -280,7 +282,7 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier { if (outParams.mBounds.isEmpty()) { getTaskBounds(root, suggestedDisplayArea, layout, launchMode, hasInitialBounds, outParams.mBounds); - hasInitialBoundsForSuggestedDisplayAreaInFreeformDisplay = true; + hasInitialBoundsForSuggestedDisplayAreaInFreeformMode = true; } if (DEBUG) appendLog("unresizable-freeform"); } else { @@ -290,10 +292,10 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier { } } } else { - if (DEBUG) appendLog("non-freeform-display"); + if (DEBUG) appendLog("non-freeform-task-display-area"); } // If launch mode matches display windowing mode, let it inherit from display. - outParams.mWindowingMode = launchMode == display.getWindowingMode() + outParams.mWindowingMode = launchMode == suggestedDisplayArea.getWindowingMode() ? WINDOWING_MODE_UNDEFINED : launchMode; if (phase == PHASE_WINDOWING_MODE) { @@ -303,7 +305,7 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier { // STEP 3: Finalize the display area. Here we allow WM shell route all launches that match // certain criteria to specific task display areas. final int resolvedMode = (launchMode != WINDOWING_MODE_UNDEFINED) ? launchMode - : display.getWindowingMode(); + : suggestedDisplayArea.getWindowingMode(); TaskDisplayArea taskDisplayArea = suggestedDisplayArea; // If launch task display area is set in options we should just use it. We assume the // suggestedDisplayArea has the right one in this case. @@ -320,14 +322,17 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier { mTmpDisplayArea = displayArea; return true; }); - // We may need to recalculate the bounds if the new TaskDisplayArea is different from - // the suggested one we used to calculate the bounds. + // We may need to recalculate the bounds and the windowing mode if the new + // TaskDisplayArea is different from the suggested one we used to calculate the two + // configurations. if (mTmpDisplayArea != null && mTmpDisplayArea != suggestedDisplayArea) { + outParams.mWindowingMode = (launchMode == mTmpDisplayArea.getWindowingMode()) + ? WINDOWING_MODE_UNDEFINED : launchMode; if (hasInitialBoundsForSuggestedDisplayAreaInFreeformWindow) { outParams.mBounds.setEmpty(); getLayoutBounds(mTmpDisplayArea, root, layout, outParams.mBounds); hasInitialBounds = !outParams.mBounds.isEmpty(); - } else if (hasInitialBoundsForSuggestedDisplayAreaInFreeformDisplay) { + } else if (hasInitialBoundsForSuggestedDisplayAreaInFreeformMode) { outParams.mBounds.setEmpty(); getTaskBounds(root, mTmpDisplayArea, layout, launchMode, hasInitialBounds, outParams.mBounds); @@ -519,7 +524,7 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier { } private boolean canInheritWindowingModeFromSource(@NonNull DisplayContent display, - @Nullable ActivityRecord source) { + TaskDisplayArea suggestedDisplayArea, @Nullable ActivityRecord source) { if (source == null) { return false; } @@ -527,7 +532,7 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier { // There is not really any strong reason to tie the launching windowing mode and the source // on freeform displays. The launching windowing mode is more tied to the content of the new // activities. - if (display.inFreeformWindowingMode()) { + if (suggestedDisplayArea.inFreeformWindowingMode()) { return false; } @@ -543,9 +548,11 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier { return display.getDisplayId() == source.getDisplayId(); } - private boolean canApplyFreeformWindowPolicy(@NonNull DisplayContent display, int launchMode) { + private boolean canApplyFreeformWindowPolicy(@NonNull TaskDisplayArea suggestedDisplayArea, + int launchMode) { return mSupervisor.mService.mSupportsFreeformWindowManagement - && (display.inFreeformWindowingMode() || launchMode == WINDOWING_MODE_FREEFORM); + && (suggestedDisplayArea.inFreeformWindowingMode() + || launchMode == WINDOWING_MODE_FREEFORM); } private boolean canApplyPipWindowPolicy(int launchMode) { diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java index 135fcd4c68a5..488fe676d265 100644 --- a/services/core/java/com/android/server/wm/Transition.java +++ b/services/core/java/com/android/server/wm/Transition.java @@ -46,8 +46,9 @@ import static android.view.WindowManager.TransitionFlags; import static android.view.WindowManager.TransitionType; import static android.view.WindowManager.transitTypeToString; import static android.window.TransitionInfo.FLAG_DISPLAY_HAS_ALERT_WINDOWS; +import static android.window.TransitionInfo.FLAG_FILLS_TASK; +import static android.window.TransitionInfo.FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY; import static android.window.TransitionInfo.FLAG_IS_DISPLAY; -import static android.window.TransitionInfo.FLAG_IS_EMBEDDED; import static android.window.TransitionInfo.FLAG_IS_INPUT_METHOD; import static android.window.TransitionInfo.FLAG_IS_VOICE_INTERACTION; import static android.window.TransitionInfo.FLAG_IS_WALLPAPER; @@ -577,17 +578,16 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe t.setLayer(targetLeash, target.getLastLayer()); target.getRelativePosition(tmpPos); t.setPosition(targetLeash, tmpPos.x, tmpPos.y); - final Rect clipRect; // No need to clip the display in case seeing the clipped content when during the // display rotation. No need to clip activities because they rely on clipping on // task layers. if (target.asDisplayContent() != null || target.asActivityRecord() != null) { - clipRect = null; + t.setCrop(targetLeash, null /* crop */); } else { - clipRect = target.getRequestedOverrideBounds(); - clipRect.offset(-tmpPos.x, -tmpPos.y); + // Crop to the requested bounds. + final Rect clipRect = target.getRequestedOverrideBounds(); + t.setWindowCrop(targetLeash, clipRect.width(), clipRect.height()); } - t.setCrop(targetLeash, clipRect); t.setCornerRadius(targetLeash, 0); t.setShadowRadius(targetLeash, 0); t.setMatrix(targetLeash, 1, 0, 0, 1); @@ -1874,8 +1874,10 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe flags |= FLAG_WILL_IME_SHOWN; } } + Task parentTask = null; final ActivityRecord record = wc.asActivityRecord(); if (record != null) { + parentTask = record.getTask(); if (record.mUseTransferredAnimation) { flags |= FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT; } @@ -1883,6 +1885,26 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe flags |= FLAG_IS_VOICE_INTERACTION; } } + final TaskFragment taskFragment = wc.asTaskFragment(); + if (taskFragment != null && task == null) { + parentTask = taskFragment.getTask(); + } + if (parentTask != null) { + if (parentTask.forAllLeafTaskFragments(TaskFragment::isEmbedded)) { + // Whether this is in a Task with embedded activity. + flags |= FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY; + } + final Rect taskBounds = parentTask.getBounds(); + final Rect startBounds = mAbsoluteBounds; + final Rect endBounds = wc.getBounds(); + if (taskBounds.width() == startBounds.width() + && taskBounds.height() == startBounds.height() + && taskBounds.width() == endBounds.width() + && taskBounds.height() == endBounds.height()) { + // Whether the container fills the Task bounds before and after the transition. + flags |= FLAG_FILLS_TASK; + } + } final DisplayContent dc = wc.asDisplayContent(); if (dc != null) { flags |= FLAG_IS_DISPLAY; @@ -1899,9 +1921,6 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe if (occludesKeyguard(wc)) { flags |= FLAG_OCCLUDES_KEYGUARD; } - if (wc.isEmbedded()) { - flags |= FLAG_IS_EMBEDDED; - } return flags; } } @@ -2156,8 +2175,12 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe Slog.w(TAG, "Failed to capture screenshot for " + wc); return false; } + final boolean isDisplayRotation = wc.asDisplayContent() != null + && wc.asDisplayContent().isRotationChanging(); + // Some tests may check the name "RotationLayer" to detect display rotation. + final String name = isDisplayRotation ? "RotationLayer" : "transition snapshot: " + wc; SurfaceControl snapshotSurface = wc.makeAnimationLeash() - .setName("transition snapshot: " + wc.toString()) + .setName(name) .setOpaque(true) .setParent(wc.getSurfaceControl()) .setSecure(screenshotBuffer.containsSecureLayers()) @@ -2167,9 +2190,8 @@ class Transition extends Binder implements BLASTSyncEngine.TransactionReadyListe mFrozen.add(wc); final ChangeInfo changeInfo = Objects.requireNonNull(mChanges.get(wc)); changeInfo.mSnapshot = snapshotSurface; - if (wc.asDisplayContent() != null) { - // This isn't cheap, so only do it for rotations: assume display-level is rotate - // since most of the time it is. + if (isDisplayRotation) { + // This isn't cheap, so only do it for display rotations. changeInfo.mSnapshotLuma = RotationAnimationUtils.getMedianBorderLuma( screenshotBuffer.getHardwareBuffer(), screenshotBuffer.getColorSpace()); } diff --git a/services/core/java/com/android/server/wm/TransitionController.java b/services/core/java/com/android/server/wm/TransitionController.java index 0d6532fe0848..e8682f7a3b22 100644 --- a/services/core/java/com/android/server/wm/TransitionController.java +++ b/services/core/java/com/android/server/wm/TransitionController.java @@ -67,7 +67,7 @@ class TransitionController { /** Which sync method to use for transition syncs. */ static final int SYNC_METHOD = - android.os.SystemProperties.getBoolean("persist.wm.debug.shell_transit_blast", true) + android.os.SystemProperties.getBoolean("persist.wm.debug.shell_transit_blast", false) ? BLASTSyncEngine.METHOD_BLAST : BLASTSyncEngine.METHOD_NONE; /** The same as legacy APP_TRANSITION_TIMEOUT_MS. */ diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index cc17b5b50039..66c962d855b7 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -650,7 +650,7 @@ public class WindowManagerService extends IWindowManager.Stub // Whether the system should use BLAST for ViewRootImpl final boolean mUseBLAST; // Whether to enable BLASTSyncEngine Transaction passing. - final boolean mUseBLASTSync = true; + static final boolean USE_BLAST_SYNC = true; final BLASTSyncEngine mSyncEngine; @@ -2576,7 +2576,7 @@ public class WindowManagerService extends IWindowManager.Stub if (outSyncIdBundle != null) { final int maybeSyncSeqId; - if (mUseBLASTSync && win.useBLASTSync() && viewVisibility != View.GONE + if (USE_BLAST_SYNC && win.useBLASTSync() && viewVisibility == View.VISIBLE && win.mSyncSeqId > lastSyncSeqId) { maybeSyncSeqId = win.shouldSyncWithBuffers() ? win.mSyncSeqId : -1; win.markRedrawForSyncReported(); @@ -5659,7 +5659,7 @@ public class WindowManagerService extends IWindowManager.Stub } public boolean useBLASTSync() { - return mUseBLASTSync; + return USE_BLAST_SYNC; } @Override diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 65db35971026..fd18d3de180e 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -5959,10 +5959,10 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP @Override boolean isSyncFinished() { - if (mSyncState == SYNC_STATE_WAITING_FOR_DRAW && mViewVisibility == View.GONE + if (mSyncState == SYNC_STATE_WAITING_FOR_DRAW && mViewVisibility != View.VISIBLE && !isVisibleRequested()) { - // Don't wait for GONE windows. However, we don't alter the state in case the window - // becomes un-gone while the syncset is still active. + // Don't wait for invisible windows. However, we don't alter the state in case the + // window becomes visible while the sync group is still active. return true; } return super.isSyncFinished(); diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java index 72e7e65ae43a..805559035ef9 100644 --- a/services/core/java/com/android/server/wm/WindowToken.java +++ b/services/core/java/com/android/server/wm/WindowToken.java @@ -16,7 +16,6 @@ package com.android.server.wm; -import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; @@ -631,12 +630,6 @@ class WindowToken extends WindowContainer<WindowState> { getResolvedOverrideConfiguration().updateFrom( mFixedRotationTransformState.mRotatedOverrideConfiguration); } - if (getTaskDisplayArea() == null) { - // We only defined behaviors of system windows in fullscreen mode, i.e. windows not - // contained in a task display area. - getResolvedOverrideConfiguration().windowConfiguration.setWindowingMode( - WINDOWING_MODE_FULLSCREEN); - } } @Override diff --git a/services/core/jni/com_android_server_companion_virtual_InputController.cpp b/services/core/jni/com_android_server_companion_virtual_InputController.cpp index 8197b67355d4..daca1531d41f 100644 --- a/services/core/jni/com_android_server_companion_virtual_InputController.cpp +++ b/services/core/jni/com_android_server_companion_virtual_InputController.cpp @@ -21,6 +21,7 @@ #include <android/keycodes.h> #include <errno.h> #include <fcntl.h> +#include <input/Input.h> #include <linux/uinput.h> #include <math.h> #include <nativehelper/JNIHelp.h> @@ -271,6 +272,14 @@ static int openUinput(const char* readableName, jint vendorId, jint productId, c ALOGE("Error creating touchscreen uinput pressure axis: %s", strerror(errno)); return -errno; } + uinput_abs_setup slotAbsSetup; + slotAbsSetup.code = ABS_MT_SLOT; + slotAbsSetup.absinfo.maximum = MAX_POINTERS; + slotAbsSetup.absinfo.minimum = 0; + if (ioctl(fd, UI_ABS_SETUP, &slotAbsSetup) != 0) { + ALOGE("Error creating touchscreen uinput slots: %s", strerror(errno)); + return -errno; + } } if (ioctl(fd, UI_DEV_SETUP, &setup) != 0) { ALOGE("Error creating uinput device: %s", strerror(errno)); diff --git a/services/core/xsd/display-device-config/display-device-config.xsd b/services/core/xsd/display-device-config/display-device-config.xsd index 6b05d8f74a5e..267cff6652bb 100644 --- a/services/core/xsd/display-device-config/display-device-config.xsd +++ b/services/core/xsd/display-device-config/display-device-config.xsd @@ -97,6 +97,16 @@ <xs:annotation name="nonnull"/> <xs:annotation name="final"/> </xs:element> + <!-- Set of thresholds that dictate the change needed for screen brightness + adaptations while in idle mode --> + <xs:element type="thresholds" name="displayBrightnessChangeThresholdsIdle" minOccurs="0" maxOccurs="1"> + <xs:annotation name="final"/> + </xs:element> + <!-- Set of thresholds that dictate the change needed for ambient brightness + adaptations while in idle mode --> + <xs:element type="thresholds" name="ambientBrightnessChangeThresholdsIdle" minOccurs="0" maxOccurs="1"> + <xs:annotation name="final"/> + </xs:element> </xs:sequence> </xs:complexType> </xs:element> @@ -319,13 +329,13 @@ <!-- Thresholds for brightness changes. --> <xs:complexType name="thresholds"> <xs:sequence> - <!-- Brightening thresholds. --> + <!-- Brightening thresholds for active screen brightness mode. --> <xs:element name="brighteningThresholds" type="brightnessThresholds" minOccurs="0" maxOccurs="1" > <xs:annotation name="nonnull"/> <xs:annotation name="final"/> </xs:element> - <!-- Darkening thresholds. --> + <!-- Darkening thresholds for active screen brightness mode. --> <xs:element name="darkeningThresholds" type="brightnessThresholds" minOccurs="0" maxOccurs="1" > <xs:annotation name="nonnull"/> diff --git a/services/core/xsd/display-device-config/schema/current.txt b/services/core/xsd/display-device-config/schema/current.txt index fb7a920f7d82..f8bff757f1ac 100644 --- a/services/core/xsd/display-device-config/schema/current.txt +++ b/services/core/xsd/display-device-config/schema/current.txt @@ -61,11 +61,13 @@ package com.android.server.display.config { public class DisplayConfiguration { ctor public DisplayConfiguration(); method @NonNull public final com.android.server.display.config.Thresholds getAmbientBrightnessChangeThresholds(); + method public final com.android.server.display.config.Thresholds getAmbientBrightnessChangeThresholdsIdle(); method public final java.math.BigInteger getAmbientLightHorizonLong(); method public final java.math.BigInteger getAmbientLightHorizonShort(); method public com.android.server.display.config.AutoBrightness getAutoBrightness(); method @Nullable public final com.android.server.display.config.DensityMapping getDensityMapping(); method @NonNull public final com.android.server.display.config.Thresholds getDisplayBrightnessChangeThresholds(); + method public final com.android.server.display.config.Thresholds getDisplayBrightnessChangeThresholdsIdle(); method public com.android.server.display.config.HighBrightnessMode getHighBrightnessMode(); method public final com.android.server.display.config.SensorDetails getLightSensor(); method public final com.android.server.display.config.SensorDetails getProxSensor(); @@ -80,11 +82,13 @@ package com.android.server.display.config { method public final java.math.BigDecimal getScreenBrightnessRampSlowIncrease(); method @NonNull public final com.android.server.display.config.ThermalThrottling getThermalThrottling(); method public final void setAmbientBrightnessChangeThresholds(@NonNull com.android.server.display.config.Thresholds); + method public final void setAmbientBrightnessChangeThresholdsIdle(com.android.server.display.config.Thresholds); method public final void setAmbientLightHorizonLong(java.math.BigInteger); method public final void setAmbientLightHorizonShort(java.math.BigInteger); method public void setAutoBrightness(com.android.server.display.config.AutoBrightness); method public final void setDensityMapping(@Nullable com.android.server.display.config.DensityMapping); method public final void setDisplayBrightnessChangeThresholds(@NonNull com.android.server.display.config.Thresholds); + method public final void setDisplayBrightnessChangeThresholdsIdle(com.android.server.display.config.Thresholds); method public void setHighBrightnessMode(com.android.server.display.config.HighBrightnessMode); method public final void setLightSensor(com.android.server.display.config.SensorDetails); method public final void setProxSensor(com.android.server.display.config.SensorDetails); diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java index 06fb4b0a01d8..6aca14f08188 100644 --- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java +++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java @@ -8178,7 +8178,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { } final CallerIdentity caller = getCallerIdentity(who); - Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(caller, userHandle)); + Preconditions.checkCallAuthorization(hasFullCrossUsersPermission(caller, userHandle) + || isCameraServerUid(caller)); if (parent) { Preconditions.checkCallAuthorization( @@ -9689,6 +9690,10 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager { return UserHandle.isSameApp(caller.getUid(), Process.SHELL_UID); } + private boolean isCameraServerUid(CallerIdentity caller) { + return UserHandle.isSameApp(caller.getUid(), Process.CAMERASERVER_UID); + } + private @UserIdInt int getCurrentForegroundUserId() { try { UserInfo currentUser = mInjector.getIActivityManager().getCurrentUser(); diff --git a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java index 3c6866205fda..f05b1d47ac0b 100644 --- a/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java +++ b/services/profcollect/src/com/android/server/profcollect/ProfcollectForwardingService.java @@ -218,6 +218,9 @@ public final class ProfcollectForwardingService extends SystemService { BackgroundThread.get().getThreadHandler().post( () -> { try { + if (sSelfService.mIProfcollect == null) { + return; + } sSelfService.mIProfcollect.process(); } catch (RemoteException e) { Log.e(LOG_TAG, "Failed to process profiles in background: " diff --git a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java index 9c615d140e85..ed369c016770 100644 --- a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java @@ -764,11 +764,13 @@ public class LocalDisplayAdapterTest { @Test public void testGetSystemPreferredDisplayMode() throws Exception { SurfaceControl.DisplayMode displayMode1 = createFakeDisplayMode(0, 1920, 1080, 60f); - // preferred mode + // system preferred mode SurfaceControl.DisplayMode displayMode2 = createFakeDisplayMode(1, 3840, 2160, 60f); + // user preferred mode + SurfaceControl.DisplayMode displayMode3 = createFakeDisplayMode(2, 1920, 1080, 30f); SurfaceControl.DisplayMode[] modes = - new SurfaceControl.DisplayMode[]{displayMode1, displayMode2}; + new SurfaceControl.DisplayMode[]{displayMode1, displayMode2, displayMode3}; FakeDisplay display = new FakeDisplay(PORT_A, modes, 0, 1); setUpDisplay(display); updateAvailableDisplays(); @@ -780,24 +782,43 @@ public class LocalDisplayAdapterTest { DisplayDeviceInfo displayDeviceInfo = mListener.addedDisplays.get( 0).getDisplayDeviceInfoLocked(); - assertThat(displayDeviceInfo.supportedModes.length).isEqualTo(modes.length); - Display.Mode defaultMode = getModeById(displayDeviceInfo, displayDeviceInfo.defaultModeId); + assertThat(matches(defaultMode, displayMode1)).isTrue(); + + // Set the user preferred display mode + mListener.addedDisplays.get(0).setUserPreferredDisplayModeLocked( + new Display.Mode( + displayMode3.width, displayMode3.height, displayMode3.refreshRate)); + updateAvailableDisplays(); + waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS); + displayDeviceInfo = mListener.addedDisplays.get( + 0).getDisplayDeviceInfoLocked(); + defaultMode = getModeById(displayDeviceInfo, displayDeviceInfo.defaultModeId); + assertThat(matches(defaultMode, displayMode3)).isTrue(); + + // clear the user preferred mode + mListener.addedDisplays.get(0).setUserPreferredDisplayModeLocked(null); + updateAvailableDisplays(); + waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS); + displayDeviceInfo = mListener.addedDisplays.get( + 0).getDisplayDeviceInfoLocked(); + defaultMode = getModeById(displayDeviceInfo, displayDeviceInfo.defaultModeId); assertThat(matches(defaultMode, displayMode2)).isTrue(); - // Change the display and add new preferred mode - SurfaceControl.DisplayMode addedDisplayInfo = createFakeDisplayMode(2, 2340, 1080, 60f); - modes = new SurfaceControl.DisplayMode[]{displayMode1, displayMode2, addedDisplayInfo}; + // Change the display and add new system preferred mode + SurfaceControl.DisplayMode addedDisplayInfo = createFakeDisplayMode(3, 2340, 1080, 20f); + modes = new SurfaceControl.DisplayMode[]{ + displayMode1, displayMode2, displayMode3, addedDisplayInfo}; display.dynamicInfo.supportedDisplayModes = modes; - display.dynamicInfo.preferredBootDisplayMode = 2; + display.dynamicInfo.preferredBootDisplayMode = 3; setUpDisplay(display); mInjector.getTransmitter().sendHotplug(display, /* connected */ true); waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS); assertTrue(mListener.traversalRequested); assertThat(mListener.addedDisplays.size()).isEqualTo(1); - assertThat(mListener.changedDisplays.size()).isEqualTo(1); + assertThat(mListener.changedDisplays.size()).isEqualTo(3); DisplayDevice displayDevice = mListener.changedDisplays.get(0); displayDevice.applyPendingDisplayDeviceInfoChangesLocked(); diff --git a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java index db1209224bd5..1508055263ef 100644 --- a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java +++ b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java @@ -179,6 +179,11 @@ public class UserControllerTest { doNothing().when(mInjector).taskSupervisorRemoveUser(anyInt()); // All UserController params are set to default. mUserController = new UserController(mInjector); + + // TODO(b/232452368): need to explicitly call setAllowUserUnlocking(), otherwise most + // tests would fail. But we might need to disable it for the onBootComplete() test (i.e, + // to make sure the users are unlocked at the right time) + mUserController.setAllowUserUnlocking(true); setUpUser(TEST_USER_ID, NO_USERINFO_FLAGS); setUpUser(TEST_PRE_CREATED_USER_ID, NO_USERINFO_FLAGS, /* preCreated=*/ true, null); }); @@ -600,6 +605,16 @@ public class UserControllerTest { } @Test + public void testUserNotUnlockedBeforeAllowed() throws Exception { + mUserController.setAllowUserUnlocking(false); + + mUserController.startUser(TEST_USER_ID, /* foreground= */ false); + + verify(mInjector.mStorageManagerMock, never()) + .unlockUserKey(eq(TEST_USER_ID), anyInt(), any()); + } + + @Test public void testStartProfile_fullUserFails() { setUpUser(TEST_USER_ID1, 0); assertThrows(IllegalArgumentException.class, diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java index 92e1f27ab624..837b55397416 100644 --- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java +++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java @@ -16,6 +16,8 @@ package com.android.server.biometrics.sensors.fingerprint.aidl; +import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_POWER_PRESSED; + import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.anyBoolean; @@ -253,6 +255,16 @@ public class FingerprintEnrollClientTest { showHideOverlay(c -> c.onEnrollResult(new Fingerprint("", 1, 1), 0)); } + @Test + public void testPowerPressForwardsAcquireMessage() throws RemoteException { + final FingerprintEnrollClient client = createClient(); + client.start(mCallback); + client.onPowerPressed(); + + verify(mClientMonitorCallbackConverter).onAcquired(anyInt(), + eq(FINGERPRINT_ACQUIRED_POWER_PRESSED), anyInt()); + } + private void showHideOverlay(Consumer<FingerprintEnrollClient> block) throws RemoteException { final FingerprintEnrollClient client = createClient(); diff --git a/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java b/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java index 9d82f1a90c77..8280fc6c962f 100644 --- a/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java +++ b/services/tests/servicestests/src/com/android/server/display/AutomaticBrightnessControllerTest.java @@ -82,6 +82,8 @@ public class AutomaticBrightnessControllerTest { @Mock BrightnessMappingStrategy mIdleBrightnessMappingStrategy; @Mock HysteresisLevels mAmbientBrightnessThresholds; @Mock HysteresisLevels mScreenBrightnessThresholds; + @Mock HysteresisLevels mAmbientBrightnessThresholdsIdle; + @Mock HysteresisLevels mScreenBrightnessThresholdsIdle; @Mock Handler mNoOpHandler; @Mock HighBrightnessModeController mHbmController; @Mock BrightnessThrottler mBrightnessThrottler; @@ -129,6 +131,7 @@ public class AutomaticBrightnessControllerTest { INITIAL_LIGHT_SENSOR_RATE, BRIGHTENING_LIGHT_DEBOUNCE_CONFIG, DARKENING_LIGHT_DEBOUNCE_CONFIG, RESET_AMBIENT_LUX_AFTER_WARMUP_CONFIG, mAmbientBrightnessThresholds, mScreenBrightnessThresholds, + mAmbientBrightnessThresholdsIdle, mScreenBrightnessThresholdsIdle, mContext, mHbmController, mBrightnessThrottler, mIdleBrightnessMappingStrategy, AMBIENT_LIGHT_HORIZON_SHORT, AMBIENT_LIGHT_HORIZON_LONG ); @@ -314,8 +317,9 @@ public class AutomaticBrightnessControllerTest { // Now let's do the same for idle mode mController.switchToIdleMode(); - // Called once for init, and once when switching - verify(mBrightnessMappingStrategy, times(2)).isForIdleMode(); + // Called once for init, and once when switching, + // setAmbientLux() is called twice and once in updateAutoBrightness() + verify(mBrightnessMappingStrategy, times(5)).isForIdleMode(); // Ensure, after switching, original BMS is not used anymore verifyNoMoreInteractions(mBrightnessMappingStrategy); diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java index 49879efe4b51..798604306b43 100644 --- a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java @@ -1704,8 +1704,8 @@ public class ManagedServicesTest extends UiServiceTestCase { } @Test - public void testInfoIsPermittedForProfile_notAllowed() { - when(mUserProfiles.canProfileUseBoundServices(anyInt())).thenReturn(false); + public void testInfoIsPermittedForProfile_notProfile() { + when(mUserProfiles.isProfileUser(anyInt())).thenReturn(false); IInterface service = mock(IInterface.class); when(service.asBinder()).thenReturn(mock(IBinder.class)); @@ -1714,12 +1714,12 @@ public class ManagedServicesTest extends UiServiceTestCase { services.registerSystemService(service, null, 10, 1000); ManagedServices.ManagedServiceInfo info = services.checkServiceTokenLocked(service); - assertFalse(info.isPermittedForProfile(0)); + assertTrue(info.isPermittedForProfile(0)); } @Test - public void testInfoIsPermittedForProfile_allows() { - when(mUserProfiles.canProfileUseBoundServices(anyInt())).thenReturn(true); + public void testInfoIsPermittedForProfile_profileAndDpmAllows() { + when(mUserProfiles.isProfileUser(anyInt())).thenReturn(true); when(mDpm.isNotificationListenerServicePermitted(anyString(), anyInt())).thenReturn(true); IInterface service = mock(IInterface.class); @@ -1734,6 +1734,22 @@ public class ManagedServicesTest extends UiServiceTestCase { } @Test + public void testInfoIsPermittedForProfile_profileAndDpmDenies() { + when(mUserProfiles.isProfileUser(anyInt())).thenReturn(true); + when(mDpm.isNotificationListenerServicePermitted(anyString(), anyInt())).thenReturn(false); + + IInterface service = mock(IInterface.class); + when(service.asBinder()).thenReturn(mock(IBinder.class)); + ManagedServices services = new TestManagedServices(getContext(), mLock, mUserProfiles, + mIpm, APPROVAL_BY_PACKAGE); + services.registerSystemService(service, null, 10, 1000); + ManagedServices.ManagedServiceInfo info = services.checkServiceTokenLocked(service); + info.component = new ComponentName("a","b"); + + assertFalse(info.isPermittedForProfile(0)); + } + + @Test public void testUserProfiles_canProfileUseBoundServices_managedProfile() { List<UserInfo> users = new ArrayList<>(); UserInfo profile = new UserInfo(ActivityManager.getCurrentUser(), "current", 0); @@ -1750,9 +1766,9 @@ public class ManagedServicesTest extends UiServiceTestCase { ManagedServices.UserProfiles profiles = new ManagedServices.UserProfiles(); profiles.updateCache(mContext); - assertTrue(profiles.canProfileUseBoundServices(ActivityManager.getCurrentUser())); - assertFalse(profiles.canProfileUseBoundServices(12)); - assertFalse(profiles.canProfileUseBoundServices(13)); + assertFalse(profiles.isProfileUser(ActivityManager.getCurrentUser())); + assertTrue(profiles.isProfileUser(12)); + assertTrue(profiles.isProfileUser(13)); } private void resetComponentsAndPackages() { diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java index bbd7695fc8cd..95e9f20011d0 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java @@ -2993,6 +2993,7 @@ public class ActivityRecordTests extends WindowTestsBase { // Add a decor insets provider window. final WindowState navbar = createNavBarWithProvidedInsets(squareDisplay); squareDisplay.getDisplayPolicy().updateDecorInsetsInfoIfNeeded(navbar); + squareDisplay.sendNewConfiguration(); final Task task = new TaskBuilder(mSupervisor).setDisplay(squareDisplay).build(); // create a fixed portrait activity diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java index 20b1120d7d3e..2fccd64bceca 100644 --- a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java @@ -220,10 +220,7 @@ public class ActivityTaskManagerServiceTests extends WindowTestsBase { // Check that changes are reported Configuration c = new Configuration(newDisp1.getRequestedOverrideConfiguration()); c.windowConfiguration.setBounds(new Rect(0, 0, 1000, 1300)); - newDisp1.onRequestedOverrideConfigurationChanged(c); - mAtm.mRootWindowContainer.ensureVisibilityAndConfig(null /* starting */, - newDisp1.mDisplayId, false /* markFrozenIfConfigChanged */, - false /* deferResume */); + newDisp1.performDisplayOverrideConfigUpdate(c); assertEquals(0, added.size()); assertEquals(1, changed.size()); assertEquals(0, removed.size()); diff --git a/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java index b5764f54ff92..4d71b30d71e2 100644 --- a/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java @@ -134,9 +134,9 @@ public class AppChangeTransitionTests extends WindowTestsBase { @Test public void testNoChangeOnOldDisplayWhenMoveDisplay() { - mDisplayContent.setWindowingMode(WINDOWING_MODE_FULLSCREEN); + mDisplayContent.getDefaultTaskDisplayArea().setWindowingMode(WINDOWING_MODE_FULLSCREEN); final DisplayContent dc1 = createNewDisplay(Display.STATE_ON); - dc1.setWindowingMode(WINDOWING_MODE_FREEFORM); + dc1.getDefaultTaskDisplayArea().setWindowingMode(WINDOWING_MODE_FREEFORM); setUpOnDisplay(dc1); assertEquals(WINDOWING_MODE_FREEFORM, mTask.getWindowingMode()); diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java index fd97d910e127..63f4f5f5b9fb 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java @@ -1066,6 +1066,7 @@ public class DisplayContentTests extends WindowTestsBase { final DisplayContent dc = createNewDisplay(); dc.getDisplayRotation().setFixedToUserRotation( IWindowManager.FIXED_TO_USER_ROTATION_DISABLED); + dc.getDefaultTaskDisplayArea().setWindowingMode(WINDOWING_MODE_FULLSCREEN); final int newOrientation = getRotatedOrientation(dc); final Task task = new TaskBuilder(mSupervisor) @@ -1125,6 +1126,7 @@ public class DisplayContentTests extends WindowTestsBase { IWindowManager.FIXED_TO_USER_ROTATION_ENABLED); dc.getDisplayRotation().setUserRotation( WindowManagerPolicy.USER_ROTATION_LOCKED, ROTATION_0); + dc.getDefaultTaskDisplayArea().setWindowingMode(WINDOWING_MODE_FULLSCREEN); final int newOrientation = getRotatedOrientation(dc); final Task task = new TaskBuilder(mSupervisor) @@ -2028,23 +2030,6 @@ public class DisplayContentTests extends WindowTestsBase { } @Test - public void testSetWindowingModeAtomicallyUpdatesWindoingModeAndDisplayWindowingMode() { - final DisplayContent dc = createNewDisplay(); - final Task rootTask = new TaskBuilder(mSupervisor) - .setDisplay(dc) - .build(); - doAnswer(invocation -> { - Object[] args = invocation.getArguments(); - final Configuration config = ((Configuration) args[0]); - assertEquals(config.windowConfiguration.getWindowingMode(), - config.windowConfiguration.getDisplayWindowingMode()); - return null; - }).when(rootTask).onConfigurationChanged(any()); - dc.setWindowingMode(WINDOWING_MODE_FREEFORM); - dc.setWindowingMode(WINDOWING_MODE_FULLSCREEN); - } - - @Test public void testForceDesktopMode() { mWm.mForceDesktopModeOnExternalDisplays = true; // Not applicable for default display diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java index 093be82c6128..c398a0a26016 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java @@ -110,7 +110,7 @@ public class DisplayWindowSettingsTests extends WindowTestsBase { mDisplayWindowSettings.applySettingsToDisplayLocked(mPrimaryDisplay); assertEquals(WindowConfiguration.WINDOWING_MODE_FULLSCREEN, - mPrimaryDisplay.getWindowingMode()); + mPrimaryDisplay.getDefaultTaskDisplayArea().getWindowingMode()); } @Test @@ -120,7 +120,7 @@ public class DisplayWindowSettingsTests extends WindowTestsBase { mDisplayWindowSettings.applySettingsToDisplayLocked(mPrimaryDisplay); assertEquals(WindowConfiguration.WINDOWING_MODE_FULLSCREEN, - mPrimaryDisplay.getWindowingMode()); + mPrimaryDisplay.getDefaultTaskDisplayArea().getWindowingMode()); } @Test @@ -131,7 +131,7 @@ public class DisplayWindowSettingsTests extends WindowTestsBase { mDisplayWindowSettings.applySettingsToDisplayLocked(mPrimaryDisplay); assertEquals(WindowConfiguration.WINDOWING_MODE_FULLSCREEN, - mPrimaryDisplay.getWindowingMode()); + mPrimaryDisplay.getDefaultTaskDisplayArea().getWindowingMode()); } @Test @@ -141,7 +141,8 @@ public class DisplayWindowSettingsTests extends WindowTestsBase { mDisplayWindowSettings.applySettingsToDisplayLocked(mPrimaryDisplay); - assertEquals(WINDOWING_MODE_FREEFORM, mPrimaryDisplay.getWindowingMode()); + assertEquals(WINDOWING_MODE_FREEFORM, + mPrimaryDisplay.getDefaultTaskDisplayArea().getWindowingMode()); } @Test @@ -154,7 +155,7 @@ public class DisplayWindowSettingsTests extends WindowTestsBase { mDisplayWindowSettings.updateSettingsForDisplay(mPrimaryDisplay); assertEquals(WindowConfiguration.WINDOWING_MODE_FREEFORM, - mPrimaryDisplay.getWindowingMode()); + mPrimaryDisplay.getDefaultTaskDisplayArea().getWindowingMode()); } @Test @@ -162,7 +163,7 @@ public class DisplayWindowSettingsTests extends WindowTestsBase { mDisplayWindowSettings.applySettingsToDisplayLocked(mSecondaryDisplay); assertEquals(WindowConfiguration.WINDOWING_MODE_FULLSCREEN, - mSecondaryDisplay.getWindowingMode()); + mSecondaryDisplay.getDefaultTaskDisplayArea().getWindowingMode()); } @Test @@ -172,7 +173,7 @@ public class DisplayWindowSettingsTests extends WindowTestsBase { mDisplayWindowSettings.applySettingsToDisplayLocked(mSecondaryDisplay); assertEquals(WindowConfiguration.WINDOWING_MODE_FULLSCREEN, - mSecondaryDisplay.getWindowingMode()); + mSecondaryDisplay.getDefaultTaskDisplayArea().getWindowingMode()); } @Test @@ -183,7 +184,7 @@ public class DisplayWindowSettingsTests extends WindowTestsBase { mDisplayWindowSettings.applySettingsToDisplayLocked(mSecondaryDisplay); assertEquals(WINDOWING_MODE_FREEFORM, - mSecondaryDisplay.getWindowingMode()); + mSecondaryDisplay.getDefaultTaskDisplayArea().getWindowingMode()); } @Test @@ -194,7 +195,7 @@ public class DisplayWindowSettingsTests extends WindowTestsBase { mDisplayWindowSettings.applySettingsToDisplayLocked(mSecondaryDisplay); assertEquals(WINDOWING_MODE_FREEFORM, - mSecondaryDisplay.getWindowingMode()); + mSecondaryDisplay.getDefaultTaskDisplayArea().getWindowingMode()); } @Test diff --git a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java index 68079f4a9ac5..601cf154b3bf 100644 --- a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java @@ -107,9 +107,10 @@ public class RootWindowContainerTests extends WindowTestsBase { } @Test - public void testUpdateDefaultDisplayWindowingModeOnSettingsRetrieved() { + public void testUpdateDefaultTaskDisplayAreaWindowingModeOnSettingsRetrieved() { assertEquals(WindowConfiguration.WINDOWING_MODE_FULLSCREEN, - mWm.getDefaultDisplayContentLocked().getWindowingMode()); + mWm.getDefaultDisplayContentLocked().getDefaultTaskDisplayArea() + .getWindowingMode()); mWm.mIsPc = true; mWm.mAtmService.mSupportsFreeformWindowManagement = true; @@ -117,7 +118,8 @@ public class RootWindowContainerTests extends WindowTestsBase { mWm.mRoot.onSettingsRetrieved(); assertEquals(WindowConfiguration.WINDOWING_MODE_FREEFORM, - mWm.getDefaultDisplayContentLocked().getWindowingMode()); + mWm.getDefaultDisplayContentLocked().getDefaultTaskDisplayArea() + .getWindowingMode()); } /** diff --git a/services/tests/wmtests/src/com/android/server/wm/SafeActivityOptionsTest.java b/services/tests/wmtests/src/com/android/server/wm/SafeActivityOptionsTest.java index 71118521acf5..e57ad5d9ff8c 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SafeActivityOptionsTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/SafeActivityOptionsTest.java @@ -17,9 +17,12 @@ package com.android.server.wm; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertSame; +import static org.mockito.Mockito.mock; import android.app.ActivityOptions; import android.platform.test.annotations.Presubmit; +import android.window.WindowContainerToken; import androidx.test.filters.MediumTest; @@ -43,4 +46,21 @@ public class SafeActivityOptionsTest { final ActivityOptions result = options.mergeActivityOptions(opts1, opts2); assertEquals(6, result.getLaunchDisplayId()); } + + @Test + public void test_selectiveCloneDisplayOptions() { + final WindowContainerToken token = mock(WindowContainerToken.class); + final int launchDisplayId = 5; + final int callerDisplayId = 6; + + final SafeActivityOptions clone = new SafeActivityOptions(ActivityOptions.makeBasic() + .setLaunchTaskDisplayArea(token) + .setLaunchDisplayId(launchDisplayId) + .setCallerDisplayId(callerDisplayId)) + .selectiveCloneDisplayOptions(); + + assertSame(clone.getOriginalOptions().getLaunchTaskDisplayArea(), token); + assertEquals(clone.getOriginalOptions().getLaunchDisplayId(), launchDisplayId); + assertEquals(clone.getOriginalOptions().getCallerDisplayId(), callerDisplayId); + } } diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java index 2f1cc2034bed..60d3f10bb103 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java @@ -676,7 +676,8 @@ public class SizeCompatTests extends WindowTestsBase { // The non-resizable activity should not be size compat because the display support // changing windowing mode from fullscreen to freeform. - mTask.mDisplayContent.setDisplayWindowingMode(WindowConfiguration.WINDOWING_MODE_FREEFORM); + mTask.mDisplayContent.getDefaultTaskDisplayArea() + .setWindowingMode(WindowConfiguration.WINDOWING_MODE_FREEFORM); mTask.setWindowingMode(WindowConfiguration.WINDOWING_MODE_FULLSCREEN); assertFalse(activity.shouldCreateCompatDisplayInsets()); // Activity should not be sandboxed. diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java index 6d514b20e831..ca817abeb1a4 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java +++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java @@ -345,7 +345,7 @@ public class SystemServicesTestRule implements TestRule { // Set default display to be in fullscreen mode. Devices with PC feature may start their // default display in freeform mode but some of tests in WmTests have implicit assumption on // that the default display is in fullscreen mode. - display.setDisplayWindowingMode(WINDOWING_MODE_FULLSCREEN); + display.getDefaultTaskDisplayArea().setWindowingMode(WINDOWING_MODE_FULLSCREEN); spyOn(display); final TaskDisplayArea taskDisplayArea = display.getDefaultTaskDisplayArea(); 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 c0759c110039..a6c5fd87c8d8 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java @@ -1775,7 +1775,7 @@ public class TaskLaunchParamsModifierTests extends WindowTestsBase { private TestDisplayContent createNewDisplayContent(int windowingMode) { final TestDisplayContent display = addNewDisplayContentAt(DisplayContent.POSITION_TOP); - display.setWindowingMode(windowingMode); + display.getDefaultTaskDisplayArea().setWindowingMode(windowingMode); display.setBounds(DISPLAY_BOUNDS); display.getConfiguration().densityDpi = DENSITY_DEFAULT; display.getConfiguration().orientation = ORIENTATION_LANDSCAPE; diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java index 9480ae81aede..76cd19be19b0 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java @@ -1256,7 +1256,8 @@ public class TaskTests extends WindowTestsBase { final Task task = getTestTask(); task.setHasBeenVisible(false); - task.getDisplayContent().setDisplayWindowingMode(WINDOWING_MODE_FREEFORM); + task.getDisplayContent().getDefaultTaskDisplayArea() + .setWindowingMode(WINDOWING_MODE_FREEFORM); task.getRootTask().setWindowingMode(WINDOWING_MODE_FULLSCREEN); task.setHasBeenVisible(true); @@ -1272,7 +1273,9 @@ public class TaskTests extends WindowTestsBase { final Task task = getTestTask(); task.setHasBeenVisible(false); - task.getDisplayContent().setWindowingMode(WindowConfiguration.WINDOWING_MODE_FREEFORM); + task.getDisplayContent() + .getDefaultTaskDisplayArea() + .setWindowingMode(WindowConfiguration.WINDOWING_MODE_FREEFORM); task.getRootTask().setWindowingMode(WINDOWING_MODE_FULLSCREEN); final DisplayContent oldDisplay = task.getDisplayContent(); @@ -1312,7 +1315,8 @@ public class TaskTests extends WindowTestsBase { final Task task = getTestTask(); task.setHasBeenVisible(false); - task.getDisplayContent().setDisplayWindowingMode(WINDOWING_MODE_FREEFORM); + task.getDisplayContent().getDefaultTaskDisplayArea() + .setWindowingMode(WINDOWING_MODE_FREEFORM); task.getRootTask().setWindowingMode(WINDOWING_MODE_PINNED); task.setHasBeenVisible(true); @@ -1329,7 +1333,8 @@ public class TaskTests extends WindowTestsBase { final Task task = new TaskBuilder(mSupervisor).setCreateActivity(true) .setCreateParentTask(true).build().getRootTask(); task.setHasBeenVisible(false); - task.getDisplayContent().setDisplayWindowingMode(WINDOWING_MODE_FREEFORM); + task.getDisplayContent().getDefaultTaskDisplayArea() + .setWindowingMode(WINDOWING_MODE_FREEFORM); task.getRootTask().setWindowingMode(WINDOWING_MODE_FULLSCREEN); final Task leafTask = createTaskInRootTask(task, 0 /* userId */); diff --git a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java index 8f186e40e201..8cf32baa49eb 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java @@ -19,6 +19,7 @@ package com.android.server.wm; import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; +import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_NOSENSOR; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET; import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS; @@ -31,7 +32,8 @@ import static android.view.WindowManager.TRANSIT_CHANGE; import static android.view.WindowManager.TRANSIT_CLOSE; import static android.view.WindowManager.TRANSIT_OPEN; import static android.view.WindowManager.TRANSIT_TO_BACK; -import static android.window.TransitionInfo.FLAG_IS_EMBEDDED; +import static android.window.TransitionInfo.FLAG_FILLS_TASK; +import static android.window.TransitionInfo.FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY; import static android.window.TransitionInfo.FLAG_IS_WALLPAPER; import static android.window.TransitionInfo.FLAG_SHOW_WALLPAPER; import static android.window.TransitionInfo.FLAG_TRANSLUCENT; @@ -727,7 +729,7 @@ public class TransitionTests extends WindowTestsBase { assertTrue(ime.mToken.inTransition()); assertTrue(task.inTransition()); assertTrue(asyncRotationController.isTargetToken(decorToken)); - assertTrue(asyncRotationController.shouldFreezeInsetsPosition(navBar)); + assertShouldFreezeInsetsPosition(asyncRotationController, statusBar, true); screenDecor.setOrientationChanging(false); // Status bar finishes drawing before the start transaction. Its fade-in animation will be @@ -742,6 +744,7 @@ public class TransitionTests extends WindowTestsBase { // The transaction is committed, so fade-in animation for status bar is consumed. transactionCommittedListener.onTransactionCommitted(); assertFalse(asyncRotationController.isTargetToken(statusBar.mToken)); + assertShouldFreezeInsetsPosition(asyncRotationController, navBar, false); // Navigation bar finishes drawing after the start transaction, so its fade-in animation // can execute directly. @@ -777,7 +780,7 @@ public class TransitionTests extends WindowTestsBase { final AsyncRotationController asyncRotationController = mDisplayContent.getAsyncRotationController(); assertNotNull(asyncRotationController); - assertTrue(asyncRotationController.shouldFreezeInsetsPosition(statusBar)); + assertShouldFreezeInsetsPosition(asyncRotationController, statusBar, true); statusBar.setOrientationChanging(true); player.startTransition(); @@ -823,7 +826,7 @@ public class TransitionTests extends WindowTestsBase { final AsyncRotationController asyncRotationController = mDisplayContent.getAsyncRotationController(); assertNotNull(asyncRotationController); - assertTrue(asyncRotationController.shouldFreezeInsetsPosition(statusBar)); + assertShouldFreezeInsetsPosition(asyncRotationController, statusBar, true); assertTrue(app.getTask().inTransition()); player.start(); @@ -858,6 +861,15 @@ public class TransitionTests extends WindowTestsBase { assertNull(mDisplayContent.getAsyncRotationController()); } + private static void assertShouldFreezeInsetsPosition(AsyncRotationController controller, + WindowState w, boolean freeze) { + if (TransitionController.SYNC_METHOD != BLASTSyncEngine.METHOD_BLAST) { + // Non blast sync should never freeze insets position. + freeze = false; + } + assertEquals(freeze, controller.shouldFreezeInsetsPosition(w)); + } + @Test public void testDeferRotationForTransientLaunch() { final TestTransitionPlayer player = registerTestTransitionPlayer(); @@ -1062,12 +1074,14 @@ public class TransitionTests extends WindowTestsBase { } @Test - public void testIsEmbeddedChange() { + public void testFlagInTaskWithEmbeddedActivity() { final Transition transition = createTestTransition(TRANSIT_OPEN); final ArrayMap<WindowContainer, Transition.ChangeInfo> changes = transition.mChanges; final ArraySet<WindowContainer> participants = transition.mParticipants; final Task task = createTask(mDisplayContent); + final ActivityRecord nonEmbeddedActivity = createActivityRecord(task); + assertFalse(nonEmbeddedActivity.isEmbedded()); final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run); mAtm.mTaskFragmentOrganizerController.registerOrganizer( ITaskFragmentOrganizer.Stub.asInterface(organizer.getOrganizerToken().asBinder())); @@ -1082,20 +1096,72 @@ public class TransitionTests extends WindowTestsBase { changes.put(embeddedTf, new Transition.ChangeInfo(true /* vis */, false /* exChg */)); changes.put(closingActivity, new Transition.ChangeInfo(true /* vis */, false /* exChg */)); changes.put(openingActivity, new Transition.ChangeInfo(false /* vis */, true /* exChg */)); + changes.put(nonEmbeddedActivity, new Transition.ChangeInfo(true /* vis */, + false /* exChg */)); // End states. closingActivity.mVisibleRequested = false; openingActivity.mVisibleRequested = true; + nonEmbeddedActivity.mVisibleRequested = false; participants.add(closingActivity); participants.add(openingActivity); + participants.add(nonEmbeddedActivity); + final ArrayList<WindowContainer> targets = Transition.calculateTargets( + participants, changes); + final TransitionInfo info = Transition.calculateTransitionInfo( + transition.mType, 0 /* flags */, targets, changes, mMockT); + + // All windows in the Task should have FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY because the Task + // contains embedded activity. + assertEquals(3, info.getChanges().size()); + assertTrue(info.getChanges().get(0).hasFlags(FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY)); + assertTrue(info.getChanges().get(1).hasFlags(FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY)); + assertTrue(info.getChanges().get(2).hasFlags(FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY)); + } + + @Test + public void testFlagFillsTask() { + final Transition transition = createTestTransition(TRANSIT_OPEN); + final ArrayMap<WindowContainer, Transition.ChangeInfo> changes = transition.mChanges; + final ArraySet<WindowContainer> participants = transition.mParticipants; + + final Task task = createTask(mDisplayContent); + // Set to multi-windowing mode in order to set bounds. + task.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW); + final Rect taskBounds = new Rect(0, 0, 500, 1000); + task.setBounds(taskBounds); + final ActivityRecord nonEmbeddedActivity = createActivityRecord(task); + final TaskFragmentOrganizer organizer = new TaskFragmentOrganizer(Runnable::run); + mAtm.mTaskFragmentOrganizerController.registerOrganizer( + ITaskFragmentOrganizer.Stub.asInterface(organizer.getOrganizerToken().asBinder())); + final TaskFragment embeddedTf = new TaskFragmentBuilder(mAtm) + .setParentTask(task) + .createActivityCount(1) + .setOrganizer(organizer) + .build(); + final ActivityRecord embeddedActivity = embeddedTf.getTopMostActivity(); + // Start states. + changes.put(task, new Transition.ChangeInfo(true /* vis */, false /* exChg */)); + changes.put(nonEmbeddedActivity, new Transition.ChangeInfo(true /* vis */, + false /* exChg */)); + changes.put(embeddedTf, new Transition.ChangeInfo(false /* vis */, true /* exChg */)); + // End states. + nonEmbeddedActivity.mVisibleRequested = false; + embeddedActivity.mVisibleRequested = true; + embeddedTf.setBounds(new Rect(0, 0, 500, 500)); + + participants.add(nonEmbeddedActivity); + participants.add(embeddedTf); final ArrayList<WindowContainer> targets = Transition.calculateTargets( participants, changes); final TransitionInfo info = Transition.calculateTransitionInfo( transition.mType, 0 /* flags */, targets, changes, mMockT); + // The embedded with bounds overridden should not have the flag. assertEquals(2, info.getChanges().size()); - assertTrue((info.getChanges().get(0).getFlags() & FLAG_IS_EMBEDDED) != 0); - assertTrue((info.getChanges().get(1).getFlags() & FLAG_IS_EMBEDDED) != 0); + assertFalse(info.getChanges().get(0).hasFlags(FLAG_FILLS_TASK)); + assertEquals(embeddedTf.getBounds(), info.getChanges().get(0).getEndAbsBounds()); + assertFalse(info.getChanges().get(1).hasFlags(FLAG_FILLS_TASK)); } @Test diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/GameAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/GameAppHelper.kt new file mode 100644 index 000000000000..d11ca4950d16 --- /dev/null +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/GameAppHelper.kt @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.wm.flicker.helpers + +import android.app.Instrumentation +import android.support.test.launcherhelper.ILauncherStrategy +import android.support.test.launcherhelper.LauncherStrategyFactory +import androidx.test.uiautomator.By +import androidx.test.uiautomator.Direction +import androidx.test.uiautomator.Until +import com.android.server.wm.flicker.testapp.ActivityOptions +import com.android.server.wm.traces.common.FlickerComponentName +import com.android.server.wm.traces.parser.toFlickerComponent +import com.android.server.wm.traces.parser.windowmanager.WindowManagerStateHelper + +class GameAppHelper @JvmOverloads constructor( + instr: Instrumentation, + launcherName: String = ActivityOptions.GAME_ACTIVITY_LAUNCHER_NAME, + component: FlickerComponentName = + ActivityOptions.GAME_ACTIVITY_COMPONENT_NAME.toFlickerComponent(), + launcherStrategy: ILauncherStrategy = + LauncherStrategyFactory.getInstance(instr).launcherStrategy, +) : StandardAppHelper(instr, launcherName, component, launcherStrategy) { + + /** + * Swipes down in the mock game app. + * + * @return true if the swipe operation is successful. + */ + fun swipeDown(): Boolean { + val gameView = uiDevice.wait( + Until.findObject(By.res(getPackage(), GAME_APP_VIEW_RES)), WAIT_TIME_MS) + require(gameView != null) { "Mock game app view not found." } + + val bound = gameView.getVisibleBounds() + return uiDevice.swipe( + bound.centerX(), bound.top, bound.centerX(), bound.centerY(), SWIPE_STEPS) + } + + /** + * Switches to a recent app by quick switch gesture. This function can be used in both portrait + * and landscape mode. + * + * @param wmHelper Helper used to get window region. + * @param direction UiAutomator Direction enum to indicate the swipe direction. + * + * @return true if the swipe operation is successful. + */ + fun switchToPreviousAppByQuickSwitchGesture( + wmHelper: WindowManagerStateHelper, + direction: Direction + ): Boolean { + val ratioForScreenBottom = 0.97 + val fullView = wmHelper.getWindowRegion(component) + require(!fullView.isEmpty) { "Target $component view not found." } + + val bound = fullView.bounds + val targetYPos = bound.bottom * ratioForScreenBottom + val endX = when (direction) { + Direction.LEFT -> bound.left + Direction.RIGHT -> bound.right + else -> { + throw IllegalStateException("Only left or right direction is allowed.") + } + } + return uiDevice.swipe( + bound.centerX(), targetYPos.toInt(), endX, targetYPos.toInt(), SWIPE_STEPS) + } + + /** + * Waits for view idel with timeout, then checkes the target object whether visible on screen. + * + * @param packageName The targe application's package name. + * @param identifier The resource id of the target object. + * @param timeout The timeout duration in milliseconds. + * + * @return true if the target object exists. + */ + @JvmOverloads + fun isTargetObjVisible( + packageName: String, + identifier: String, + timeout: Long = WAIT_TIME_MS + ): Boolean { + uiDevice.waitForIdle(timeout) + return uiDevice.hasObject(By.res(packageName, identifier)) + } + + companion object { + private const val GAME_APP_VIEW_RES = "container" + private const val WAIT_TIME_MS = 3_000L + private const val SWIPE_STEPS = 30 + } +} diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/MailAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/MailAppHelper.kt new file mode 100644 index 000000000000..3385784de8af --- /dev/null +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/MailAppHelper.kt @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.wm.flicker.helpers + +import android.app.Instrumentation +import android.support.test.launcherhelper.ILauncherStrategy +import android.support.test.launcherhelper.LauncherStrategyFactory +import androidx.test.uiautomator.By +import androidx.test.uiautomator.Direction +import androidx.test.uiautomator.UiObject2 +import androidx.test.uiautomator.Until +import com.android.server.wm.flicker.testapp.ActivityOptions +import com.android.server.wm.traces.common.FlickerComponentName +import com.android.server.wm.traces.parser.toFlickerComponent + +class MailAppHelper @JvmOverloads constructor( + instr: Instrumentation, + launcherName: String = ActivityOptions.MAIL_ACTIVITY_LAUNCHER_NAME, + component: FlickerComponentName = + ActivityOptions.MAIL_ACTIVITY_COMPONENT_NAME.toFlickerComponent(), + launcherStrategy: ILauncherStrategy = LauncherStrategyFactory + .getInstance(instr) + .launcherStrategy +) : StandardAppHelper(instr, launcherName, component, launcherStrategy) { + + fun openMail(rowIdx: Int) { + val rowSel = By.res(getPackage(), "mail_row_item_text") + .textEndsWith(String.format("%04d", rowIdx)) + var row: UiObject2? = null + for (i in 1..1000) { + row = uiDevice.wait(Until.findObject(rowSel), SHORT_WAIT_TIME_MS) + if (row != null) break + scrollDown() + } + require(row != null) {""} + row.click() + uiDevice.wait(Until.gone(By.res(getPackage(), MAIL_LIST_RES_ID)), FIND_TIMEOUT) + } + + fun scrollDown() { + val listView = waitForMailList() + listView.scroll(Direction.DOWN, 1.0f) + } + + fun waitForMailList(): UiObject2 { + var sel = By.res(getPackage(), MAIL_LIST_RES_ID).scrollable(true) + val ret = uiDevice.wait(Until.findObject(sel), FIND_TIMEOUT) + require(ret != null) {""} + return ret + } + + companion object { + private const val SHORT_WAIT_TIME_MS = 5000L + private const val MAIL_LIST_RES_ID = "mail_recycle_view" + } +} diff --git a/tests/FlickerTests/test-apps/flickerapp/AndroidManifest.xml b/tests/FlickerTests/test-apps/flickerapp/AndroidManifest.xml index 25216a3176cb..b8ef1954d5fc 100644 --- a/tests/FlickerTests/test-apps/flickerapp/AndroidManifest.xml +++ b/tests/FlickerTests/test-apps/flickerapp/AndroidManifest.xml @@ -173,5 +173,46 @@ <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> + <activity android:name=".GameActivity" + android:taskAffinity="com.android.server.wm.flicker.testapp.GameActivity" + android:immersive="true" + android:theme="@android:style/Theme.NoTitleBar" + android:configChanges="screenSize" + android:label="GameApp" + android:exported="true"> + <intent-filter> + <action android:name="android.intent.action.MAIN"/> + <category android:name="android.intent.category.LAUNCHER"/> + </intent-filter> + </activity> + <service + android:name=".AssistantInteractionSessionService" + android:exported="true" + android:permission="android.permission.BIND_VOICE_INTERACTION" /> + <service + android:name=".AssistantRecognitionService" + android:exported="true" + android:label="Test Voice Interaction Service"> + <intent-filter> + <action android:name="android.speech.RecognitionService" /> + <category android:name="android.intent.category.DEFAULT" /> + </intent-filter> + <meta-data + android:name="android.speech" + android:resource="@xml/recognition_service" /> + </service> + <service + android:name=".AssistantInteractionService" + android:exported="true" + android:label="Test Voice Interaction Service" + android:permission="android.permission.BIND_VOICE_INTERACTION"> + <intent-filter> + <action android:name="android.service.voice.VoiceInteractionService" /> + </intent-filter> + <meta-data + android:name="android.voice_interaction" + android:resource="@xml/interaction_service" /> + </service> </application> + <uses-permission android:name="android.permission.ACTIVITY_RECOGNITION" /> </manifest> diff --git a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_surfaceview.xml b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_surfaceview.xml new file mode 100644 index 000000000000..0b4693dec6e1 --- /dev/null +++ b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_surfaceview.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright 2018 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. +--> +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/container" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="@android:color/holo_orange_light"> + + <SurfaceView + android:id="@+id/surface_view" + android:layout_width="match_parent" + android:layout_height="match_parent"/> +</LinearLayout> diff --git a/tests/FlickerTests/test-apps/flickerapp/res/layout/assistant_session.xml b/tests/FlickerTests/test-apps/flickerapp/res/layout/assistant_session.xml new file mode 100644 index 000000000000..eb7f3074ebfb --- /dev/null +++ b/tests/FlickerTests/test-apps/flickerapp/res/layout/assistant_session.xml @@ -0,0 +1,26 @@ +<!-- + ~ 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. + --> + +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent"> + <FrameLayout + android:id="@+id/vis_frame" + android:layout_width="match_parent" + android:layout_height="300dp" + android:layout_gravity="bottom" + android:background="#37474F"/> +</FrameLayout> diff --git a/tests/FlickerTests/test-apps/flickerapp/res/xml/interaction_service.xml b/tests/FlickerTests/test-apps/flickerapp/res/xml/interaction_service.xml new file mode 100644 index 000000000000..2e661fbd3122 --- /dev/null +++ b/tests/FlickerTests/test-apps/flickerapp/res/xml/interaction_service.xml @@ -0,0 +1,20 @@ +<!-- + ~ 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. + --> + +<voice-interaction-service xmlns:android="http://schemas.android.com/apk/res/android" + android:recognitionService="com.android.server.wm.flicker.testapp.AssistantRecognitionService" + android:sessionService="com.android.server.wm.flicker.testapp.AssistantInteractionSessionService" + android:supportsAssist="true" /> diff --git a/tests/FlickerTests/test-apps/flickerapp/res/xml/recognition_service.xml b/tests/FlickerTests/test-apps/flickerapp/res/xml/recognition_service.xml new file mode 100644 index 000000000000..2e124982084f --- /dev/null +++ b/tests/FlickerTests/test-apps/flickerapp/res/xml/recognition_service.xml @@ -0,0 +1,17 @@ +<!-- + ~ 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. + --> + +<recognition-service xmlns:android="http://schemas.android.com/apk/res/android" /> diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityOptions.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityOptions.java index 6cda482dd30a..45a47303990c 100644 --- a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityOptions.java +++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityOptions.java @@ -87,4 +87,13 @@ public class ActivityOptions { public static final ComponentName NOTIFICATION_ACTIVITY_COMPONENT_NAME = new ComponentName(FLICKER_APP_PACKAGE, FLICKER_APP_PACKAGE + ".NotificationActivity"); + + public static final String MAIL_ACTIVITY_LAUNCHER_NAME = "MailActivity"; + public static final ComponentName MAIL_ACTIVITY_COMPONENT_NAME = new ComponentName( + FLICKER_APP_PACKAGE, FLICKER_APP_PACKAGE + ".MailActivity"); + + public static final String GAME_ACTIVITY_LAUNCHER_NAME = "GameApp"; + public static final ComponentName GAME_ACTIVITY_COMPONENT_NAME = + new ComponentName(FLICKER_APP_PACKAGE, + FLICKER_APP_PACKAGE + ".GameActivity"); } diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/AssistantInteractionService.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/AssistantInteractionService.java new file mode 100644 index 000000000000..d60143cdf40a --- /dev/null +++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/AssistantInteractionService.java @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.wm.flicker.testapp; + +import android.service.voice.VoiceInteractionService; + +public class AssistantInteractionService extends VoiceInteractionService { +} diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/AssistantInteractionSession.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/AssistantInteractionSession.java new file mode 100644 index 000000000000..d2c9b37704b8 --- /dev/null +++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/AssistantInteractionSession.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.wm.flicker.testapp; + +import android.content.Context; +import android.graphics.Color; +import android.os.Bundle; +import android.service.voice.VoiceInteractionSession; +import android.view.View; +import android.view.Window; + +public class AssistantInteractionSession extends VoiceInteractionSession { + + public AssistantInteractionSession(Context context) { + super(context); + } + + @Override + public void onCreate() { + Window window = getWindow().getWindow(); + if (window != null) { + window.getDecorView().setBackgroundColor(Color.TRANSPARENT); + + } + View rootView = getLayoutInflater().inflate(R.layout.assistant_session, null); + setContentView(rootView); + setUiEnabled(false); + } + + @Override + public void onShow(Bundle args, int showFlags) { + setUiEnabled(true); + } + + @Override + public void onHide() { + setUiEnabled(false); + } +} diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/AssistantInteractionSessionService.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/AssistantInteractionSessionService.java new file mode 100644 index 000000000000..4d6125c9a5d8 --- /dev/null +++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/AssistantInteractionSessionService.java @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.wm.flicker.testapp; + +import android.os.Bundle; +import android.service.voice.VoiceInteractionSession; +import android.service.voice.VoiceInteractionSessionService; + +public class AssistantInteractionSessionService extends VoiceInteractionSessionService { + @Override + public VoiceInteractionSession onNewSession(Bundle args) { + return new AssistantInteractionSession(this); + } +} diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/AssistantRecognitionService.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/AssistantRecognitionService.java new file mode 100644 index 000000000000..68aae4520fe9 --- /dev/null +++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/AssistantRecognitionService.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.wm.flicker.testapp; + +import android.content.Intent; +import android.speech.RecognitionService; + +public class AssistantRecognitionService extends RecognitionService { + @Override + protected void onStartListening(Intent recognizerIntent, Callback listener) { + + } + + @Override + protected void onCancel(Callback listener) { + + } + + @Override + protected void onStopListening(Callback listener) { + + } +} diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/GameActivity.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/GameActivity.java new file mode 100644 index 000000000000..ef75d4ddcdcd --- /dev/null +++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/GameActivity.java @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.wm.flicker.testapp; + +import android.app.Activity; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.PixelFormat; +import android.os.Bundle; +import android.view.SurfaceHolder; +import android.view.SurfaceView; + +import androidx.core.view.ViewCompat; +import androidx.core.view.WindowInsetsCompat; +import androidx.core.view.WindowInsetsControllerCompat; + +public class GameActivity extends Activity implements SurfaceHolder.Callback { + private SurfaceHolder mSurfaceHolder; + private SurfaceView mSurfaceView; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + setContentView(R.layout.activity_surfaceview); + + mSurfaceView = (SurfaceView) findViewById(R.id.surface_view); + mSurfaceView.setZOrderOnTop(true); + mSurfaceHolder = mSurfaceView.getHolder(); + mSurfaceHolder.setFormat(PixelFormat.TRANSPARENT); + mSurfaceHolder.addCallback(this); + } + + @Override + public void surfaceCreated(SurfaceHolder holder) { + hideSystemBars(); + } + + @Override + public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { + Canvas canvas = holder.lockCanvas(); + canvas.drawColor(Color.BLUE); + holder.unlockCanvasAndPost(canvas); + } + + @Override + public void surfaceDestroyed(SurfaceHolder holder) { + } + + private void hideSystemBars() { + WindowInsetsControllerCompat windowInsetsController = + ViewCompat.getWindowInsetsController(getWindow().getDecorView()); + if (windowInsetsController == null) { + return; + } + // Configure the behavior of the hidden system bars. + windowInsetsController.setSystemBarsBehavior( + WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE + ); + // Hide both the status bar and the navigation bar. + windowInsetsController.hide(WindowInsetsCompat.Type.systemBars()); + } +} |